Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Loading...
Loading
Contract Name:
SFFLRegistryRollup
Compiler Version
v0.8.12+commit.f00d7308
Optimization Enabled:
Yes with 100 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; import {Initializable} from "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol"; import {OwnableUpgradeable} from "@openzeppelin-upgrades/contracts/access/OwnableUpgradeable.sol"; import {Pausable} from "@eigenlayer/contracts/permissions/Pausable.sol"; import {IPauserRegistry} from "@eigenlayer/contracts/interfaces/IPauserRegistry.sol"; import {BN254} from "eigenlayer-middleware/src/libraries/BN254.sol"; import {SFFLRegistryBase} from "../base/SFFLRegistryBase.sol"; import {StateRootUpdate} from "../base/message/StateRootUpdate.sol"; import {OperatorSetUpdate} from "../base/message/OperatorSetUpdate.sol"; import {RollupOperators} from "../base/utils/RollupOperators.sol"; /** * @title SFFL registry for rollups / external networks * @notice Contract that centralizes the AVS operator set copy management, * which is based on agreements such as the state root updates, as well as * state root updates themselves. Differently from the Ethereum AVS contracts, * the rollup contract heavily assumes a one-quorum operator set and can only * prove agreements based on the current operator set state */ contract SFFLRegistryRollup is Initializable, OwnableUpgradeable, Pausable, SFFLRegistryBase { using BN254 for BN254.G1Point; using RollupOperators for RollupOperators.OperatorSet; using OperatorSetUpdate for OperatorSetUpdate.Message; using StateRootUpdate for StateRootUpdate.Message; /** * @notice Index for flag that pauses operator set updates */ uint8 public constant PAUSED_UPDATE_OPERATOR_SET = 0; /** * @notice Index for flag that pauses state root updates */ uint8 public constant PAUSED_UPDATE_STATE_ROOT = 1; /** * @dev Operator set used for agreements */ RollupOperators.OperatorSet internal _operatorSet; /** * @notice Next operator set update message ID */ uint64 public nextOperatorUpdateId; /** * @notice Aggregator address, used for the initial operator set setup */ address public aggregator; modifier onlyAggregator() { require(msg.sender == aggregator, "Sender is not aggregator"); _; } constructor() { _disableInitializers(); } /** * @notice Initializes the contract * @param quorumThreshold Quorum threshold, based on THRESHOLD_DENOMINATOR * @param initialOwner Owner address * @param _aggregator Aggregator address * @param _pauserRegistry Pauser registry address */ function initialize( uint128 quorumThreshold, address initialOwner, address _aggregator, IPauserRegistry _pauserRegistry ) public initializer { _initializePauser(_pauserRegistry, UNPAUSE_ALL); _transferOwnership(initialOwner); _operatorSet.setQuorumThreshold(quorumThreshold); aggregator = _aggregator; } /** * @notice Sets the initial operator set * @param operators Initial operator list * @param _nextOperatorUpdateId Starting next operator update message ID */ function setInitialOperatorSet(RollupOperators.Operator[] memory operators, uint64 _nextOperatorUpdateId) external onlyAggregator { require(_operatorSet.totalWeight == 0, "Operator set already initialized"); _operatorSet.update(operators); nextOperatorUpdateId = _nextOperatorUpdateId; } /** * @notice Updates the operator set through an operator set update message * @param message Operator set update message * @param signatureInfo BLS aggregated signature info */ function updateOperatorSet( OperatorSetUpdate.Message calldata message, RollupOperators.SignatureInfo calldata signatureInfo ) external onlyWhenNotPaused(PAUSED_UPDATE_OPERATOR_SET) { require(message.id == nextOperatorUpdateId, "Wrong message ID"); require(_operatorSet.verifyCalldata(message.hashCalldata(), signatureInfo), "Quorum not met"); nextOperatorUpdateId = message.id + 1; _operatorSet.update(message.operators); } /** * @notice Updates a rollup's state root for a block height through a state * root update message * @param message State root update message * @param signatureInfo BLS aggregated signature info */ function updateStateRoot( StateRootUpdate.Message calldata message, RollupOperators.SignatureInfo calldata signatureInfo ) public onlyWhenNotPaused(PAUSED_UPDATE_STATE_ROOT) { require(_operatorSet.verifyCalldata(message.hashCalldata(), signatureInfo), "Quorum not met"); _pushStateRoot(message.rollupId, message.blockHeight, message.stateRoot); } /** * Updates a rollup's state root based on the AVS operators agreement * @param message State root update message * @param encodedSignatureInfo Encoded BLS aggregated signature info */ function _updateStateRoot(StateRootUpdate.Message calldata message, bytes calldata encodedSignatureInfo) internal override { RollupOperators.SignatureInfo calldata signatureInfo; assembly { signatureInfo := encodedSignatureInfo.offset } updateStateRoot(message, signatureInfo); } /** * @notice Sets the operator set quorum weight threshold * @param newQuorumThreshold New quorum threshold, based on * THRESHOLD_DENOMINATOR */ function setQuorumThreshold(uint128 newQuorumThreshold) external onlyOwner { return _operatorSet.setQuorumThreshold(newQuorumThreshold); } /** * @notice Gets an operator's weight * @param pubkeyHash Operator pubkey hash * @return Operator weight */ function getOperatorWeight(bytes32 pubkeyHash) external view returns (uint128) { return _operatorSet.getOperatorWeight(pubkeyHash); } /** * @notice Gets the operator set aggregate public key * @return Operator set aggregate public key */ function getApk() external view returns (BN254.G1Point memory) { return _operatorSet.apk; } /** * @notice Gets the operator set total weight * @return Operator set total weight */ function getTotalWeight() external view returns (uint128) { return _operatorSet.totalWeight; } /** * @notice Gets the operator set weight threshold * @return Operator set weight threshold */ function getQuorumThreshold() external view returns (uint128) { return _operatorSet.quorumThreshold; } /** * @notice Gets the operator set quorum weight threshold denominator * @return Operator set weight threshold denominator */ function THRESHOLD_DENOMINATOR() external pure returns (uint128) { return RollupOperators.THRESHOLD_DENOMINATOR; } }
// 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 // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _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 anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing 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); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity =0.8.12; import "../interfaces/IPausable.sol"; /** * @title Adds pausability to a contract, with pausing & unpausing controlled by the `pauser` and `unpauser` of a PauserRegistry contract. * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service * @notice Contracts that inherit from this contract may define their own `pause` and `unpause` (and/or related) functions. * These functions should be permissioned as "onlyPauser" which defers to a `PauserRegistry` for determining access control. * @dev Pausability is implemented using a uint256, which allows up to 256 different single bit-flags; each bit can potentially pause different functionality. * Inspiration for this was taken from the NearBridge design here https://etherscan.io/address/0x3FEFc5A4B1c02f21cBc8D3613643ba0635b9a873#code. * For the `pause` and `unpause` functions we've implemented, if you pause, you can only flip (any number of) switches to on/1 (aka "paused"), and if you unpause, * you can only flip (any number of) switches to off/0 (aka "paused"). * If you want a pauseXYZ function that just flips a single bit / "pausing flag", it will: * 1) 'bit-wise and' (aka `&`) a flag with the current paused state (as a uint256) * 2) update the paused state to this new value * @dev We note as well that we have chosen to identify flags by their *bit index* as opposed to their numerical value, so, e.g. defining `DEPOSITS_PAUSED = 3` * indicates specifically that if the *third bit* of `_paused` is flipped -- i.e. it is a '1' -- then deposits should be paused */ contract Pausable is IPausable { /// @notice Address of the `PauserRegistry` contract that this contract defers to for determining access control (for pausing). IPauserRegistry public pauserRegistry; /// @dev whether or not the contract is currently paused uint256 private _paused; uint256 internal constant UNPAUSE_ALL = 0; uint256 internal constant PAUSE_ALL = type(uint256).max; /// @notice modifier onlyPauser() { require(pauserRegistry.isPauser(msg.sender), "msg.sender is not permissioned as pauser"); _; } modifier onlyUnpauser() { require(msg.sender == pauserRegistry.unpauser(), "msg.sender is not permissioned as unpauser"); _; } /// @notice Throws if the contract is paused, i.e. if any of the bits in `_paused` is flipped to 1. modifier whenNotPaused() { require(_paused == 0, "Pausable: contract is paused"); _; } /// @notice Throws if the `indexed`th bit of `_paused` is 1, i.e. if the `index`th pause switch is flipped. modifier onlyWhenNotPaused(uint8 index) { require(!paused(index), "Pausable: index is paused"); _; } /// @notice One-time function for setting the `pauserRegistry` and initializing the value of `_paused`. function _initializePauser(IPauserRegistry _pauserRegistry, uint256 initPausedStatus) internal { require( address(pauserRegistry) == address(0) && address(_pauserRegistry) != address(0), "Pausable._initializePauser: _initializePauser() can only be called once" ); _paused = initPausedStatus; emit Paused(msg.sender, initPausedStatus); _setPauserRegistry(_pauserRegistry); } /** * @notice This function is used to pause an EigenLayer contract's functionality. * It is permissioned to the `pauser` address, which is expected to be a low threshold multisig. * @param newPausedStatus represents the new value for `_paused` to take, which means it may flip several bits at once. * @dev This function can only pause functionality, and thus cannot 'unflip' any bit in `_paused` from 1 to 0. */ function pause(uint256 newPausedStatus) external onlyPauser { // verify that the `newPausedStatus` does not *unflip* any bits (i.e. doesn't unpause anything, all 1 bits remain) require((_paused & newPausedStatus) == _paused, "Pausable.pause: invalid attempt to unpause functionality"); _paused = newPausedStatus; emit Paused(msg.sender, newPausedStatus); } /** * @notice Alias for `pause(type(uint256).max)`. */ function pauseAll() external onlyPauser { _paused = type(uint256).max; emit Paused(msg.sender, type(uint256).max); } /** * @notice This function is used to unpause an EigenLayer contract's functionality. * It is permissioned to the `unpauser` address, which is expected to be a high threshold multisig or governance contract. * @param newPausedStatus represents the new value for `_paused` to take, which means it may flip several bits at once. * @dev This function can only unpause functionality, and thus cannot 'flip' any bit in `_paused` from 0 to 1. */ function unpause(uint256 newPausedStatus) external onlyUnpauser { // verify that the `newPausedStatus` does not *flip* any bits (i.e. doesn't pause anything, all 0 bits remain) require( ((~_paused) & (~newPausedStatus)) == (~_paused), "Pausable.unpause: invalid attempt to pause functionality" ); _paused = newPausedStatus; emit Unpaused(msg.sender, newPausedStatus); } /// @notice Returns the current paused status as a uint256. function paused() public view virtual returns (uint256) { return _paused; } /// @notice Returns 'true' if the `indexed`th bit of `_paused` is 1, and 'false' otherwise function paused(uint8 index) public view virtual returns (bool) { uint256 mask = 1 << index; return ((_paused & mask) == mask); } /// @notice Allows the unpauser to set a new pauser registry function setPauserRegistry(IPauserRegistry newPauserRegistry) external onlyUnpauser { _setPauserRegistry(newPauserRegistry); } /// internal function for setting pauser registry function _setPauserRegistry(IPauserRegistry newPauserRegistry) internal { require( address(newPauserRegistry) != address(0), "Pausable._setPauserRegistry: newPauserRegistry cannot be the zero address" ); emit PauserRegistrySet(pauserRegistry, newPauserRegistry); pauserRegistry = newPauserRegistry; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[48] private __gap; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; /** * @title Interface for the `PauserRegistry` contract. * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service */ interface IPauserRegistry { event PauserStatusChanged(address pauser, bool canPause); event UnpauserChanged(address previousUnpauser, address newUnpauser); /// @notice Mapping of addresses to whether they hold the pauser role. function isPauser(address pauser) external view returns (bool); /// @notice Unique address that holds the unpauser role. Capable of changing *both* the pauser and unpauser addresses. function unpauser() external view returns (address); }
// 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.12; import {Lib_AddressResolver} from "@eth-optimism/contracts/libraries/resolver/Lib_AddressResolver.sol"; import {Lib_OVMCodec} from "@eth-optimism/contracts/libraries/codec/Lib_OVMCodec.sol"; import {Lib_SecureMerkleTrie} from "@eth-optimism/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; import {Lib_RLPReader} from "@eth-optimism/contracts/libraries/rlp/Lib_RLPReader.sol"; import {StateRootUpdate} from "../base/message/StateRootUpdate.sol"; /** * @title SFFL registry base implementation * @notice Base implementation for all SFFL contracts in any chain, including * state root storage utilities and storage verification through the trusted * roots. * @dev This base implementation expects `_pushStateRoot` to be called by the * children contracts. This should ideally be done only through state root * update messages, and after verifying its agreement. */ abstract contract SFFLRegistryBase { /** * @dev Maps rollupId => blockHeight => stateRoot */ mapping(uint32 => mapping(uint64 => bytes32)) internal _stateRootBuffers; /** * @notice Emitted when a rollup's state root is updated * @param rollupId Pre-defined rollup ID * @param blockHeight Rollup block height * @param stateRoot Rollup state root at blockHeight */ event StateRootUpdated(uint32 indexed rollupId, uint64 indexed blockHeight, bytes32 stateRoot); /** * @notice Gets a state root for a rollup in a specific block height * @dev Does not fail if it's empty, should be checked for zeroes * @param rollupId Pre-defined rollup ID * @param blockHeight Rollup block height * @return Rollup state root, or 0 if unset */ function getStateRoot(uint32 rollupId, uint64 blockHeight) external view returns (bytes32) { return _stateRootBuffers[rollupId][blockHeight]; } struct ProofParams { address target; bytes32 storageKey; bytes stateTrieWitness; bytes storageTrieWitness; } /** * @notice Gets a storage key value based on a rollup's state root in a block * @param message State root update message * @param proofParams Storage proof parameters * @param agreement AVS operators agreement info * @return Verified storage value */ function updateAndGetStorageValue( StateRootUpdate.Message calldata message, ProofParams calldata proofParams, bytes calldata agreement ) external returns (bytes32) { require( message.nearDaTransactionId != bytes32(0) && message.nearDaCommitment != bytes32(0), "Empty NEAR DA commitment" ); bytes32 stateRoot = _stateRootBuffers[message.rollupId][message.blockHeight]; if (stateRoot == bytes32(0)) { require(agreement.length != 0, "Empty agreement"); _updateStateRoot(message, agreement); } return getStorageValue(message, proofParams); } /** * @notice Gets a storage key value based on a rollup's state root in a block * @param message State root update message * @param proofParams Storage proof parameters * @return Verified storage value */ function getStorageValue(StateRootUpdate.Message calldata message, ProofParams calldata proofParams) public view returns (bytes32) { bytes32 stateRoot = _stateRootBuffers[message.rollupId][message.blockHeight]; require(stateRoot == message.stateRoot, "Mismatching state roots"); return _getStorageValue( proofParams.target, proofParams.storageKey, stateRoot, proofParams.stateTrieWitness, proofParams.storageTrieWitness ); } /** * @notice Gets a storage slot value based on a state root * @dev Based on: https://github.com/ensdomains/arb-resolver/blob/a2ee680e4a62bb5a3f22fd9cfc4a1863504144d2/packages/contracts/contracts/l1/ArbitrumResolverStub.sol#L167C1-L194C1 * @param target Address of the account * @param slot Storage slot / key * @param stateRoot Network state root * @param stateTrieWitness Witness for the state trie * @param storageTrieWitness Witness for the storage trie * @return Retrieved storage value padded to 32 bytes */ function _getStorageValue( address target, bytes32 slot, bytes32 stateRoot, bytes memory stateTrieWitness, bytes memory storageTrieWitness ) internal pure returns (bytes32) { (bool exists, bytes memory encodedResolverAccount) = Lib_SecureMerkleTrie.get(abi.encodePacked(target), stateTrieWitness, stateRoot); require(exists, "Account does not exist"); Lib_OVMCodec.EVMAccount memory account = Lib_OVMCodec.decodeEVMAccount(encodedResolverAccount); (bool storageExists, bytes memory retrievedValue) = Lib_SecureMerkleTrie.get(abi.encodePacked(slot), storageTrieWitness, account.storageRoot); require(storageExists, "Storage value does not exist"); return _toBytes32PadLeft(Lib_RLPReader.readBytes(retrievedValue)); } /** * Updates a rollup's state root based on the AVS operators agreement * @param message State root update message * @param agreement AVS operators agreement info */ function _updateStateRoot(StateRootUpdate.Message calldata message, bytes calldata agreement) internal virtual; /** * @dev Simple utility to pad a bytes into a bytes32. * Based on: https://github.com/ensdomains/arb-resolver/blob/a2ee680e4a62bb5a3f22fd9cfc4a1863504144d2/packages/contracts/contracts/l1/ArbitrumResolverStub.sol#L196C1-L208C1 * @param _bytes Byte array, should be 32 bytes or smaller */ function _toBytes32PadLeft(bytes memory _bytes) internal pure returns (bytes32) { bytes32 ret; uint256 len = _bytes.length <= 32 ? _bytes.length : 32; assembly { ret := shr(mul(sub(32, len), 8), mload(add(_bytes, 32))) } return ret; } /** * @dev Stores the state root for a rollup in a specific block height * @param rollupId Pre-defined rollup ID * @param blockHeight Rollup block height * @param stateRoot Rollup state root at blockHeight */ function _pushStateRoot(uint32 rollupId, uint64 blockHeight, bytes32 stateRoot) internal { _stateRootBuffers[rollupId][blockHeight] = stateRoot; emit StateRootUpdated(rollupId, blockHeight, stateRoot); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; /** * @title SFFL state root update message library * @notice Represents the message passed to update state roots in various * chains and related utilities * @dev These messages include a rollup ID, which is a pre-defined ID for a * rollup, the rollup's block height and its state root, as well as the NEAR * DA transaction ID and commitment for the block submission. In case of * messages that do not correspond to NEAR DA data, both these fields must be * `bytes32(0)`. * The hashes of these messages should be signed by the SFFL operators through * their BLS private key */ library StateRootUpdate { struct Message { uint32 rollupId; uint64 blockHeight; uint64 timestamp; bytes32 nearDaTransactionId; bytes32 nearDaCommitment; bytes32 stateRoot; } bytes32 internal constant STATE_ROOT_UPDATE_HASH_PREFIX = keccak256("SFFL::StateRootUpdateMessage"); /** * @notice Hashes a state root update message * @param message Message structured data * @return Message hash */ function hashCalldata(Message calldata message) internal pure returns (bytes32) { return keccak256(abi.encode(STATE_ROOT_UPDATE_HASH_PREFIX, keccak256(abi.encode(message)))); } /** * @notice Hashes a state root update message * @param message Message structured data * @return Message hash */ function hash(Message memory message) internal pure returns (bytes32) { return keccak256(abi.encode(STATE_ROOT_UPDATE_HASH_PREFIX, keccak256(abi.encode(message)))); } /** * @notice Gets a state root update index * @dev This is linked to the byte size of Message.blockHeight and * Message.rollupId. This MUST be updated if any of those types is changed. * @param message Message structured data * @return Message index */ function indexCalldata(Message calldata message) internal pure returns (bytes32) { return bytes32(uint256(message.blockHeight) | (uint256(message.rollupId) << 64)); } /** * @notice Gets a state root update index * @dev This is linked to the byte size of Message.blockHeight and * Message.rollupId. This MUST be updated if any of those types is changed. * @param message Message structured data * @return Message index */ function index(Message memory message) internal pure returns (bytes32) { return bytes32(uint256(message.blockHeight) | (uint256(message.rollupId) << 64)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; import {RollupOperators} from "../utils/RollupOperators.sol"; /** * @title SFFL operator set update message library * @notice Represents the message passed to update operator set copies in * various chains and related utilities. * @dev These messages include a sequential ID and an operator list. The * operators should be simply set based on this list, i.e. creating, updating * and removing an operator is effectively the same operation. */ library OperatorSetUpdate { struct Message { uint64 id; uint64 timestamp; RollupOperators.Operator[] operators; } bytes32 internal constant OPERATOR_SET_UPDATE_HASH_PREFIX = keccak256("SFFL::OperatorSetUpdateMessage"); /** * @notice Hashes an operator set update message * @param message Message structured data * @return Message hash */ function hashCalldata(Message calldata message) internal pure returns (bytes32) { return keccak256(abi.encode(OPERATOR_SET_UPDATE_HASH_PREFIX, keccak256(abi.encode(message)))); } /** * @notice Hashes an operator set update message * @param message Message structured data * @return Message hash */ function hash(Message memory message) internal pure returns (bytes32) { return keccak256(abi.encode(OPERATOR_SET_UPDATE_HASH_PREFIX, keccak256(abi.encode(message)))); } /** * @notice Gets a state root update index * @dev This is linked to the byte size of Message.id. This MUST be updated * if the Message.id type is changed. * @param message Message structured data * @return Message index */ function indexCalldata(Message calldata message) internal pure returns (bytes32) { return bytes32(uint256(message.id)); } /** * @notice Gets a state root update index * @dev This is linked to the byte size of Message.id. This MUST be updated * if the Message.id type is changed. * @return Message index */ function index(Message memory message) internal pure returns (bytes32) { return bytes32(uint256(message.id)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; import {BN254} from "eigenlayer-middleware/src/libraries/BN254.sol"; /** * @title Operator set utilities * @notice Utilities for SFFL's rollups operator set copy. Each rollup has an * operator set which is periodically updated by the AVS, and is used to * validate agreements on state root updates * @dev The operator set is an alternative representation of the AVS' original * operator set, as it assumes a one-quorum one-weight based voting */ library RollupOperators { using BN254 for BN254.G1Point; /** * @dev Denominator for quorum weight thresholds */ uint128 internal constant THRESHOLD_DENOMINATOR = 100; /** * @dev Gas for checking pairing equality on ecpairing call. Based on * Eigenlayer's BLSSignatureChecker */ uint256 internal constant PAIRING_EQUALITY_CHECK_GAS = 120000; struct Operator { BN254.G1Point pubkey; uint128 weight; } struct OperatorSet { mapping(bytes32 => uint128) pubkeyHashToWeight; BN254.G1Point apk; uint128 totalWeight; uint128 quorumThreshold; } struct SignatureInfo { BN254.G1Point[] nonSignerPubkeys; BN254.G2Point apkG2; BN254.G1Point sigma; } /** * @notice Emitted when an operator is updated * @param pubkeyHash Hash of the BLS pubkey * @param weight Operator weight */ event OperatorUpdated(bytes32 indexed pubkeyHash, uint128 weight); /** * @notice Emitted when the quorum weight threshold is updated * @param newQuorumThreshold New quorum weight threshold, based on * THRESHOLD_DENOMINATOR */ event QuorumThresholdUpdated(uint128 indexed newQuorumThreshold); /** * @notice Sets the weight threshold for agreement validations * @param self Operator set * @param quorumThreshold New quorum weight threshold, based on * THRESHOLD_DENOMINATOR */ function setQuorumThreshold(OperatorSet storage self, uint128 quorumThreshold) internal { require(quorumThreshold <= THRESHOLD_DENOMINATOR, "Quorum threshold greater than denominator"); self.quorumThreshold = quorumThreshold; emit QuorumThresholdUpdated(quorumThreshold); } /** * @notice Gets an operator's weight * @param self Operator set * @param pubkeyHash Operator pubkey hash * @return Operator weight */ function getOperatorWeight(OperatorSet storage self, bytes32 pubkeyHash) internal view returns (uint128) { return self.pubkeyHashToWeight[pubkeyHash]; } /** * @notice Updates the operator set operators, effectively overwriting set * operators * @param self Operator set * @param operators Operators to be overwritten */ function update(OperatorSet storage self, Operator[] memory operators) internal { Operator memory operator; BN254.G1Point memory newApk = self.apk; uint128 newTotalWeight = self.totalWeight; for (uint256 i = 0; i < operators.length; i++) { operator = operators[i]; bytes32 pubkeyHash = operator.pubkey.hashG1Point(); uint128 currentWeight = self.pubkeyHashToWeight[pubkeyHash]; require(operator.weight != currentWeight, "Operator is up to date"); newTotalWeight = newTotalWeight - currentWeight + operator.weight; self.pubkeyHashToWeight[pubkeyHash] = operator.weight; if (currentWeight == 0) { newApk = newApk.plus(operator.pubkey); } else if (operator.weight == 0) { newApk = newApk.plus(operator.pubkey.negate()); } emit OperatorUpdated(pubkeyHash, operator.weight); } self.totalWeight = newTotalWeight; self.apk = newApk; } /** * @notice Verifies an agreement * @dev This fails if the agreement is invalid, as opposed to returning * `false` * @param self Operator set * @param msgHash Message hash, which is the signed value * @param signatureInfo BLS aggregated signature info * @return Whether the agreement passed quorum or not */ function verifyCalldata(OperatorSet storage self, bytes32 msgHash, SignatureInfo calldata signatureInfo) internal view returns (bool) { BN254.G1Point memory apk = BN254.G1Point(0, 0); uint256 weight = self.totalWeight; require(weight != 0, "Operator set was not initialized"); bytes32[] memory nonSignerPubkeyHashes = new bytes32[](signatureInfo.nonSignerPubkeys.length); for (uint256 i = 0; i < signatureInfo.nonSignerPubkeys.length; i++) { nonSignerPubkeyHashes[i] = signatureInfo.nonSignerPubkeys[i].hashG1Point(); if (i != 0) { require(uint256(nonSignerPubkeyHashes[i]) > uint256(nonSignerPubkeyHashes[i - 1]), "Pubkeys not sorted"); } uint256 operatorWeight = self.pubkeyHashToWeight[nonSignerPubkeyHashes[i]]; require(operatorWeight != 0, "Operator has zero weight"); apk = apk.plus(signatureInfo.nonSignerPubkeys[i]); weight -= operatorWeight; } apk = self.apk.plus(apk.negate()); (bool pairingSuccessful, bool signatureIsValid) = trySignatureAndApkVerification(msgHash, apk, signatureInfo.apkG2, signatureInfo.sigma); require(pairingSuccessful, "Pairing precompile call failed"); require(signatureIsValid, "Signature is invalid"); return weight >= (self.totalWeight * self.quorumThreshold) / THRESHOLD_DENOMINATOR; } /** * @dev Tries verifying a BLS aggregate signature * @param apk Expected G1 public key * @param apkG2 Provided G2 public key * @param sigma G1 point signature * @return pairingSuccessful Whether the inner ecpairing call was successful * @return signatureIsValid Whether the signature is valid */ function trySignatureAndApkVerification( bytes32 msgHash, BN254.G1Point memory apk, BN254.G2Point memory apkG2, BN254.G1Point memory sigma ) private view returns (bool pairingSuccessful, bool signatureIsValid) { uint256 gamma = uint256( keccak256( abi.encodePacked( msgHash, apk.X, apk.Y, apkG2.X[0], apkG2.X[1], apkG2.Y[0], apkG2.Y[1], sigma.X, sigma.Y ) ) ) % BN254.FR_MODULUS; (pairingSuccessful, signatureIsValid) = BN254.safePairing( sigma.plus(apk.scalar_mul(gamma)), BN254.negGeneratorG2(), BN254.hashToG1(msgHash).plus(BN254.generatorG1().scalar_mul(gamma)), apkG2, PAIRING_EQUALITY_CHECK_GAS ); } }
// 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); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; import "../interfaces/IPauserRegistry.sol"; /** * @title Adds pausability to a contract, with pausing & unpausing controlled by the `pauser` and `unpauser` of a PauserRegistry contract. * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service * @notice Contracts that inherit from this contract may define their own `pause` and `unpause` (and/or related) functions. * These functions should be permissioned as "onlyPauser" which defers to a `PauserRegistry` for determining access control. * @dev Pausability is implemented using a uint256, which allows up to 256 different single bit-flags; each bit can potentially pause different functionality. * Inspiration for this was taken from the NearBridge design here https://etherscan.io/address/0x3FEFc5A4B1c02f21cBc8D3613643ba0635b9a873#code. * For the `pause` and `unpause` functions we've implemented, if you pause, you can only flip (any number of) switches to on/1 (aka "paused"), and if you unpause, * you can only flip (any number of) switches to off/0 (aka "paused"). * If you want a pauseXYZ function that just flips a single bit / "pausing flag", it will: * 1) 'bit-wise and' (aka `&`) a flag with the current paused state (as a uint256) * 2) update the paused state to this new value * @dev We note as well that we have chosen to identify flags by their *bit index* as opposed to their numerical value, so, e.g. defining `DEPOSITS_PAUSED = 3` * indicates specifically that if the *third bit* of `_paused` is flipped -- i.e. it is a '1' -- then deposits should be paused */ interface IPausable { /// @notice Emitted when the `pauserRegistry` is set to `newPauserRegistry`. event PauserRegistrySet(IPauserRegistry pauserRegistry, IPauserRegistry newPauserRegistry); /// @notice Emitted when the pause is triggered by `account`, and changed to `newPausedStatus`. event Paused(address indexed account, uint256 newPausedStatus); /// @notice Emitted when the pause is lifted by `account`, and changed to `newPausedStatus`. event Unpaused(address indexed account, uint256 newPausedStatus); /// @notice Address of the `PauserRegistry` contract that this contract defers to for determining access control (for pausing). function pauserRegistry() external view returns (IPauserRegistry); /** * @notice This function is used to pause an EigenLayer contract's functionality. * It is permissioned to the `pauser` address, which is expected to be a low threshold multisig. * @param newPausedStatus represents the new value for `_paused` to take, which means it may flip several bits at once. * @dev This function can only pause functionality, and thus cannot 'unflip' any bit in `_paused` from 1 to 0. */ function pause(uint256 newPausedStatus) external; /** * @notice Alias for `pause(type(uint256).max)`. */ function pauseAll() external; /** * @notice This function is used to unpause an EigenLayer contract's functionality. * It is permissioned to the `unpauser` address, which is expected to be a high threshold multisig or governance contract. * @param newPausedStatus represents the new value for `_paused` to take, which means it may flip several bits at once. * @dev This function can only unpause functionality, and thus cannot 'flip' any bit in `_paused` from 0 to 1. */ function unpause(uint256 newPausedStatus) external; /// @notice Returns the current paused status as a uint256. function paused() external view returns (uint256); /// @notice Returns 'true' if the `indexed`th bit of `_paused` is 1, and 'false' otherwise function paused(uint8 index) external view returns (bool); /// @notice Allows the unpauser to set a new pauser registry function setPauserRegistry(IPauserRegistry newPauserRegistry) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /* Library Imports */ import {Lib_AddressManager} from "./Lib_AddressManager.sol"; /** * @title Lib_AddressResolver */ abstract contract Lib_AddressResolver { /** * * Variables * * */ Lib_AddressManager public libAddressManager; /** * * Constructor * * */ /** * @param _libAddressManager Address of the Lib_AddressManager. */ constructor(address _libAddressManager) { libAddressManager = Lib_AddressManager(_libAddressManager); } /** * * Public Functions * * */ /** * Resolves the address associated with a given name. * @param _name Name to resolve an address for. * @return Address associated with the given name. */ function resolve(string memory _name) public view returns (address) { return libAddressManager.getAddress(_name); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /* Library Imports */ import {Lib_RLPReader} from "../rlp/Lib_RLPReader.sol"; import {Lib_RLPWriter} from "../rlp/Lib_RLPWriter.sol"; import {Lib_BytesUtils} from "../utils/Lib_BytesUtils.sol"; import {Lib_Bytes32Utils} from "../utils/Lib_Bytes32Utils.sol"; /** * @title Lib_OVMCodec */ library Lib_OVMCodec { /** * * Enums * * */ enum QueueOrigin { SEQUENCER_QUEUE, L1TOL2_QUEUE } /** * * Structs * * */ struct EVMAccount { uint256 nonce; uint256 balance; bytes32 storageRoot; bytes32 codeHash; } struct ChainBatchHeader { uint256 batchIndex; bytes32 batchRoot; uint256 batchSize; uint256 prevTotalElements; bytes extraData; } struct ChainInclusionProof { uint256 index; bytes32[] siblings; } struct Transaction { uint256 timestamp; uint256 blockNumber; QueueOrigin l1QueueOrigin; address l1TxOrigin; address entrypoint; uint256 gasLimit; bytes data; } struct TransactionChainElement { bool isSequenced; uint256 queueIndex; // QUEUED TX ONLY uint256 timestamp; // SEQUENCER TX ONLY uint256 blockNumber; // SEQUENCER TX ONLY bytes txData; // SEQUENCER TX ONLY } struct QueueElement { bytes32 transactionHash; uint40 timestamp; uint40 blockNumber; } /** * * Internal Functions * * */ /** * Encodes a standard OVM transaction. * @param _transaction OVM transaction to encode. * @return Encoded transaction bytes. */ function encodeTransaction(Transaction memory _transaction) internal pure returns (bytes memory) { return abi.encodePacked( _transaction.timestamp, _transaction.blockNumber, _transaction.l1QueueOrigin, _transaction.l1TxOrigin, _transaction.entrypoint, _transaction.gasLimit, _transaction.data ); } /** * Hashes a standard OVM transaction. * @param _transaction OVM transaction to encode. * @return Hashed transaction */ function hashTransaction(Transaction memory _transaction) internal pure returns (bytes32) { return keccak256(encodeTransaction(_transaction)); } /** * @notice Decodes an RLP-encoded account state into a useful struct. * @param _encoded RLP-encoded account state. * @return Account state struct. */ function decodeEVMAccount(bytes memory _encoded) internal pure returns (EVMAccount memory) { Lib_RLPReader.RLPItem[] memory accountState = Lib_RLPReader.readList(_encoded); return EVMAccount({ nonce: Lib_RLPReader.readUint256(accountState[0]), balance: Lib_RLPReader.readUint256(accountState[1]), storageRoot: Lib_RLPReader.readBytes32(accountState[2]), codeHash: Lib_RLPReader.readBytes32(accountState[3]) }); } /** * Calculates a hash for a given batch header. * @param _batchHeader Header to hash. * @return Hash of the header. */ function hashBatchHeader(Lib_OVMCodec.ChainBatchHeader memory _batchHeader) internal pure returns (bytes32) { return keccak256( abi.encode( _batchHeader.batchRoot, _batchHeader.batchSize, _batchHeader.prevTotalElements, _batchHeader.extraData ) ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /* Library Imports */ import {Lib_MerkleTrie} from "./Lib_MerkleTrie.sol"; /** * @title Lib_SecureMerkleTrie */ library Lib_SecureMerkleTrie { /** * * Internal Functions * * */ /** * @notice Verifies a proof that a given key/value pair is present in the * Merkle trie. * @param _key Key of the node to search for, as a hex string. * @param _value Value of the node to search for, as a hex string. * @param _proof Merkle trie inclusion proof for the desired node. Unlike * traditional Merkle trees, this proof is executed top-down and consists * of a list of RLP-encoded nodes that make a path down to the target node. * @param _root Known root of the Merkle trie. Used to verify that the * included proof is correctly constructed. * @return _verified `true` if the k/v pair exists in the trie, `false` otherwise. */ function verifyInclusionProof(bytes memory _key, bytes memory _value, bytes memory _proof, bytes32 _root) internal pure returns (bool _verified) { bytes memory key = _getSecureKey(_key); return Lib_MerkleTrie.verifyInclusionProof(key, _value, _proof, _root); } /** * @notice Retrieves the value associated with a given key. * @param _key Key to search for, as hex bytes. * @param _proof Merkle trie inclusion proof for the key. * @param _root Known root of the Merkle trie. * @return _exists Whether or not the key exists. * @return _value Value of the key if it exists. */ function get(bytes memory _key, bytes memory _proof, bytes32 _root) internal pure returns (bool _exists, bytes memory _value) { bytes memory key = _getSecureKey(_key); return Lib_MerkleTrie.get(key, _proof, _root); } /** * * Private Functions * * */ /** * Computes the secure counterpart to a key. * @param _key Key to get a secure key from. * @return _secureKey Secure version of the key. */ function _getSecureKey(bytes memory _key) private pure returns (bytes memory _secureKey) { return abi.encodePacked(keccak256(_key)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /** * @title Lib_RLPReader * @dev Adapted from "RLPReader" by Hamdi Allam ([email protected]). */ library Lib_RLPReader { /** * * Constants * * */ uint256 internal constant MAX_LIST_LENGTH = 32; /** * * Enums * * */ enum RLPItemType { DATA_ITEM, LIST_ITEM } /** * * Structs * * */ struct RLPItem { uint256 length; uint256 ptr; } /** * * Internal Functions * * */ /** * Converts bytes to a reference to memory position and length. * @param _in Input bytes to convert. * @return Output memory reference. */ function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory) { uint256 ptr; assembly { ptr := add(_in, 32) } return RLPItem({length: _in.length, ptr: ptr}); } /** * Reads an RLP list value into a list of RLP items. * @param _in RLP list value. * @return Decoded RLP list items. */ function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory) { (uint256 listOffset,, RLPItemType itemType) = _decodeLength(_in); require(itemType == RLPItemType.LIST_ITEM, "Invalid RLP list value."); // Solidity in-memory arrays can't be increased in size, but *can* be decreased in size by // writing to the length. Since we can't know the number of RLP items without looping over // the entire input, we'd have to loop twice to accurately size this array. It's easier to // simply set a reasonable maximum list length and decrease the size before we finish. RLPItem[] memory out = new RLPItem[](MAX_LIST_LENGTH); uint256 itemCount = 0; uint256 offset = listOffset; while (offset < _in.length) { require(itemCount < MAX_LIST_LENGTH, "Provided RLP list exceeds max list length."); (uint256 itemOffset, uint256 itemLength,) = _decodeLength(RLPItem({length: _in.length - offset, ptr: _in.ptr + offset})); out[itemCount] = RLPItem({length: itemLength + itemOffset, ptr: _in.ptr + offset}); itemCount += 1; offset += itemOffset + itemLength; } // Decrease the array size to match the actual item count. assembly { mstore(out, itemCount) } return out; } /** * Reads an RLP list value into a list of RLP items. * @param _in RLP list value. * @return Decoded RLP list items. */ function readList(bytes memory _in) internal pure returns (RLPItem[] memory) { return readList(toRLPItem(_in)); } /** * Reads an RLP bytes value into bytes. * @param _in RLP bytes value. * @return Decoded bytes. */ function readBytes(RLPItem memory _in) internal pure returns (bytes memory) { (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in); require(itemType == RLPItemType.DATA_ITEM, "Invalid RLP bytes value."); return _copy(_in.ptr, itemOffset, itemLength); } /** * Reads an RLP bytes value into bytes. * @param _in RLP bytes value. * @return Decoded bytes. */ function readBytes(bytes memory _in) internal pure returns (bytes memory) { return readBytes(toRLPItem(_in)); } /** * Reads an RLP string value into a string. * @param _in RLP string value. * @return Decoded string. */ function readString(RLPItem memory _in) internal pure returns (string memory) { return string(readBytes(_in)); } /** * Reads an RLP string value into a string. * @param _in RLP string value. * @return Decoded string. */ function readString(bytes memory _in) internal pure returns (string memory) { return readString(toRLPItem(_in)); } /** * Reads an RLP bytes32 value into a bytes32. * @param _in RLP bytes32 value. * @return Decoded bytes32. */ function readBytes32(RLPItem memory _in) internal pure returns (bytes32) { require(_in.length <= 33, "Invalid RLP bytes32 value."); (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in); require(itemType == RLPItemType.DATA_ITEM, "Invalid RLP bytes32 value."); uint256 ptr = _in.ptr + itemOffset; bytes32 out; assembly { out := mload(ptr) // Shift the bytes over to match the item size. if lt(itemLength, 32) { out := div(out, exp(256, sub(32, itemLength))) } } return out; } /** * Reads an RLP bytes32 value into a bytes32. * @param _in RLP bytes32 value. * @return Decoded bytes32. */ function readBytes32(bytes memory _in) internal pure returns (bytes32) { return readBytes32(toRLPItem(_in)); } /** * Reads an RLP uint256 value into a uint256. * @param _in RLP uint256 value. * @return Decoded uint256. */ function readUint256(RLPItem memory _in) internal pure returns (uint256) { return uint256(readBytes32(_in)); } /** * Reads an RLP uint256 value into a uint256. * @param _in RLP uint256 value. * @return Decoded uint256. */ function readUint256(bytes memory _in) internal pure returns (uint256) { return readUint256(toRLPItem(_in)); } /** * Reads an RLP bool value into a bool. * @param _in RLP bool value. * @return Decoded bool. */ function readBool(RLPItem memory _in) internal pure returns (bool) { require(_in.length == 1, "Invalid RLP boolean value."); uint256 ptr = _in.ptr; uint256 out; assembly { out := byte(0, mload(ptr)) } require(out == 0 || out == 1, "Lib_RLPReader: Invalid RLP boolean value, must be 0 or 1"); return out != 0; } /** * Reads an RLP bool value into a bool. * @param _in RLP bool value. * @return Decoded bool. */ function readBool(bytes memory _in) internal pure returns (bool) { return readBool(toRLPItem(_in)); } /** * Reads an RLP address value into a address. * @param _in RLP address value. * @return Decoded address. */ function readAddress(RLPItem memory _in) internal pure returns (address) { if (_in.length == 1) { return address(0); } require(_in.length == 21, "Invalid RLP address value."); return address(uint160(readUint256(_in))); } /** * Reads an RLP address value into a address. * @param _in RLP address value. * @return Decoded address. */ function readAddress(bytes memory _in) internal pure returns (address) { return readAddress(toRLPItem(_in)); } /** * Reads the raw bytes of an RLP item. * @param _in RLP item to read. * @return Raw RLP bytes. */ function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory) { return _copy(_in); } /** * * Private Functions * * */ /** * Decodes the length of an RLP item. * @param _in RLP item to decode. * @return Offset of the encoded data. * @return Length of the encoded data. * @return RLP item type (LIST_ITEM or DATA_ITEM). */ function _decodeLength(RLPItem memory _in) private pure returns (uint256, uint256, RLPItemType) { require(_in.length > 0, "RLP item cannot be null."); uint256 ptr = _in.ptr; uint256 prefix; assembly { prefix := byte(0, mload(ptr)) } if (prefix <= 0x7f) { // Single byte. return (0, 1, RLPItemType.DATA_ITEM); } else if (prefix <= 0xb7) { // Short string. // slither-disable-next-line variable-scope uint256 strLen = prefix - 0x80; require(_in.length > strLen, "Invalid RLP short string."); return (1, strLen, RLPItemType.DATA_ITEM); } else if (prefix <= 0xbf) { // Long string. uint256 lenOfStrLen = prefix - 0xb7; require(_in.length > lenOfStrLen, "Invalid RLP long string length."); uint256 strLen; assembly { // Pick out the string length. strLen := div(mload(add(ptr, 1)), exp(256, sub(32, lenOfStrLen))) } require(_in.length > lenOfStrLen + strLen, "Invalid RLP long string."); return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM); } else if (prefix <= 0xf7) { // Short list. // slither-disable-next-line variable-scope uint256 listLen = prefix - 0xc0; require(_in.length > listLen, "Invalid RLP short list."); return (1, listLen, RLPItemType.LIST_ITEM); } else { // Long list. uint256 lenOfListLen = prefix - 0xf7; require(_in.length > lenOfListLen, "Invalid RLP long list length."); uint256 listLen; assembly { // Pick out the list length. listLen := div(mload(add(ptr, 1)), exp(256, sub(32, lenOfListLen))) } require(_in.length > lenOfListLen + listLen, "Invalid RLP long list."); return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM); } } /** * Copies the bytes from a memory location. * @param _src Pointer to the location to read from. * @param _offset Offset to start reading from. * @param _length Number of bytes to read. * @return Copied bytes. */ function _copy(uint256 _src, uint256 _offset, uint256 _length) private pure returns (bytes memory) { bytes memory out = new bytes(_length); if (out.length == 0) { return out; } uint256 src = _src + _offset; uint256 dest; assembly { dest := add(out, 32) } // Copy over as many complete words as we can. for (uint256 i = 0; i < _length / 32; i++) { assembly { mstore(dest, mload(src)) } src += 32; dest += 32; } // Pick out the remaining bytes. uint256 mask; unchecked { mask = 256 ** (32 - (_length % 32)) - 1; } assembly { mstore(dest, or(and(mload(src), not(mask)), and(mload(dest), mask))) } return out; } /** * Copies an RLP item into bytes. * @param _in RLP item to copy. * @return Copied bytes. */ function _copy(RLPItem memory _in) private pure returns (bytes memory) { return _copy(_in.ptr, 0, _in.length); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /* External Imports */ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; /** * @title Lib_AddressManager */ contract Lib_AddressManager is Ownable { /** * * Events * * */ event AddressSet(string indexed _name, address _newAddress, address _oldAddress); /** * * Variables * * */ mapping(bytes32 => address) private addresses; /** * * Public Functions * * */ /** * Changes the address associated with a particular name. * @param _name String name to associate an address with. * @param _address Address to associate with the name. */ function setAddress(string memory _name, address _address) external onlyOwner { bytes32 nameHash = _getNameHash(_name); address oldAddress = addresses[nameHash]; addresses[nameHash] = _address; emit AddressSet(_name, _address, oldAddress); } /** * Retrieves the address associated with a given name. * @param _name Name to retrieve an address for. * @return Address associated with the given name. */ function getAddress(string memory _name) external view returns (address) { return addresses[_getNameHash(_name)]; } /** * * Internal Functions * * */ /** * Computes the hash of a name. * @param _name Name to compute a hash for. * @return Hash of the given name. */ function _getNameHash(string memory _name) internal pure returns (bytes32) { return keccak256(abi.encodePacked(_name)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /** * @title Lib_RLPWriter * @author Bakaoh (with modifications) */ library Lib_RLPWriter { /** * * Internal Functions * * */ /** * RLP encodes a byte string. * @param _in The byte string to encode. * @return The RLP encoded string in bytes. */ function writeBytes(bytes memory _in) internal pure returns (bytes memory) { bytes memory encoded; if (_in.length == 1 && uint8(_in[0]) < 128) { encoded = _in; } else { encoded = abi.encodePacked(_writeLength(_in.length, 128), _in); } return encoded; } /** * RLP encodes a list of RLP encoded byte byte strings. * @param _in The list of RLP encoded byte strings. * @return The RLP encoded list of items in bytes. */ function writeList(bytes[] memory _in) internal pure returns (bytes memory) { bytes memory list = _flatten(_in); return abi.encodePacked(_writeLength(list.length, 192), list); } /** * RLP encodes a string. * @param _in The string to encode. * @return The RLP encoded string in bytes. */ function writeString(string memory _in) internal pure returns (bytes memory) { return writeBytes(bytes(_in)); } /** * RLP encodes an address. * @param _in The address to encode. * @return The RLP encoded address in bytes. */ function writeAddress(address _in) internal pure returns (bytes memory) { return writeBytes(abi.encodePacked(_in)); } /** * RLP encodes a uint. * @param _in The uint256 to encode. * @return The RLP encoded uint256 in bytes. */ function writeUint(uint256 _in) internal pure returns (bytes memory) { return writeBytes(_toBinary(_in)); } /** * RLP encodes a bool. * @param _in The bool to encode. * @return The RLP encoded bool in bytes. */ function writeBool(bool _in) internal pure returns (bytes memory) { bytes memory encoded = new bytes(1); encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80)); return encoded; } /** * * Private Functions * * */ /** * Encode the first byte, followed by the `len` in binary form if `length` is more than 55. * @param _len The length of the string or the payload. * @param _offset 128 if item is string, 192 if item is list. * @return RLP encoded bytes. */ function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) { bytes memory encoded; if (_len < 56) { encoded = new bytes(1); encoded[0] = bytes1(uint8(_len) + uint8(_offset)); } else { uint256 lenLen; uint256 i = 1; while (_len / i != 0) { lenLen++; i *= 256; } encoded = new bytes(lenLen + 1); encoded[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55); for (i = 1; i <= lenLen; i++) { encoded[i] = bytes1(uint8((_len / (256 ** (lenLen - i))) % 256)); } } return encoded; } /** * Encode integer in big endian binary form with no leading zeroes. * @notice TODO: This should be optimized with assembly to save gas costs. * @param _x The integer to encode. * @return RLP encoded bytes. */ function _toBinary(uint256 _x) private pure returns (bytes memory) { bytes memory b = abi.encodePacked(_x); uint256 i = 0; for (; i < 32; i++) { if (b[i] != 0) { break; } } bytes memory res = new bytes(32 - i); for (uint256 j = 0; j < res.length; j++) { res[j] = b[i++]; } return res; } /** * Copies a piece of memory to another location. * @notice From: https://github.com/Arachnid/solidity-stringutils/blob/master/src/strings.sol. * @param _dest Destination location. * @param _src Source location. * @param _len Length of memory to copy. */ function _memcpy(uint256 _dest, uint256 _src, uint256 _len) private pure { uint256 dest = _dest; uint256 src = _src; uint256 len = _len; for (; len >= 32; len -= 32) { assembly { mstore(dest, mload(src)) } dest += 32; src += 32; } uint256 mask; unchecked { mask = 256 ** (32 - len) - 1; } assembly { let srcpart := and(mload(src), not(mask)) let destpart := and(mload(dest), mask) mstore(dest, or(destpart, srcpart)) } } /** * Flattens a list of byte strings into one byte string. * @notice From: https://github.com/sammayo/solidity-rlp-encoder/blob/master/RLPEncode.sol. * @param _list List of byte strings to flatten. * @return The flattened byte string. */ function _flatten(bytes[] memory _list) private pure returns (bytes memory) { if (_list.length == 0) { return new bytes(0); } uint256 len; uint256 i = 0; for (; i < _list.length; i++) { len += _list[i].length; } bytes memory flattened = new bytes(len); uint256 flattenedPtr; assembly { flattenedPtr := add(flattened, 0x20) } for (i = 0; i < _list.length; i++) { bytes memory item = _list[i]; uint256 listPtr; assembly { listPtr := add(item, 0x20) } _memcpy(flattenedPtr, listPtr, item.length); flattenedPtr += _list[i].length; } return flattened; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /** * @title Lib_BytesUtils */ library Lib_BytesUtils { /** * * Internal Functions * * */ function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_start + _length >= _start, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) { if (_start >= _bytes.length) { return bytes(""); } return slice(_bytes, _start, _bytes.length - _start); } function toBytes32(bytes memory _bytes) internal pure returns (bytes32) { if (_bytes.length < 32) { bytes32 ret; assembly { ret := mload(add(_bytes, 32)) } return ret; } return abi.decode(_bytes, (bytes32)); // will truncate if input length > 32 bytes } function toUint256(bytes memory _bytes) internal pure returns (uint256) { return uint256(toBytes32(_bytes)); } function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) { bytes memory nibbles = new bytes(_bytes.length * 2); for (uint256 i = 0; i < _bytes.length; i++) { nibbles[i * 2] = _bytes[i] >> 4; nibbles[i * 2 + 1] = bytes1(uint8(_bytes[i]) % 16); } return nibbles; } function fromNibbles(bytes memory _bytes) internal pure returns (bytes memory) { bytes memory ret = new bytes(_bytes.length / 2); for (uint256 i = 0; i < ret.length; i++) { ret[i] = (_bytes[i * 2] << 4) | (_bytes[i * 2 + 1]); } return ret; } function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) { return keccak256(_bytes) == keccak256(_other); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /** * @title Lib_Byte32Utils */ library Lib_Bytes32Utils { /** * * Internal Functions * * */ /** * Converts a bytes32 value to a boolean. Anything non-zero will be converted to "true." * @param _in Input bytes32 value. * @return Bytes32 as a boolean. */ function toBool(bytes32 _in) internal pure returns (bool) { return _in != 0; } /** * Converts a boolean to a bytes32 value. * @param _in Input boolean value. * @return Boolean as a bytes32. */ function fromBool(bool _in) internal pure returns (bytes32) { return bytes32(uint256(_in ? 1 : 0)); } /** * Converts a bytes32 value to an address. Takes the *last* 20 bytes. * @param _in Input bytes32 value. * @return Bytes32 as an address. */ function toAddress(bytes32 _in) internal pure returns (address) { return address(uint160(uint256(_in))); } /** * Converts an address to a bytes32. * @param _in Input address value. * @return Address as a bytes32. */ function fromAddress(address _in) internal pure returns (bytes32) { return bytes32(uint256(uint160(_in))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /* Library Imports */ import {Lib_BytesUtils} from "../utils/Lib_BytesUtils.sol"; import {Lib_RLPReader} from "../rlp/Lib_RLPReader.sol"; import {Lib_RLPWriter} from "../rlp/Lib_RLPWriter.sol"; /** * @title Lib_MerkleTrie */ library Lib_MerkleTrie { /** * * Data Structures * * */ enum NodeType { BranchNode, ExtensionNode, LeafNode } struct TrieNode { bytes encoded; Lib_RLPReader.RLPItem[] decoded; } /** * * Contract Constants * * */ // TREE_RADIX determines the number of elements per branch node. uint256 constant TREE_RADIX = 16; // Branch nodes have TREE_RADIX elements plus an additional `value` slot. uint256 constant BRANCH_NODE_LENGTH = TREE_RADIX + 1; // Leaf nodes and extension nodes always have two elements, a `path` and a `value`. uint256 constant LEAF_OR_EXTENSION_NODE_LENGTH = 2; // Prefixes are prepended to the `path` within a leaf or extension node and // allow us to differentiate between the two node types. `ODD` or `EVEN` is // determined by the number of nibbles within the unprefixed `path`. If the // number of nibbles if even, we need to insert an extra padding nibble so // the resulting prefixed `path` has an even number of nibbles. uint8 constant PREFIX_EXTENSION_EVEN = 0; uint8 constant PREFIX_EXTENSION_ODD = 1; uint8 constant PREFIX_LEAF_EVEN = 2; uint8 constant PREFIX_LEAF_ODD = 3; // Just a utility constant. RLP represents `NULL` as 0x80. bytes1 constant RLP_NULL = bytes1(0x80); /** * * Internal Functions * * */ /** * @notice Verifies a proof that a given key/value pair is present in the * Merkle trie. * @param _key Key of the node to search for, as a hex string. * @param _value Value of the node to search for, as a hex string. * @param _proof Merkle trie inclusion proof for the desired node. Unlike * traditional Merkle trees, this proof is executed top-down and consists * of a list of RLP-encoded nodes that make a path down to the target node. * @param _root Known root of the Merkle trie. Used to verify that the * included proof is correctly constructed. * @return _verified `true` if the k/v pair exists in the trie, `false` otherwise. */ function verifyInclusionProof(bytes memory _key, bytes memory _value, bytes memory _proof, bytes32 _root) internal pure returns (bool _verified) { (bool exists, bytes memory value) = get(_key, _proof, _root); return (exists && Lib_BytesUtils.equal(_value, value)); } /** * @notice Retrieves the value associated with a given key. * @param _key Key to search for, as hex bytes. * @param _proof Merkle trie inclusion proof for the key. * @param _root Known root of the Merkle trie. * @return _exists Whether or not the key exists. * @return _value Value of the key if it exists. */ function get(bytes memory _key, bytes memory _proof, bytes32 _root) internal pure returns (bool _exists, bytes memory _value) { TrieNode[] memory proof = _parseProof(_proof); (uint256 pathLength, bytes memory keyRemainder, bool isFinalNode) = _walkNodePath(proof, _key, _root); bool exists = keyRemainder.length == 0; require(exists || isFinalNode, "Provided proof is invalid."); bytes memory value = exists ? _getNodeValue(proof[pathLength - 1]) : bytes(""); return (exists, value); } /** * * Private Functions * * */ /** * @notice Walks through a proof using a provided key. * @param _proof Inclusion proof to walk through. * @param _key Key to use for the walk. * @param _root Known root of the trie. * @return _pathLength Length of the final path * @return _keyRemainder Portion of the key remaining after the walk. * @return _isFinalNode Whether or not we've hit a dead end. */ function _walkNodePath(TrieNode[] memory _proof, bytes memory _key, bytes32 _root) private pure returns (uint256 _pathLength, bytes memory _keyRemainder, bool _isFinalNode) { uint256 pathLength = 0; bytes memory key = Lib_BytesUtils.toNibbles(_key); bytes32 currentNodeID = _root; uint256 currentKeyIndex = 0; uint256 currentKeyIncrement = 0; TrieNode memory currentNode; // Proof is top-down, so we start at the first element (root). for (uint256 i = 0; i < _proof.length; i++) { currentNode = _proof[i]; currentKeyIndex += currentKeyIncrement; // Keep track of the proof elements we actually need. // It's expensive to resize arrays, so this simply reduces gas costs. pathLength += 1; if (currentKeyIndex == 0) { // First proof element is always the root node. require(keccak256(currentNode.encoded) == currentNodeID, "Invalid root hash"); } else if (currentNode.encoded.length >= 32) { // Nodes 32 bytes or larger are hashed inside branch nodes. require(keccak256(currentNode.encoded) == currentNodeID, "Invalid large internal hash"); } else { // Nodes smaller than 31 bytes aren't hashed. require(Lib_BytesUtils.toBytes32(currentNode.encoded) == currentNodeID, "Invalid internal node hash"); } if (currentNode.decoded.length == BRANCH_NODE_LENGTH) { if (currentKeyIndex == key.length) { // We've hit the end of the key // meaning the value should be within this branch node. break; } else { // We're not at the end of the key yet. // Figure out what the next node ID should be and continue. uint8 branchKey = uint8(key[currentKeyIndex]); Lib_RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey]; currentNodeID = _getNodeID(nextNode); currentKeyIncrement = 1; continue; } } else if (currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) { bytes memory path = _getNodePath(currentNode); uint8 prefix = uint8(path[0]); uint8 offset = 2 - (prefix % 2); bytes memory pathRemainder = Lib_BytesUtils.slice(path, offset); bytes memory keyRemainder = Lib_BytesUtils.slice(key, currentKeyIndex); uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder); if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) { if (pathRemainder.length == sharedNibbleLength && keyRemainder.length == sharedNibbleLength) { // The key within this leaf matches our key exactly. // Increment the key index to reflect that we have no remainder. currentKeyIndex += sharedNibbleLength; } // We've hit a leaf node, so our next node should be NULL. currentNodeID = bytes32(RLP_NULL); break; } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) { if (sharedNibbleLength != pathRemainder.length) { // Our extension node is not identical to the remainder. // We've hit the end of this path // updates will need to modify this extension. currentNodeID = bytes32(RLP_NULL); break; } else { // Our extension shares some nibbles. // Carry on to the next node. currentNodeID = _getNodeID(currentNode.decoded[1]); currentKeyIncrement = sharedNibbleLength; continue; } } else { revert("Received a node with an unknown prefix"); } } else { revert("Received an unparseable node."); } } // If our node ID is NULL, then we're at a dead end. bool isFinalNode = currentNodeID == bytes32(RLP_NULL); return (pathLength, Lib_BytesUtils.slice(key, currentKeyIndex), isFinalNode); } /** * @notice Parses an RLP-encoded proof into something more useful. * @param _proof RLP-encoded proof to parse. * @return _parsed Proof parsed into easily accessible structs. */ function _parseProof(bytes memory _proof) private pure returns (TrieNode[] memory _parsed) { Lib_RLPReader.RLPItem[] memory nodes = Lib_RLPReader.readList(_proof); TrieNode[] memory proof = new TrieNode[](nodes.length); for (uint256 i = 0; i < nodes.length; i++) { bytes memory encoded = Lib_RLPReader.readBytes(nodes[i]); proof[i] = TrieNode({encoded: encoded, decoded: Lib_RLPReader.readList(encoded)}); } return proof; } /** * @notice Picks out the ID for a node. Node ID is referred to as the * "hash" within the specification, but nodes < 32 bytes are not actually * hashed. * @param _node Node to pull an ID for. * @return _nodeID ID for the node, depending on the size of its contents. */ function _getNodeID(Lib_RLPReader.RLPItem memory _node) private pure returns (bytes32 _nodeID) { bytes memory nodeID; if (_node.length < 32) { // Nodes smaller than 32 bytes are RLP encoded. nodeID = Lib_RLPReader.readRawBytes(_node); } else { // Nodes 32 bytes or larger are hashed. nodeID = Lib_RLPReader.readBytes(_node); } return Lib_BytesUtils.toBytes32(nodeID); } /** * @notice Gets the path for a leaf or extension node. * @param _node Node to get a path for. * @return _path Node path, converted to an array of nibbles. */ function _getNodePath(TrieNode memory _node) private pure returns (bytes memory _path) { return Lib_BytesUtils.toNibbles(Lib_RLPReader.readBytes(_node.decoded[0])); } /** * @notice Gets the path for a node. * @param _node Node to get a value for. * @return _value Node value, as hex bytes. */ function _getNodeValue(TrieNode memory _node) private pure returns (bytes memory _value) { return Lib_RLPReader.readBytes(_node.decoded[_node.decoded.length - 1]); } /** * @notice Utility; determines the number of nibbles shared between two * nibble arrays. * @param _a First nibble array. * @param _b Second nibble array. * @return _shared Number of shared nibbles. */ function _getSharedNibbleLength(bytes memory _a, bytes memory _b) private pure returns (uint256 _shared) { uint256 i = 0; while (_a.length > i && _b.length > i && _a[i] == _b[i]) { i++; } return i; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.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 anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing 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); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "@eigenlayer/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/", "eigenlayer-middleware/=lib/eigenlayer-middleware/", "@eth-optimism/=node_modules/@eth-optimism/", "@openzeppelin/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts/", "@openzeppelin-upgrades/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable/", "eigenlayer-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/", "openzeppelin-contracts-upgradeable/=lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/eigenlayer-middleware/lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 100 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "viaIR": false, "libraries": {} }
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"newPausedStatus","type":"uint256"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IPauserRegistry","name":"pauserRegistry","type":"address"},{"indexed":false,"internalType":"contract IPauserRegistry","name":"newPauserRegistry","type":"address"}],"name":"PauserRegistrySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"rollupId","type":"uint32"},{"indexed":true,"internalType":"uint64","name":"blockHeight","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"stateRoot","type":"bytes32"}],"name":"StateRootUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"newPausedStatus","type":"uint256"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"PAUSED_UPDATE_OPERATOR_SET","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSED_UPDATE_STATE_ROOT","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"THRESHOLD_DENOMINATOR","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"aggregator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getApk","outputs":[{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct BN254.G1Point","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"pubkeyHash","type":"bytes32"}],"name":"getOperatorWeight","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getQuorumThreshold","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"rollupId","type":"uint32"},{"internalType":"uint64","name":"blockHeight","type":"uint64"}],"name":"getStateRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"rollupId","type":"uint32"},{"internalType":"uint64","name":"blockHeight","type":"uint64"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"bytes32","name":"nearDaTransactionId","type":"bytes32"},{"internalType":"bytes32","name":"nearDaCommitment","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"}],"internalType":"struct StateRootUpdate.Message","name":"message","type":"tuple"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes32","name":"storageKey","type":"bytes32"},{"internalType":"bytes","name":"stateTrieWitness","type":"bytes"},{"internalType":"bytes","name":"storageTrieWitness","type":"bytes"}],"internalType":"struct SFFLRegistryBase.ProofParams","name":"proofParams","type":"tuple"}],"name":"getStorageValue","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalWeight","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"quorumThreshold","type":"uint128"},{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"address","name":"_aggregator","type":"address"},{"internalType":"contract IPauserRegistry","name":"_pauserRegistry","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nextOperatorUpdateId","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPausedStatus","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"index","type":"uint8"}],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauserRegistry","outputs":[{"internalType":"contract IPauserRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct BN254.G1Point","name":"pubkey","type":"tuple"},{"internalType":"uint128","name":"weight","type":"uint128"}],"internalType":"struct RollupOperators.Operator[]","name":"operators","type":"tuple[]"},{"internalType":"uint64","name":"_nextOperatorUpdateId","type":"uint64"}],"name":"setInitialOperatorSet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPauserRegistry","name":"newPauserRegistry","type":"address"}],"name":"setPauserRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"newQuorumThreshold","type":"uint128"}],"name":"setQuorumThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPausedStatus","type":"uint256"}],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"rollupId","type":"uint32"},{"internalType":"uint64","name":"blockHeight","type":"uint64"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"bytes32","name":"nearDaTransactionId","type":"bytes32"},{"internalType":"bytes32","name":"nearDaCommitment","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"}],"internalType":"struct StateRootUpdate.Message","name":"message","type":"tuple"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes32","name":"storageKey","type":"bytes32"},{"internalType":"bytes","name":"stateTrieWitness","type":"bytes"},{"internalType":"bytes","name":"storageTrieWitness","type":"bytes"}],"internalType":"struct SFFLRegistryBase.ProofParams","name":"proofParams","type":"tuple"},{"internalType":"bytes","name":"agreement","type":"bytes"}],"name":"updateAndGetStorageValue","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"id","type":"uint64"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"components":[{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct BN254.G1Point","name":"pubkey","type":"tuple"},{"internalType":"uint128","name":"weight","type":"uint128"}],"internalType":"struct RollupOperators.Operator[]","name":"operators","type":"tuple[]"}],"internalType":"struct OperatorSetUpdate.Message","name":"message","type":"tuple"},{"components":[{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct BN254.G1Point[]","name":"nonSignerPubkeys","type":"tuple[]"},{"components":[{"internalType":"uint256[2]","name":"X","type":"uint256[2]"},{"internalType":"uint256[2]","name":"Y","type":"uint256[2]"}],"internalType":"struct BN254.G2Point","name":"apkG2","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct BN254.G1Point","name":"sigma","type":"tuple"}],"internalType":"struct RollupOperators.SignatureInfo","name":"signatureInfo","type":"tuple"}],"name":"updateOperatorSet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"rollupId","type":"uint32"},{"internalType":"uint64","name":"blockHeight","type":"uint64"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"bytes32","name":"nearDaTransactionId","type":"bytes32"},{"internalType":"bytes32","name":"nearDaCommitment","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"}],"internalType":"struct StateRootUpdate.Message","name":"message","type":"tuple"},{"components":[{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct BN254.G1Point[]","name":"nonSignerPubkeys","type":"tuple[]"},{"components":[{"internalType":"uint256[2]","name":"X","type":"uint256[2]"},{"internalType":"uint256[2]","name":"Y","type":"uint256[2]"}],"internalType":"struct BN254.G2Point","name":"apkG2","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct BN254.G1Point","name":"sigma","type":"tuple"}],"internalType":"struct RollupOperators.SignatureInfo","name":"signatureInfo","type":"tuple"}],"name":"updateStateRoot","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b506200001c62000022565b620000e4565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff9081161015620000e2576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b61428380620000f46000396000f3fe608060405234801561001057600080fd5b50600436106101795760003560e01c8063715018a6116100d9578063d5d4bb5a11610087578063d5d4bb5a1461034e578063dd64766e14610361578063e0f5d9f014610374578063ef0244581461039f578063f2fde38b146103a6578063f4db0571146103b9578063fabc1cbc146103c157600080fd5b8063715018a6146102d657806382616b7b146102de578063886f1195146102f15780638da5cb5b1461030457806390540c3714610315578063b128aeee14610328578063b3a9e53b1461033b57600080fd5b80632db52ea5116101365780632db52ea5146102245780632f65284e146102375780634afa71b914610258578063595c6a67146102705780635ac86ab7146102785780635c975abb146102ab5780636f5b9918146102b357600080fd5b80630510c1911461017e57806306aba0e11461019d57806310d67a2f146101c2578063136439dd146101d75780631fb4d411146101ea578063245a7bfc146101fd575b600080fd5b610186600181565b60405160ff90911681526020015b60405180910390f35b60cd546001600160801b03165b6040516001600160801b039091168152602001610194565b6101d56101d036600461366f565b6103d4565b005b6101d56101e536600461368c565b610490565b6101d56101f83660046136cf565b6105bd565b60ce5461021790600160401b90046001600160a01b031681565b604051610194919061371d565b6101d5610232366004613748565b610646565b61024a610245366004613775565b610659565b604051908152602001610194565b60cd54600160801b90046001600160801b03166101aa565b6101d5610778565b61029b610286366004613818565b606654600160ff9092169190911b9081161490565b6040519015158152602001610194565b60665461024a565b6102bb610832565b60408051825181526020928301519281019290925201610194565b6101d5610855565b6101d56102ec36600461383b565b610869565b606554610217906001600160a01b031681565b6033546001600160a01b0316610217565b6101d561032336600461389c565b6109c6565b6101d56103363660046139ea565b610b16565b61024a610349366004613abe565b610bfa565b61024a61035c366004613af1565b610c2b565b6101aa61036f36600461368c565b610d84565b60ce54610387906001600160401b031681565b6040516001600160401b039091168152602001610194565b60646101aa565b6101d56103b436600461366f565b610da1565b610186600081565b6101d56103cf36600461368c565b610e17565b606560009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610427573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044b9190613b35565b6001600160a01b0316336001600160a01b0316146104845760405162461bcd60e51b815260040161047b90613b52565b60405180910390fd5b61048d81610f6e565b50565b60655460405163237dfb4760e11b81526001600160a01b03909116906346fbf68e906104c090339060040161371d565b602060405180830381865afa1580156104dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105019190613b9c565b61051d5760405162461bcd60e51b815260040161047b90613bbe565b606654818116146105915760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e70617573653a20696e76616c696420617474656d707420604482015277746f20756e70617573652066756e6374696f6e616c69747960401b606482015260840161047b565b6066819055604051818152339060008051602061420e833981519152906020015b60405180910390a250565b606654600190600290811614156105e65760405162461bcd60e51b815260040161047b90613c06565b6105fb6105f284611065565b60ca90846110e6565b6106175760405162461bcd60e51b815260040161047b90613c39565b6106416106276020850185613c61565b6106376040860160208701613c7c565b8560a001356114d7565b505050565b61064e61153d565b61048d60ca82611597565b60006060850135158015906106715750608085013515155b6106b85760405162461bcd60e51b8152602060048201526018602482015277115b5c1d1e48139150548811104818dbdb5b5a5d1b595b9d60421b604482015260640161047b565b60006097816106ca6020890189613c61565b63ffffffff1663ffffffff16815260200190815260200160002060008760200160208101906106f99190613c7c565b6001600160401b0316815260208101919091526040016000205490508061076457826107595760405162461bcd60e51b815260206004820152600f60248201526e115b5c1d1e481859dc99595b595b9d608a1b604482015260640161047b565b610764868585611650565b61076e8686610c2b565b9695505050505050565b60655460405163237dfb4760e11b81526001600160a01b03909116906346fbf68e906107a890339060040161371d565b602060405180830381865afa1580156107c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e99190613b9c565b6108055760405162461bcd60e51b815260040161047b90613bbe565b6000196066819055604051908152339060008051602061420e8339815191529060200160405180910390a2565b61083a613546565b506040805180820190915260cb54815260cc54602082015290565b61085d61153d565b6108676000611661565b565b606654600090600190811614156108925760405162461bcd60e51b815260040161047b90613c06565b60ce546001600160401b03166108ab6020850185613c7c565b6001600160401b0316146108f45760405162461bcd60e51b815260206004820152601060248201526f15dc9bdb99c81b595cdcd859d948125160821b604482015260640161047b565b6109006105f2846116b3565b61091c5760405162461bcd60e51b815260040161047b90613c39565b6109296020840184613c7c565b610934906001613cad565b60ce805467ffffffffffffffff19166001600160401b03929092169190911790556106416109656040850185613cd8565b808060200260200160405190810160405280939291908181526020016000905b828210156109b1576109a260608302860136819003810190613d27565b81526020019060010190610985565b505050505060ca6116e790919063ffffffff16565b600054610100900460ff16158080156109e65750600054600160ff909116105b80610a005750303b158015610a00575060005460ff166001145b610a635760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161047b565b6000805460ff191660011790558015610a86576000805461ff0019166101001790555b610a918260006118e9565b610a9a84611661565b610aa560ca86611597565b60ce8054600160401b600160e01b031916600160401b6001600160a01b038616021790558015610b0f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b60ce54600160401b90046001600160a01b03163314610b725760405162461bcd60e51b815260206004820152601860248201527729b2b73232b91034b9903737ba1030b3b3b932b3b0ba37b960411b604482015260640161047b565b60cd546001600160801b031615610bcb5760405162461bcd60e51b815260206004820181905260248201527f4f70657261746f722073657420616c726561647920696e697469616c697a6564604482015260640161047b565b610bd660ca836116e7565b60ce805467ffffffffffffffff19166001600160401b039290921691909117905550565b63ffffffff821660009081526097602090815260408083206001600160401b03851684529091529020545b92915050565b600080609781610c3e6020870187613c61565b63ffffffff1663ffffffff1681526020019081526020016000206000856020016020810190610c6d9190613c7c565b6001600160401b03166001600160401b031681526020019081526020016000205490508360a001358114610cdd5760405162461bcd60e51b81526020600482015260176024820152764d69736d61746368696e6720737461746520726f6f747360481b604482015260640161047b565b610d7c610ced602085018561366f565b602085013583610d006040880188613d43565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610d42925050506060890189613d43565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506119c192505050565b949350505050565b600081815260ca60205260408120546001600160801b0316610c25565b610da961153d565b6001600160a01b038116610e0e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161047b565b61048d81611661565b606560009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8e9190613b35565b6001600160a01b0316336001600160a01b031614610ebe5760405162461bcd60e51b815260040161047b90613b52565b606654198119606654191614610f375760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e756e70617573653a20696e76616c696420617474656d706044820152777420746f2070617573652066756e6374696f6e616c69747960401b606482015260840161047b565b606681905560405181815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c906020016105b2565b6001600160a01b038116610ffc5760405162461bcd60e51b815260206004820152604960248201527f5061757361626c652e5f73657450617573657252656769737472793a206e657760448201527f50617573657252656769737472792063616e6e6f7420626520746865207a65726064820152686f206164647265737360b81b608482015260a40161047b565b606554604080516001600160a01b03928316815291831660208301527f6e9fcd539896fca60e8b0f01dd580233e48a6b0f7df013b89ba7f565869acdb6910160405180910390a1606580546001600160a01b0319166001600160a01b0392909216919091179055565b60007f482a38e491413194a63664d1808926c0e075bf3aeee17b4a07878c670a8936c5826040516020016110999190613d89565b604051602081830303815290604052805190602001206040516020016110c9929190918252602082015260400190565b604051602081830303815290604052805190602001209050919050565b6040805180820190915260008082526020820181905260038501549091906001600160801b03168061115a5760405162461bcd60e51b815260206004820181905260248201527f4f70657261746f722073657420776173206e6f7420696e697469616c697a6564604482015260640161047b565b60006111668580613df3565b90506001600160401b0381111561117f5761117f6138f6565b6040519080825280602002602001820160405280156111a8578160200160208202803683370190505b50905060005b6111b88680613df3565b90508110156113985761120b6111ce8780613df3565b838181106111de576111de613e3c565b9050604002018036038101906111f49190613e52565b805160009081526020918201519091526040902090565b82828151811061121d5761121d613e3c565b602090810291909101015280156112b4578161123a600183613e6e565b8151811061124a5761124a613e3c565b602002602001015160001c82828151811061126757611267613e3c565b602002602001015160001c116112b45760405162461bcd60e51b8152602060048201526012602482015271141d589ad95e5cc81b9bdd081cdbdc9d195960721b604482015260640161047b565b60008860000160008484815181106112ce576112ce613e3c565b6020908102919091018101518252810191909152604001600020546001600160801b031690508061133c5760405162461bcd60e51b815260206004820152601860248201527713dc195c985d1bdc881a185cc81e995c9bc81dd95a59da1d60421b604482015260640161047b565b6113766113498880613df3565b8481811061135957611359613e3c565b90506040020180360381019061136f9190613e52565b8690611afc565b94506113828185613e6e565b935050808061139090613e85565b9150506111ae565b506113c66113a584611b93565b6040805180820190915260018a0154815260028a0154602082015290611afc565b92506000806113f988866113e2368b90038b0160208c01613f0f565b6113f4368c90038c0160a08d01613e52565b611c22565b915091508161144a5760405162461bcd60e51b815260206004820152601e60248201527f50616972696e6720707265636f6d70696c652063616c6c206661696c65640000604482015260640161047b565b8061148e5760405162461bcd60e51b815260206004820152601460248201527314da59db985d1d5c99481a5cc81a5b9d985b1a5960621b604482015260640161047b565b60038901546064906114b2906001600160801b03600160801b820481169116613f4e565b6114bc9190613f93565b6001600160801b0316841015955050505050505b9392505050565b63ffffffff831660008181526097602090815260408083206001600160401b03871680855290835292819020859055518481529192917fca7171570f4ca232f925661b810636124eaf784a25b7c14e6b34c95b814dfdd8910160405180910390a3505050565b6033546001600160a01b031633146108675760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161047b565b60646001600160801b03821611156116035760405162461bcd60e51b815260206004820152602960248201527f51756f72756d207468726573686f6c642067726561746572207468616e2064656044820152683737b6b4b730ba37b960b91b606482015260840161047b565b6003820180546001600160801b03808416600160801b810291909216179091556040517f2b71b2179969a005ac6fd9c196134b364ff40069a17dd72faa96c4a00e73e9f490600090a25050565b8161165b84826105bd565b50505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f6c53db212565b8956d5fc704eb18d9f2372ce861f785ef64103f74e6c2154b3f826040516020016110999190613fb9565b6116ef613560565b60408051808201909152600184015481526002840154602082015260038401546001600160801b031660005b84518110156118ae5784818151811061173657611736613e3c565b6020026020010151935060006117618560000151805160009081526020918201519091526040902090565b60008181526020898152604090912054908701519192506001600160801b0390811691168114156117cd5760405162461bcd60e51b81526020600482015260166024820152754f70657261746f7220697320757020746f206461746560501b604482015260640161047b565b60208601516117dc8286614091565b6117e691906140b9565b6020878101516000858152918b9052604090912080546001600160801b0319166001600160801b03928316179055909450811661183157855161182a908690611afc565b9450611856565b60208601516001600160801b03166118565761185361136f8760000151611b93565b94505b6020808701516040516001600160801b03909116815283917f7714c619c02393ccf44c3de606bec5c80ae7a6077504b74887fb39f335e98adc910160405180910390a2505080806118a690613e85565b91505061171b565b506003850180546001600160801b0319166001600160801b039290921691909117905580516001850155602001516002909301929092555050565b6065546001600160a01b031615801561190a57506001600160a01b03821615155b61198c5760405162461bcd60e51b815260206004820152604760248201527f5061757361626c652e5f696e697469616c697a655061757365723a205f696e6960448201527f7469616c697a6550617573657228292063616e206f6e6c792062652063616c6c6064820152666564206f6e636560c81b608482015260a40161047b565b6066819055604051818152339060008051602061420e8339815191529060200160405180910390a26119bd82610f6e565b5050565b6040516bffffffffffffffffffffffff19606087901b16602082015260009081908190611a01906034016040516020818303038152906040528688611d81565b9150915081611a4b5760405162461bcd60e51b81526020600482015260166024820152751058d8dbdd5b9d08191bd95cc81b9bdd08195e1a5cdd60521b604482015260640161047b565b6000611a5682611daa565b9050600080611a8b8a604051602001611a7191815260200190565b604051602081830303815290604052888560400151611d81565b9150915081611adc5760405162461bcd60e51b815260206004820152601c60248201527f53746f726167652076616c756520646f6573206e6f7420657869737400000000604482015260640161047b565b611aed611ae882611e6e565b611e81565b9b9a5050505050505050505050565b611b04613546565b611b0c613580565b835181526020808501518183015283516040808401919091529084015160608301526000908360808460066107d05a03fa9050808015611b4b57611b4d565bfe5b5080611b8b5760405162461bcd60e51b815260206004820152600d60248201526c1958cb5859190b59985a5b1959609a1b604482015260640161047b565b505092915050565b611b9b613546565b8151158015611bac57506020820151155b15611bca575050604080518082019091526000808252602082015290565b60405180604001604052808360000151815260200160008051602061422e8339815191528460200151611bfd91906140db565b611c159060008051602061422e833981519152613e6e565b905292915050565b919050565b60008060007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000187876000015188602001518860000151600060028110611c6a57611c6a613e3c565b60200201518951600160200201518a60200151600060028110611c8f57611c8f613e3c565b60200201518b60200151600160028110611cab57611cab613e3c565b602090810291909101518c518d830151604051611d089a99989796959401988952602089019790975260408801959095526060870193909352608086019190915260a085015260c084015260e08301526101008201526101200190565b6040516020818303038152906040528051906020012060001c611d2b91906140db565b9050611d73611d3d61136f8884611eb0565b611d45611f2c565b611d69611d5a85611d54611fec565b90611eb0565b611d638c61200d565b90611afc565b886201d4c0612091565b909890975095505050505050565b600060606000611d90866122b5565b9050611d9d8186866122e7565b9250925050935093915050565b604080516080810182526000808252602082018190529181018290526060810182905290611dd7836123c2565b90506040518060800160405280611e0783600081518110611dfa57611dfa613e3c565b60200260200101516123d5565b8152602001611e2283600181518110611dfa57611dfa613e3c565b8152602001611e4a83600281518110611e3d57611e3d613e3c565b60200260200101516123dc565b8152602001611e6583600381518110611e3d57611e3d613e3c565b90529392505050565b6060610c25611e7c8361247e565b6124ab565b6000806000602084511115611e97576020611e9a565b83515b60209485015194036008029390931c9392505050565b611eb8613546565b611ec061359e565b835181526020808501519082015260408082018490526000908360608460076107d05a03fa9050808015611b4b575080611b8b5760405162461bcd60e51b815260206004820152600d60248201526c1958cb5b5d5b0b59985a5b1959609a1b604482015260640161047b565b611f346135bc565b50604080516080810182527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c28183019081527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6060830152815281518083019092527f275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec82527f1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d60208381019190915281019190915290565b611ff4613546565b5060408051808201909152600181526002602082015290565b612015613546565b6000808061203160008051602061422e833981519152866140db565b90505b61203d81612536565b909350915060008051602061422e833981519152828309831415612077576040805180820190915290815260208101919091529392505050565b60008051602061422e833981519152600182089050612034565b6040805180820182528681526020808201869052825180840190935286835282018490526000918291906120c36135e1565b60005b60028110156122885760006120dc8260066140ef565b90508482600281106120f0576120f0613e3c565b6020020151518361210283600061410e565b600c811061211257612112613e3c565b602002015284826002811061212957612129613e3c565b60200201516020015183826001612140919061410e565b600c811061215057612150613e3c565b602002015283826002811061216757612167613e3c565b602002015151518361217a83600261410e565b600c811061218a5761218a613e3c565b60200201528382600281106121a1576121a1613e3c565b60200201515160016020020151836121ba83600361410e565b600c81106121ca576121ca613e3c565b60200201528382600281106121e1576121e1613e3c565b6020020151602001516000600281106121fc576121fc613e3c565b60200201518361220d83600461410e565b600c811061221d5761221d613e3c565b602002015283826002811061223457612234613e3c565b60200201516020015160016002811061224f5761224f613e3c565b60200201518361226083600561410e565b600c811061227057612270613e3c565b6020020152508061228081613e85565b9150506120c6565b50612291613600565b60006020826101808560088cfa9151919c9115159b50909950505050505050505050565b606081805190602001206040516020016122d191815260200190565b6040516020818303038152906040529050919050565b6000606060006122f6856125b8565b90506000806000612308848a896126b2565b8151929550909350915015808061231c5750815b6123685760405162461bcd60e51b815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e000000000000604482015260640161047b565b60008161238457604051806020016040528060008152506123b0565b6123b086612393600188613e6e565b815181106123a3576123a3613e3c565b6020026020010151612ad6565b919b919a509098505050505050505050565b6060610c256123d08361247e565b612b00565b6000610c25825b60006021826000015111156124035760405162461bcd60e51b815260040161047b90614126565b600080600061241185612ce6565b91945092509050600081600181111561242c5761242c61415d565b146124495760405162461bcd60e51b815260040161047b90614126565b600083866020015161245b919061410e565b8051909150602084101561076e5760208490036101000a90049695505050505050565b60408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b606060008060006124bb85612ce6565b9194509250905060008160018111156124d6576124d661415d565b1461251e5760405162461bcd60e51b815260206004820152601860248201527724b73b30b634b21029262810313cba32b9903b30b63ab29760411b604482015260640161047b565b61252d8560200151848461301c565b95945050505050565b6000808060008051602061422e833981519152600360008051602061422e8339815191528660008051602061422e8339815191528889090908905060006125ac827f0c19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f5260008051602061422e8339815191526130fa565b91959194509092505050565b606060006125c5836123c2565b9050600081516001600160401b038111156125e2576125e26138f6565b60405190808252806020026020018201604052801561262757816020015b60408051808201909152606080825260208201528152602001906001900390816126005790505b50905060005b82518110156126aa57600061265a84838151811061264d5761264d613e3c565b60200260200101516124ab565b90506040518060400160405280828152602001612676836123c2565b81525083838151811061268b5761268b613e3c565b60200260200101819052505080806126a290613e85565b91505061262d565b509392505050565b600060608180806126c2876131a2565b905060008690506000806126e9604051806040016040528060608152602001606081525090565b60005b8c51811015612aae578c818151811061270757612707613e3c565b60200260200101519150828461271d919061410e565b935061272a60018861410e565b9650836127825781518051602090910120851461277d5760405162461bcd60e51b8152602060048201526011602482015270092dcecc2d8d2c840e4dedee840d0c2e6d607b1b604482015260640161047b565b61283f565b8151516020116127e45781518051602090910120851461277d5760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c20686173680000000000604482015260640161047b565b846127f283600001516132dc565b1461283f5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f64652068617368000000000000604482015260640161047b565b61284b6010600161410e565b82602001515114156128c457855184141561286557612aae565b600086858151811061287957612879613e3c565b602001015160f81c60f81b60f81c9050600083602001518260ff16815181106128a4576128a4613e3c565b602002602001015190506128b781613304565b9650600194505050612a9c565b60028260200151511415612a545760006128dd8361333a565b90506000816000815181106128f4576128f4613e3c565b016020015160f81c9050600061290b600283614173565b612916906002614195565b90506000612927848360ff1661335e565b905060006129358b8a61335e565b905060006129438383613394565b905060ff85166002148061295a575060ff85166003145b156129945780835114801561296f5750808251145b156129815761297e818b61410e565b99505b50600160ff1b9950612aae945050505050565b60ff851615806129a7575060ff85166001145b156129fd57825181146129c75750600160ff1b9950612aae945050505050565b6129ee88602001516001815181106129e1576129e1613e3c565b6020026020010151613304565b9a509750612a9c945050505050565b60405162461bcd60e51b815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e206044820152650e0e4caccd2f60d31b606482015260840161047b565b60405162461bcd60e51b815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e000000604482015260640161047b565b80612aa681613e85565b9150506126ec565b50600160ff1b841486612ac1878661335e565b909e909d50909b509950505050505050505050565b60208101518051606091610c2591612af090600190613e6e565b8151811061264d5761264d613e3c565b6060600080612b0e84612ce6565b91935090915060019050816001811115612b2a57612b2a61415d565b14612b715760405162461bcd60e51b815260206004820152601760248201527624b73b30b634b210292628103634b9ba103b30b63ab29760491b604482015260640161047b565b6040805160208082526104208201909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081612b8a5790505090506000835b8651811015612cdb5760208210612c235760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201526939ba103632b733ba341760b11b606482015260840161047b565b600080612c606040518060400160405280858c60000151612c449190613e6e565b8152602001858c60200151612c59919061410e565b9052612ce6565b509150915060405180604001604052808383612c7c919061410e565b8152602001848b60200151612c91919061410e565b815250858581518110612ca657612ca6613e3c565b6020908102919091010152612cbc60018561410e565b9350612cc8818361410e565b612cd2908461410e565b92505050612bb7565b508152949350505050565b600080600080846000015111612d395760405162461bcd60e51b81526020600482015260186024820152772926281034ba32b69031b0b73737ba10313290373ab6361760411b604482015260640161047b565b6020840151805160001a607f8111612d5e576000600160009450945094505050613015565b60b78111612dd6576000612d73608083613e6e565b905080876000015111612dc45760405162461bcd60e51b815260206004820152601960248201527824b73b30b634b2102926281039b437b93a1039ba3934b7339760391b604482015260640161047b565b60019550935060009250613015915050565b60bf8111612ec0576000612deb60b783613e6e565b905080876000015111612e405760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e00604482015260640161047b565b600183015160208290036101000a9004612e5a818361410e565b885111612ea45760405162461bcd60e51b815260206004820152601860248201527724b73b30b634b210292628103637b7339039ba3934b7339760411b604482015260640161047b565b612eaf82600161410e565b965094506000935061301592505050565b60f78111612f35576000612ed560c083613e6e565b905080876000015111612f245760405162461bcd60e51b815260206004820152601760248201527624b73b30b634b2102926281039b437b93a103634b9ba1760491b604482015260640161047b565b600195509350849250613015915050565b6000612f4260f783613e6e565b905080876000015111612f975760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e000000604482015260640161047b565b600183015160208290036101000a9004612fb1818361410e565b885111612ff95760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b210292628103637b733903634b9ba1760511b604482015260640161047b565b61300482600161410e565b965094506001935061301592505050565b9193909250565b60606000826001600160401b03811115613038576130386138f6565b6040519080825280601f01601f191660200182016040528015613062576020820181803683370190505b5090508051600014156130765790506114d0565b6000613082858761410e565b90506020820160005b6130966020876141b8565b8110156130cd57825182526130ac60208461410e565b92506130b960208361410e565b9150806130c581613e85565b91505061308b565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b600080613105613600565b61310d61361e565b602080825281810181905260408201819052606082018890526080820187905260a082018690528260c08360056107d05a03fa9250828015611b4b5750826131975760405162461bcd60e51b815260206004820152601a60248201527f424e3235342e6578704d6f643a2063616c6c206661696c757265000000000000604482015260640161047b565b505195945050505050565b60606000825160026131b491906140ef565b6001600160401b038111156131cb576131cb6138f6565b6040519080825280601f01601f1916602001820160405280156131f5576020820181803683370190505b50905060005b83518110156132d557600484828151811061321857613218613e3c565b01602001516001600160f81b031916901c826132358360026140ef565b8151811061324557613245613e3c565b60200101906001600160f81b031916908160001a905350601084828151811061327057613270613e3c565b0160200151613282919060f81c614173565b60f81b826132918360026140ef565b61329c90600161410e565b815181106132ac576132ac613e3c565b60200101906001600160f81b031916908160001a905350806132cd81613e85565b9150506131fb565b5092915050565b60006020825110156132f057506020015190565b81806020019051810190610c2591906141cc565b600060606020836000015110156133255761331e83613410565b9050613331565b61332e836124ab565b90505b6114d0816132dc565b6060610c25613359836020015160008151811061264d5761264d613e3c565b6131a2565b60608251821061337d5750604080516020810190915260008152610c25565b6114d0838384865161338f9190613e6e565b61341b565b6000805b8084511180156133a85750808351115b80156133f957508281815181106133c1576133c1613e3c565b602001015160f81c60f81b6001600160f81b0319168482815181106133e8576133e8613e3c565b01602001516001600160f81b031916145b156114d0578061340881613e85565b915050613398565b6060610c2582613530565b60608161342981601f61410e565b10156134475760405162461bcd60e51b815260040161047b906141e5565b82613452838261410e565b10156134705760405162461bcd60e51b815260040161047b906141e5565b61347a828461410e565b845110156134be5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b604482015260640161047b565b6060821580156134dd5760405191506000825260208201604052613527565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156135165780518352602092830192016134fe565b5050858452601f01601f1916604052505b50949350505050565b6060610c2582602001516000846000015161301c565b604051806040016040528060008152602001600081525090565b6040518060400160405280613573613546565b8152600060209091015290565b60405180608001604052806004906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60405180604001604052806135cf61363c565b81526020016135dc61363c565b905290565b604051806101800160405280600c906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b60405180604001604052806002906020820280368337509192915050565b6001600160a01b038116811461048d57600080fd5b60006020828403121561368157600080fd5b81356114d08161365a565b60006020828403121561369e57600080fd5b5035919050565b600060c082840312156136b757600080fd5b50919050565b600060e082840312156136b757600080fd5b60008060e083850312156136e257600080fd5b6136ec84846136a5565b915060c08301356001600160401b0381111561370757600080fd5b613713858286016136bd565b9150509250929050565b6001600160a01b0391909116815260200190565b80356001600160801b0381168114611c1d57600080fd5b60006020828403121561375a57600080fd5b6114d082613731565b6000608082840312156136b757600080fd5b600080600080610100858703121561378c57600080fd5b61379686866136a5565b935060c08501356001600160401b03808211156137b257600080fd5b6137be88838901613763565b945060e08701359150808211156137d457600080fd5b818701915087601f8301126137e857600080fd5b8135818111156137f757600080fd5b88602082850101111561380957600080fd5b95989497505060200194505050565b60006020828403121561382a57600080fd5b813560ff811681146114d057600080fd5b6000806040838503121561384e57600080fd5b82356001600160401b038082111561386557600080fd5b908401906060828703121561387957600080fd5b9092506020840135908082111561388f57600080fd5b50613713858286016136bd565b600080600080608085870312156138b257600080fd5b6138bb85613731565b935060208501356138cb8161365a565b925060408501356138db8161365a565b915060608501356138eb8161365a565b939692955090935050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561392e5761392e6138f6565b60405290565b604051601f8201601f191681016001600160401b038111828210171561395c5761395c6138f6565b604052919050565b60006040828403121561397657600080fd5b61397e61390c565b9050813581526020820135602082015292915050565b6000606082840312156139a657600080fd5b6139ae61390c565b90506139ba8383613964565b81526139c860408301613731565b602082015292915050565b80356001600160401b0381168114611c1d57600080fd5b600080604083850312156139fd57600080fd5b82356001600160401b0380821115613a1457600080fd5b818501915085601f830112613a2857600080fd5b8135602082821115613a3c57613a3c6138f6565b613a4a818360051b01613934565b82815281810193506060928302850182019289841115613a6957600080fd5b948201945b83861015613a8f57613a808a87613994565b85529485019493820193613a6e565b509550613a9d8782016139d3565b9450505050509250929050565b803563ffffffff81168114611c1d57600080fd5b60008060408385031215613ad157600080fd5b613ada83613aaa565b9150613ae8602084016139d3565b90509250929050565b60008060e08385031215613b0457600080fd5b613b0e84846136a5565b915060c08301356001600160401b03811115613b2957600080fd5b61371385828601613763565b600060208284031215613b4757600080fd5b81516114d08161365a565b6020808252602a908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526939903ab73830bab9b2b960b11b606082015260800190565b600060208284031215613bae57600080fd5b815180151581146114d057600080fd5b60208082526028908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526739903830bab9b2b960c11b606082015260800190565b60208082526019908201527814185d5cd8589b194e881a5b99195e081a5cc81c185d5cd959603a1b604082015260600190565b6020808252600e908201526d145d5bdc9d5b481b9bdd081b595d60921b604082015260600190565b600060208284031215613c7357600080fd5b6114d082613aaa565b600060208284031215613c8e57600080fd5b6114d0826139d3565b634e487b7160e01b600052601160045260246000fd5b60006001600160401b03808316818516808303821115613ccf57613ccf613c97565b01949350505050565b6000808335601e19843603018112613cef57600080fd5b8301803591506001600160401b03821115613d0957600080fd5b6020019150606081023603821315613d2057600080fd5b9250929050565b600060608284031215613d3957600080fd5b6114d08383613994565b6000808335601e19843603018112613d5a57600080fd5b8301803591506001600160401b03821115613d7457600080fd5b602001915036819003821315613d2057600080fd5b60c0810163ffffffff613d9b84613aaa565b168252613daa602084016139d3565b6001600160401b03808216602085015280613dc7604087016139d3565b1660408501525050606083013560608301526080830135608083015260a083013560a083015292915050565b6000808335601e19843603018112613e0a57600080fd5b8301803591506001600160401b03821115613e2457600080fd5b6020019150600681901b3603821315613d2057600080fd5b634e487b7160e01b600052603260045260246000fd5b600060408284031215613e6457600080fd5b6114d08383613964565b600082821015613e8057613e80613c97565b500390565b6000600019821415613e9957613e99613c97565b5060010190565b600082601f830112613eb157600080fd5b604051604081018181106001600160401b0382111715613ed357613ed36138f6565b8060405250806040840185811115613eea57600080fd5b845b81811015613f04578035835260209283019201613eec565b509195945050505050565b600060808284031215613f2157600080fd5b613f2961390c565b613f338484613ea0565b8152613f428460408501613ea0565b60208201529392505050565b60006001600160801b0382811684821681151582840482111615613f7457613f74613c97565b02949350505050565b634e487b7160e01b600052601260045260246000fd5b60006001600160801b0383811680613fad57613fad613f7d565b92169190910492915050565b60006020808352608083016001600160401b0380613fd6876139d3565b1683860152613fe68387016139d3565b604082821681880152808801359150601e1988360301821261400757600080fd5b9087019081358381111561401a57600080fd5b60609350838102360389131561402f57600080fd5b87840184905293849052908401926000919060a088015b81841015614084578535815286860135878201526001600160801b0361406d848801613731565b168184015294840194600193909301928401614046565b9998505050505050505050565b60006001600160801b03838116908316818110156140b1576140b1613c97565b039392505050565b60006001600160801b03828116848216808303821115613ccf57613ccf613c97565b6000826140ea576140ea613f7d565b500690565b600081600019048311821515161561410957614109613c97565b500290565b6000821982111561412157614121613c97565b500190565b6020808252601a908201527f496e76616c696420524c5020627974657333322076616c75652e000000000000604082015260600190565b634e487b7160e01b600052602160045260246000fd5b600060ff83168061418657614186613f7d565b8060ff84160691505092915050565b600060ff821660ff8416808210156141af576141af613c97565b90039392505050565b6000826141c7576141c7613f7d565b500490565b6000602082840312156141de57600080fd5b5051919050565b6020808252600e908201526d736c6963655f6f766572666c6f7760901b60408201526060019056feab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47a2646970667358221220c5206368b967f84defb752fed54341831da8d4493f79dd8f7c874c113cd227e564736f6c634300080c0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101795760003560e01c8063715018a6116100d9578063d5d4bb5a11610087578063d5d4bb5a1461034e578063dd64766e14610361578063e0f5d9f014610374578063ef0244581461039f578063f2fde38b146103a6578063f4db0571146103b9578063fabc1cbc146103c157600080fd5b8063715018a6146102d657806382616b7b146102de578063886f1195146102f15780638da5cb5b1461030457806390540c3714610315578063b128aeee14610328578063b3a9e53b1461033b57600080fd5b80632db52ea5116101365780632db52ea5146102245780632f65284e146102375780634afa71b914610258578063595c6a67146102705780635ac86ab7146102785780635c975abb146102ab5780636f5b9918146102b357600080fd5b80630510c1911461017e57806306aba0e11461019d57806310d67a2f146101c2578063136439dd146101d75780631fb4d411146101ea578063245a7bfc146101fd575b600080fd5b610186600181565b60405160ff90911681526020015b60405180910390f35b60cd546001600160801b03165b6040516001600160801b039091168152602001610194565b6101d56101d036600461366f565b6103d4565b005b6101d56101e536600461368c565b610490565b6101d56101f83660046136cf565b6105bd565b60ce5461021790600160401b90046001600160a01b031681565b604051610194919061371d565b6101d5610232366004613748565b610646565b61024a610245366004613775565b610659565b604051908152602001610194565b60cd54600160801b90046001600160801b03166101aa565b6101d5610778565b61029b610286366004613818565b606654600160ff9092169190911b9081161490565b6040519015158152602001610194565b60665461024a565b6102bb610832565b60408051825181526020928301519281019290925201610194565b6101d5610855565b6101d56102ec36600461383b565b610869565b606554610217906001600160a01b031681565b6033546001600160a01b0316610217565b6101d561032336600461389c565b6109c6565b6101d56103363660046139ea565b610b16565b61024a610349366004613abe565b610bfa565b61024a61035c366004613af1565b610c2b565b6101aa61036f36600461368c565b610d84565b60ce54610387906001600160401b031681565b6040516001600160401b039091168152602001610194565b60646101aa565b6101d56103b436600461366f565b610da1565b610186600081565b6101d56103cf36600461368c565b610e17565b606560009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610427573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044b9190613b35565b6001600160a01b0316336001600160a01b0316146104845760405162461bcd60e51b815260040161047b90613b52565b60405180910390fd5b61048d81610f6e565b50565b60655460405163237dfb4760e11b81526001600160a01b03909116906346fbf68e906104c090339060040161371d565b602060405180830381865afa1580156104dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105019190613b9c565b61051d5760405162461bcd60e51b815260040161047b90613bbe565b606654818116146105915760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e70617573653a20696e76616c696420617474656d707420604482015277746f20756e70617573652066756e6374696f6e616c69747960401b606482015260840161047b565b6066819055604051818152339060008051602061420e833981519152906020015b60405180910390a250565b606654600190600290811614156105e65760405162461bcd60e51b815260040161047b90613c06565b6105fb6105f284611065565b60ca90846110e6565b6106175760405162461bcd60e51b815260040161047b90613c39565b6106416106276020850185613c61565b6106376040860160208701613c7c565b8560a001356114d7565b505050565b61064e61153d565b61048d60ca82611597565b60006060850135158015906106715750608085013515155b6106b85760405162461bcd60e51b8152602060048201526018602482015277115b5c1d1e48139150548811104818dbdb5b5a5d1b595b9d60421b604482015260640161047b565b60006097816106ca6020890189613c61565b63ffffffff1663ffffffff16815260200190815260200160002060008760200160208101906106f99190613c7c565b6001600160401b0316815260208101919091526040016000205490508061076457826107595760405162461bcd60e51b815260206004820152600f60248201526e115b5c1d1e481859dc99595b595b9d608a1b604482015260640161047b565b610764868585611650565b61076e8686610c2b565b9695505050505050565b60655460405163237dfb4760e11b81526001600160a01b03909116906346fbf68e906107a890339060040161371d565b602060405180830381865afa1580156107c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e99190613b9c565b6108055760405162461bcd60e51b815260040161047b90613bbe565b6000196066819055604051908152339060008051602061420e8339815191529060200160405180910390a2565b61083a613546565b506040805180820190915260cb54815260cc54602082015290565b61085d61153d565b6108676000611661565b565b606654600090600190811614156108925760405162461bcd60e51b815260040161047b90613c06565b60ce546001600160401b03166108ab6020850185613c7c565b6001600160401b0316146108f45760405162461bcd60e51b815260206004820152601060248201526f15dc9bdb99c81b595cdcd859d948125160821b604482015260640161047b565b6109006105f2846116b3565b61091c5760405162461bcd60e51b815260040161047b90613c39565b6109296020840184613c7c565b610934906001613cad565b60ce805467ffffffffffffffff19166001600160401b03929092169190911790556106416109656040850185613cd8565b808060200260200160405190810160405280939291908181526020016000905b828210156109b1576109a260608302860136819003810190613d27565b81526020019060010190610985565b505050505060ca6116e790919063ffffffff16565b600054610100900460ff16158080156109e65750600054600160ff909116105b80610a005750303b158015610a00575060005460ff166001145b610a635760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161047b565b6000805460ff191660011790558015610a86576000805461ff0019166101001790555b610a918260006118e9565b610a9a84611661565b610aa560ca86611597565b60ce8054600160401b600160e01b031916600160401b6001600160a01b038616021790558015610b0f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b60ce54600160401b90046001600160a01b03163314610b725760405162461bcd60e51b815260206004820152601860248201527729b2b73232b91034b9903737ba1030b3b3b932b3b0ba37b960411b604482015260640161047b565b60cd546001600160801b031615610bcb5760405162461bcd60e51b815260206004820181905260248201527f4f70657261746f722073657420616c726561647920696e697469616c697a6564604482015260640161047b565b610bd660ca836116e7565b60ce805467ffffffffffffffff19166001600160401b039290921691909117905550565b63ffffffff821660009081526097602090815260408083206001600160401b03851684529091529020545b92915050565b600080609781610c3e6020870187613c61565b63ffffffff1663ffffffff1681526020019081526020016000206000856020016020810190610c6d9190613c7c565b6001600160401b03166001600160401b031681526020019081526020016000205490508360a001358114610cdd5760405162461bcd60e51b81526020600482015260176024820152764d69736d61746368696e6720737461746520726f6f747360481b604482015260640161047b565b610d7c610ced602085018561366f565b602085013583610d006040880188613d43565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610d42925050506060890189613d43565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506119c192505050565b949350505050565b600081815260ca60205260408120546001600160801b0316610c25565b610da961153d565b6001600160a01b038116610e0e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161047b565b61048d81611661565b606560009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8e9190613b35565b6001600160a01b0316336001600160a01b031614610ebe5760405162461bcd60e51b815260040161047b90613b52565b606654198119606654191614610f375760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e756e70617573653a20696e76616c696420617474656d706044820152777420746f2070617573652066756e6374696f6e616c69747960401b606482015260840161047b565b606681905560405181815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c906020016105b2565b6001600160a01b038116610ffc5760405162461bcd60e51b815260206004820152604960248201527f5061757361626c652e5f73657450617573657252656769737472793a206e657760448201527f50617573657252656769737472792063616e6e6f7420626520746865207a65726064820152686f206164647265737360b81b608482015260a40161047b565b606554604080516001600160a01b03928316815291831660208301527f6e9fcd539896fca60e8b0f01dd580233e48a6b0f7df013b89ba7f565869acdb6910160405180910390a1606580546001600160a01b0319166001600160a01b0392909216919091179055565b60007f482a38e491413194a63664d1808926c0e075bf3aeee17b4a07878c670a8936c5826040516020016110999190613d89565b604051602081830303815290604052805190602001206040516020016110c9929190918252602082015260400190565b604051602081830303815290604052805190602001209050919050565b6040805180820190915260008082526020820181905260038501549091906001600160801b03168061115a5760405162461bcd60e51b815260206004820181905260248201527f4f70657261746f722073657420776173206e6f7420696e697469616c697a6564604482015260640161047b565b60006111668580613df3565b90506001600160401b0381111561117f5761117f6138f6565b6040519080825280602002602001820160405280156111a8578160200160208202803683370190505b50905060005b6111b88680613df3565b90508110156113985761120b6111ce8780613df3565b838181106111de576111de613e3c565b9050604002018036038101906111f49190613e52565b805160009081526020918201519091526040902090565b82828151811061121d5761121d613e3c565b602090810291909101015280156112b4578161123a600183613e6e565b8151811061124a5761124a613e3c565b602002602001015160001c82828151811061126757611267613e3c565b602002602001015160001c116112b45760405162461bcd60e51b8152602060048201526012602482015271141d589ad95e5cc81b9bdd081cdbdc9d195960721b604482015260640161047b565b60008860000160008484815181106112ce576112ce613e3c565b6020908102919091018101518252810191909152604001600020546001600160801b031690508061133c5760405162461bcd60e51b815260206004820152601860248201527713dc195c985d1bdc881a185cc81e995c9bc81dd95a59da1d60421b604482015260640161047b565b6113766113498880613df3565b8481811061135957611359613e3c565b90506040020180360381019061136f9190613e52565b8690611afc565b94506113828185613e6e565b935050808061139090613e85565b9150506111ae565b506113c66113a584611b93565b6040805180820190915260018a0154815260028a0154602082015290611afc565b92506000806113f988866113e2368b90038b0160208c01613f0f565b6113f4368c90038c0160a08d01613e52565b611c22565b915091508161144a5760405162461bcd60e51b815260206004820152601e60248201527f50616972696e6720707265636f6d70696c652063616c6c206661696c65640000604482015260640161047b565b8061148e5760405162461bcd60e51b815260206004820152601460248201527314da59db985d1d5c99481a5cc81a5b9d985b1a5960621b604482015260640161047b565b60038901546064906114b2906001600160801b03600160801b820481169116613f4e565b6114bc9190613f93565b6001600160801b0316841015955050505050505b9392505050565b63ffffffff831660008181526097602090815260408083206001600160401b03871680855290835292819020859055518481529192917fca7171570f4ca232f925661b810636124eaf784a25b7c14e6b34c95b814dfdd8910160405180910390a3505050565b6033546001600160a01b031633146108675760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161047b565b60646001600160801b03821611156116035760405162461bcd60e51b815260206004820152602960248201527f51756f72756d207468726573686f6c642067726561746572207468616e2064656044820152683737b6b4b730ba37b960b91b606482015260840161047b565b6003820180546001600160801b03808416600160801b810291909216179091556040517f2b71b2179969a005ac6fd9c196134b364ff40069a17dd72faa96c4a00e73e9f490600090a25050565b8161165b84826105bd565b50505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f6c53db212565b8956d5fc704eb18d9f2372ce861f785ef64103f74e6c2154b3f826040516020016110999190613fb9565b6116ef613560565b60408051808201909152600184015481526002840154602082015260038401546001600160801b031660005b84518110156118ae5784818151811061173657611736613e3c565b6020026020010151935060006117618560000151805160009081526020918201519091526040902090565b60008181526020898152604090912054908701519192506001600160801b0390811691168114156117cd5760405162461bcd60e51b81526020600482015260166024820152754f70657261746f7220697320757020746f206461746560501b604482015260640161047b565b60208601516117dc8286614091565b6117e691906140b9565b6020878101516000858152918b9052604090912080546001600160801b0319166001600160801b03928316179055909450811661183157855161182a908690611afc565b9450611856565b60208601516001600160801b03166118565761185361136f8760000151611b93565b94505b6020808701516040516001600160801b03909116815283917f7714c619c02393ccf44c3de606bec5c80ae7a6077504b74887fb39f335e98adc910160405180910390a2505080806118a690613e85565b91505061171b565b506003850180546001600160801b0319166001600160801b039290921691909117905580516001850155602001516002909301929092555050565b6065546001600160a01b031615801561190a57506001600160a01b03821615155b61198c5760405162461bcd60e51b815260206004820152604760248201527f5061757361626c652e5f696e697469616c697a655061757365723a205f696e6960448201527f7469616c697a6550617573657228292063616e206f6e6c792062652063616c6c6064820152666564206f6e636560c81b608482015260a40161047b565b6066819055604051818152339060008051602061420e8339815191529060200160405180910390a26119bd82610f6e565b5050565b6040516bffffffffffffffffffffffff19606087901b16602082015260009081908190611a01906034016040516020818303038152906040528688611d81565b9150915081611a4b5760405162461bcd60e51b81526020600482015260166024820152751058d8dbdd5b9d08191bd95cc81b9bdd08195e1a5cdd60521b604482015260640161047b565b6000611a5682611daa565b9050600080611a8b8a604051602001611a7191815260200190565b604051602081830303815290604052888560400151611d81565b9150915081611adc5760405162461bcd60e51b815260206004820152601c60248201527f53746f726167652076616c756520646f6573206e6f7420657869737400000000604482015260640161047b565b611aed611ae882611e6e565b611e81565b9b9a5050505050505050505050565b611b04613546565b611b0c613580565b835181526020808501518183015283516040808401919091529084015160608301526000908360808460066107d05a03fa9050808015611b4b57611b4d565bfe5b5080611b8b5760405162461bcd60e51b815260206004820152600d60248201526c1958cb5859190b59985a5b1959609a1b604482015260640161047b565b505092915050565b611b9b613546565b8151158015611bac57506020820151155b15611bca575050604080518082019091526000808252602082015290565b60405180604001604052808360000151815260200160008051602061422e8339815191528460200151611bfd91906140db565b611c159060008051602061422e833981519152613e6e565b905292915050565b919050565b60008060007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000187876000015188602001518860000151600060028110611c6a57611c6a613e3c565b60200201518951600160200201518a60200151600060028110611c8f57611c8f613e3c565b60200201518b60200151600160028110611cab57611cab613e3c565b602090810291909101518c518d830151604051611d089a99989796959401988952602089019790975260408801959095526060870193909352608086019190915260a085015260c084015260e08301526101008201526101200190565b6040516020818303038152906040528051906020012060001c611d2b91906140db565b9050611d73611d3d61136f8884611eb0565b611d45611f2c565b611d69611d5a85611d54611fec565b90611eb0565b611d638c61200d565b90611afc565b886201d4c0612091565b909890975095505050505050565b600060606000611d90866122b5565b9050611d9d8186866122e7565b9250925050935093915050565b604080516080810182526000808252602082018190529181018290526060810182905290611dd7836123c2565b90506040518060800160405280611e0783600081518110611dfa57611dfa613e3c565b60200260200101516123d5565b8152602001611e2283600181518110611dfa57611dfa613e3c565b8152602001611e4a83600281518110611e3d57611e3d613e3c565b60200260200101516123dc565b8152602001611e6583600381518110611e3d57611e3d613e3c565b90529392505050565b6060610c25611e7c8361247e565b6124ab565b6000806000602084511115611e97576020611e9a565b83515b60209485015194036008029390931c9392505050565b611eb8613546565b611ec061359e565b835181526020808501519082015260408082018490526000908360608460076107d05a03fa9050808015611b4b575080611b8b5760405162461bcd60e51b815260206004820152600d60248201526c1958cb5b5d5b0b59985a5b1959609a1b604482015260640161047b565b611f346135bc565b50604080516080810182527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c28183019081527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6060830152815281518083019092527f275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec82527f1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d60208381019190915281019190915290565b611ff4613546565b5060408051808201909152600181526002602082015290565b612015613546565b6000808061203160008051602061422e833981519152866140db565b90505b61203d81612536565b909350915060008051602061422e833981519152828309831415612077576040805180820190915290815260208101919091529392505050565b60008051602061422e833981519152600182089050612034565b6040805180820182528681526020808201869052825180840190935286835282018490526000918291906120c36135e1565b60005b60028110156122885760006120dc8260066140ef565b90508482600281106120f0576120f0613e3c565b6020020151518361210283600061410e565b600c811061211257612112613e3c565b602002015284826002811061212957612129613e3c565b60200201516020015183826001612140919061410e565b600c811061215057612150613e3c565b602002015283826002811061216757612167613e3c565b602002015151518361217a83600261410e565b600c811061218a5761218a613e3c565b60200201528382600281106121a1576121a1613e3c565b60200201515160016020020151836121ba83600361410e565b600c81106121ca576121ca613e3c565b60200201528382600281106121e1576121e1613e3c565b6020020151602001516000600281106121fc576121fc613e3c565b60200201518361220d83600461410e565b600c811061221d5761221d613e3c565b602002015283826002811061223457612234613e3c565b60200201516020015160016002811061224f5761224f613e3c565b60200201518361226083600561410e565b600c811061227057612270613e3c565b6020020152508061228081613e85565b9150506120c6565b50612291613600565b60006020826101808560088cfa9151919c9115159b50909950505050505050505050565b606081805190602001206040516020016122d191815260200190565b6040516020818303038152906040529050919050565b6000606060006122f6856125b8565b90506000806000612308848a896126b2565b8151929550909350915015808061231c5750815b6123685760405162461bcd60e51b815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e000000000000604482015260640161047b565b60008161238457604051806020016040528060008152506123b0565b6123b086612393600188613e6e565b815181106123a3576123a3613e3c565b6020026020010151612ad6565b919b919a509098505050505050505050565b6060610c256123d08361247e565b612b00565b6000610c25825b60006021826000015111156124035760405162461bcd60e51b815260040161047b90614126565b600080600061241185612ce6565b91945092509050600081600181111561242c5761242c61415d565b146124495760405162461bcd60e51b815260040161047b90614126565b600083866020015161245b919061410e565b8051909150602084101561076e5760208490036101000a90049695505050505050565b60408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b606060008060006124bb85612ce6565b9194509250905060008160018111156124d6576124d661415d565b1461251e5760405162461bcd60e51b815260206004820152601860248201527724b73b30b634b21029262810313cba32b9903b30b63ab29760411b604482015260640161047b565b61252d8560200151848461301c565b95945050505050565b6000808060008051602061422e833981519152600360008051602061422e8339815191528660008051602061422e8339815191528889090908905060006125ac827f0c19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f5260008051602061422e8339815191526130fa565b91959194509092505050565b606060006125c5836123c2565b9050600081516001600160401b038111156125e2576125e26138f6565b60405190808252806020026020018201604052801561262757816020015b60408051808201909152606080825260208201528152602001906001900390816126005790505b50905060005b82518110156126aa57600061265a84838151811061264d5761264d613e3c565b60200260200101516124ab565b90506040518060400160405280828152602001612676836123c2565b81525083838151811061268b5761268b613e3c565b60200260200101819052505080806126a290613e85565b91505061262d565b509392505050565b600060608180806126c2876131a2565b905060008690506000806126e9604051806040016040528060608152602001606081525090565b60005b8c51811015612aae578c818151811061270757612707613e3c565b60200260200101519150828461271d919061410e565b935061272a60018861410e565b9650836127825781518051602090910120851461277d5760405162461bcd60e51b8152602060048201526011602482015270092dcecc2d8d2c840e4dedee840d0c2e6d607b1b604482015260640161047b565b61283f565b8151516020116127e45781518051602090910120851461277d5760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c20686173680000000000604482015260640161047b565b846127f283600001516132dc565b1461283f5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f64652068617368000000000000604482015260640161047b565b61284b6010600161410e565b82602001515114156128c457855184141561286557612aae565b600086858151811061287957612879613e3c565b602001015160f81c60f81b60f81c9050600083602001518260ff16815181106128a4576128a4613e3c565b602002602001015190506128b781613304565b9650600194505050612a9c565b60028260200151511415612a545760006128dd8361333a565b90506000816000815181106128f4576128f4613e3c565b016020015160f81c9050600061290b600283614173565b612916906002614195565b90506000612927848360ff1661335e565b905060006129358b8a61335e565b905060006129438383613394565b905060ff85166002148061295a575060ff85166003145b156129945780835114801561296f5750808251145b156129815761297e818b61410e565b99505b50600160ff1b9950612aae945050505050565b60ff851615806129a7575060ff85166001145b156129fd57825181146129c75750600160ff1b9950612aae945050505050565b6129ee88602001516001815181106129e1576129e1613e3c565b6020026020010151613304565b9a509750612a9c945050505050565b60405162461bcd60e51b815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e206044820152650e0e4caccd2f60d31b606482015260840161047b565b60405162461bcd60e51b815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e000000604482015260640161047b565b80612aa681613e85565b9150506126ec565b50600160ff1b841486612ac1878661335e565b909e909d50909b509950505050505050505050565b60208101518051606091610c2591612af090600190613e6e565b8151811061264d5761264d613e3c565b6060600080612b0e84612ce6565b91935090915060019050816001811115612b2a57612b2a61415d565b14612b715760405162461bcd60e51b815260206004820152601760248201527624b73b30b634b210292628103634b9ba103b30b63ab29760491b604482015260640161047b565b6040805160208082526104208201909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081612b8a5790505090506000835b8651811015612cdb5760208210612c235760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201526939ba103632b733ba341760b11b606482015260840161047b565b600080612c606040518060400160405280858c60000151612c449190613e6e565b8152602001858c60200151612c59919061410e565b9052612ce6565b509150915060405180604001604052808383612c7c919061410e565b8152602001848b60200151612c91919061410e565b815250858581518110612ca657612ca6613e3c565b6020908102919091010152612cbc60018561410e565b9350612cc8818361410e565b612cd2908461410e565b92505050612bb7565b508152949350505050565b600080600080846000015111612d395760405162461bcd60e51b81526020600482015260186024820152772926281034ba32b69031b0b73737ba10313290373ab6361760411b604482015260640161047b565b6020840151805160001a607f8111612d5e576000600160009450945094505050613015565b60b78111612dd6576000612d73608083613e6e565b905080876000015111612dc45760405162461bcd60e51b815260206004820152601960248201527824b73b30b634b2102926281039b437b93a1039ba3934b7339760391b604482015260640161047b565b60019550935060009250613015915050565b60bf8111612ec0576000612deb60b783613e6e565b905080876000015111612e405760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e00604482015260640161047b565b600183015160208290036101000a9004612e5a818361410e565b885111612ea45760405162461bcd60e51b815260206004820152601860248201527724b73b30b634b210292628103637b7339039ba3934b7339760411b604482015260640161047b565b612eaf82600161410e565b965094506000935061301592505050565b60f78111612f35576000612ed560c083613e6e565b905080876000015111612f245760405162461bcd60e51b815260206004820152601760248201527624b73b30b634b2102926281039b437b93a103634b9ba1760491b604482015260640161047b565b600195509350849250613015915050565b6000612f4260f783613e6e565b905080876000015111612f975760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e000000604482015260640161047b565b600183015160208290036101000a9004612fb1818361410e565b885111612ff95760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b210292628103637b733903634b9ba1760511b604482015260640161047b565b61300482600161410e565b965094506001935061301592505050565b9193909250565b60606000826001600160401b03811115613038576130386138f6565b6040519080825280601f01601f191660200182016040528015613062576020820181803683370190505b5090508051600014156130765790506114d0565b6000613082858761410e565b90506020820160005b6130966020876141b8565b8110156130cd57825182526130ac60208461410e565b92506130b960208361410e565b9150806130c581613e85565b91505061308b565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b600080613105613600565b61310d61361e565b602080825281810181905260408201819052606082018890526080820187905260a082018690528260c08360056107d05a03fa9250828015611b4b5750826131975760405162461bcd60e51b815260206004820152601a60248201527f424e3235342e6578704d6f643a2063616c6c206661696c757265000000000000604482015260640161047b565b505195945050505050565b60606000825160026131b491906140ef565b6001600160401b038111156131cb576131cb6138f6565b6040519080825280601f01601f1916602001820160405280156131f5576020820181803683370190505b50905060005b83518110156132d557600484828151811061321857613218613e3c565b01602001516001600160f81b031916901c826132358360026140ef565b8151811061324557613245613e3c565b60200101906001600160f81b031916908160001a905350601084828151811061327057613270613e3c565b0160200151613282919060f81c614173565b60f81b826132918360026140ef565b61329c90600161410e565b815181106132ac576132ac613e3c565b60200101906001600160f81b031916908160001a905350806132cd81613e85565b9150506131fb565b5092915050565b60006020825110156132f057506020015190565b81806020019051810190610c2591906141cc565b600060606020836000015110156133255761331e83613410565b9050613331565b61332e836124ab565b90505b6114d0816132dc565b6060610c25613359836020015160008151811061264d5761264d613e3c565b6131a2565b60608251821061337d5750604080516020810190915260008152610c25565b6114d0838384865161338f9190613e6e565b61341b565b6000805b8084511180156133a85750808351115b80156133f957508281815181106133c1576133c1613e3c565b602001015160f81c60f81b6001600160f81b0319168482815181106133e8576133e8613e3c565b01602001516001600160f81b031916145b156114d0578061340881613e85565b915050613398565b6060610c2582613530565b60608161342981601f61410e565b10156134475760405162461bcd60e51b815260040161047b906141e5565b82613452838261410e565b10156134705760405162461bcd60e51b815260040161047b906141e5565b61347a828461410e565b845110156134be5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b604482015260640161047b565b6060821580156134dd5760405191506000825260208201604052613527565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156135165780518352602092830192016134fe565b5050858452601f01601f1916604052505b50949350505050565b6060610c2582602001516000846000015161301c565b604051806040016040528060008152602001600081525090565b6040518060400160405280613573613546565b8152600060209091015290565b60405180608001604052806004906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60405180604001604052806135cf61363c565b81526020016135dc61363c565b905290565b604051806101800160405280600c906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b60405180604001604052806002906020820280368337509192915050565b6001600160a01b038116811461048d57600080fd5b60006020828403121561368157600080fd5b81356114d08161365a565b60006020828403121561369e57600080fd5b5035919050565b600060c082840312156136b757600080fd5b50919050565b600060e082840312156136b757600080fd5b60008060e083850312156136e257600080fd5b6136ec84846136a5565b915060c08301356001600160401b0381111561370757600080fd5b613713858286016136bd565b9150509250929050565b6001600160a01b0391909116815260200190565b80356001600160801b0381168114611c1d57600080fd5b60006020828403121561375a57600080fd5b6114d082613731565b6000608082840312156136b757600080fd5b600080600080610100858703121561378c57600080fd5b61379686866136a5565b935060c08501356001600160401b03808211156137b257600080fd5b6137be88838901613763565b945060e08701359150808211156137d457600080fd5b818701915087601f8301126137e857600080fd5b8135818111156137f757600080fd5b88602082850101111561380957600080fd5b95989497505060200194505050565b60006020828403121561382a57600080fd5b813560ff811681146114d057600080fd5b6000806040838503121561384e57600080fd5b82356001600160401b038082111561386557600080fd5b908401906060828703121561387957600080fd5b9092506020840135908082111561388f57600080fd5b50613713858286016136bd565b600080600080608085870312156138b257600080fd5b6138bb85613731565b935060208501356138cb8161365a565b925060408501356138db8161365a565b915060608501356138eb8161365a565b939692955090935050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561392e5761392e6138f6565b60405290565b604051601f8201601f191681016001600160401b038111828210171561395c5761395c6138f6565b604052919050565b60006040828403121561397657600080fd5b61397e61390c565b9050813581526020820135602082015292915050565b6000606082840312156139a657600080fd5b6139ae61390c565b90506139ba8383613964565b81526139c860408301613731565b602082015292915050565b80356001600160401b0381168114611c1d57600080fd5b600080604083850312156139fd57600080fd5b82356001600160401b0380821115613a1457600080fd5b818501915085601f830112613a2857600080fd5b8135602082821115613a3c57613a3c6138f6565b613a4a818360051b01613934565b82815281810193506060928302850182019289841115613a6957600080fd5b948201945b83861015613a8f57613a808a87613994565b85529485019493820193613a6e565b509550613a9d8782016139d3565b9450505050509250929050565b803563ffffffff81168114611c1d57600080fd5b60008060408385031215613ad157600080fd5b613ada83613aaa565b9150613ae8602084016139d3565b90509250929050565b60008060e08385031215613b0457600080fd5b613b0e84846136a5565b915060c08301356001600160401b03811115613b2957600080fd5b61371385828601613763565b600060208284031215613b4757600080fd5b81516114d08161365a565b6020808252602a908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526939903ab73830bab9b2b960b11b606082015260800190565b600060208284031215613bae57600080fd5b815180151581146114d057600080fd5b60208082526028908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526739903830bab9b2b960c11b606082015260800190565b60208082526019908201527814185d5cd8589b194e881a5b99195e081a5cc81c185d5cd959603a1b604082015260600190565b6020808252600e908201526d145d5bdc9d5b481b9bdd081b595d60921b604082015260600190565b600060208284031215613c7357600080fd5b6114d082613aaa565b600060208284031215613c8e57600080fd5b6114d0826139d3565b634e487b7160e01b600052601160045260246000fd5b60006001600160401b03808316818516808303821115613ccf57613ccf613c97565b01949350505050565b6000808335601e19843603018112613cef57600080fd5b8301803591506001600160401b03821115613d0957600080fd5b6020019150606081023603821315613d2057600080fd5b9250929050565b600060608284031215613d3957600080fd5b6114d08383613994565b6000808335601e19843603018112613d5a57600080fd5b8301803591506001600160401b03821115613d7457600080fd5b602001915036819003821315613d2057600080fd5b60c0810163ffffffff613d9b84613aaa565b168252613daa602084016139d3565b6001600160401b03808216602085015280613dc7604087016139d3565b1660408501525050606083013560608301526080830135608083015260a083013560a083015292915050565b6000808335601e19843603018112613e0a57600080fd5b8301803591506001600160401b03821115613e2457600080fd5b6020019150600681901b3603821315613d2057600080fd5b634e487b7160e01b600052603260045260246000fd5b600060408284031215613e6457600080fd5b6114d08383613964565b600082821015613e8057613e80613c97565b500390565b6000600019821415613e9957613e99613c97565b5060010190565b600082601f830112613eb157600080fd5b604051604081018181106001600160401b0382111715613ed357613ed36138f6565b8060405250806040840185811115613eea57600080fd5b845b81811015613f04578035835260209283019201613eec565b509195945050505050565b600060808284031215613f2157600080fd5b613f2961390c565b613f338484613ea0565b8152613f428460408501613ea0565b60208201529392505050565b60006001600160801b0382811684821681151582840482111615613f7457613f74613c97565b02949350505050565b634e487b7160e01b600052601260045260246000fd5b60006001600160801b0383811680613fad57613fad613f7d565b92169190910492915050565b60006020808352608083016001600160401b0380613fd6876139d3565b1683860152613fe68387016139d3565b604082821681880152808801359150601e1988360301821261400757600080fd5b9087019081358381111561401a57600080fd5b60609350838102360389131561402f57600080fd5b87840184905293849052908401926000919060a088015b81841015614084578535815286860135878201526001600160801b0361406d848801613731565b168184015294840194600193909301928401614046565b9998505050505050505050565b60006001600160801b03838116908316818110156140b1576140b1613c97565b039392505050565b60006001600160801b03828116848216808303821115613ccf57613ccf613c97565b6000826140ea576140ea613f7d565b500690565b600081600019048311821515161561410957614109613c97565b500290565b6000821982111561412157614121613c97565b500190565b6020808252601a908201527f496e76616c696420524c5020627974657333322076616c75652e000000000000604082015260600190565b634e487b7160e01b600052602160045260246000fd5b600060ff83168061418657614186613f7d565b8060ff84160691505092915050565b600060ff821660ff8416808210156141af576141af613c97565b90039392505050565b6000826141c7576141c7613f7d565b500490565b6000602082840312156141de57600080fd5b5051919050565b6020808252600e908201526d736c6963655f6f766572666c6f7760901b60408201526060019056feab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47a2646970667358221220c5206368b967f84defb752fed54341831da8d4493f79dd8f7c874c113cd227e564736f6c634300080c0033
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.