Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ChallengeManager
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 100 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "../libraries/DelegateCallAware.sol"; import "../osp/IOneStepProofEntry.sol"; import "../state/GlobalState.sol"; import "./IChallengeResultReceiver.sol"; import "./ChallengeLib.sol"; import "./IChallengeManager.sol"; import {NO_CHAL_INDEX} from "../libraries/Constants.sol"; contract ChallengeManager is DelegateCallAware, IChallengeManager { using GlobalStateLib for GlobalState; using MachineLib for Machine; using ChallengeLib for ChallengeLib.Challenge; enum ChallengeModeRequirement { ANY, BLOCK, EXECUTION } string private constant NO_CHAL = "NO_CHAL"; uint256 private constant MAX_CHALLENGE_DEGREE = 40; uint64 public totalChallengesCreated; mapping(uint256 => ChallengeLib.Challenge) public challenges; IChallengeResultReceiver public resultReceiver; ISequencerInbox public sequencerInbox; IBridge public bridge; IOneStepProofEntry public osp; function challengeInfo(uint64 challengeIndex) external view override returns (ChallengeLib.Challenge memory) { return challenges[challengeIndex]; } modifier takeTurn( uint64 challengeIndex, ChallengeLib.SegmentSelection calldata selection, ChallengeModeRequirement expectedMode ) { ChallengeLib.Challenge storage challenge = challenges[challengeIndex]; require(msg.sender == currentResponder(challengeIndex), "CHAL_SENDER"); require(!isTimedOut(challengeIndex), "CHAL_DEADLINE"); if (expectedMode == ChallengeModeRequirement.ANY) { require(challenge.mode != ChallengeLib.ChallengeMode.NONE, NO_CHAL); } else if (expectedMode == ChallengeModeRequirement.BLOCK) { require(challenge.mode == ChallengeLib.ChallengeMode.BLOCK, "CHAL_NOT_BLOCK"); } else if (expectedMode == ChallengeModeRequirement.EXECUTION) { require(challenge.mode == ChallengeLib.ChallengeMode.EXECUTION, "CHAL_NOT_EXECUTION"); } else { assert(false); } require( challenge.challengeStateHash == ChallengeLib.hashChallengeState( selection.oldSegmentsStart, selection.oldSegmentsLength, selection.oldSegments ), "BIS_STATE" ); if ( selection.oldSegments.length < 2 || selection.challengePosition >= selection.oldSegments.length - 1 ) { revert("BAD_CHALLENGE_POS"); } _; if (challenge.mode == ChallengeLib.ChallengeMode.NONE) { // Early return since challenge must have terminated return; } ChallengeLib.Participant memory current = challenge.current; current.timeLeft -= block.timestamp - challenge.lastMoveTimestamp; challenge.current = challenge.next; challenge.next = current; challenge.lastMoveTimestamp = block.timestamp; } function initialize( IChallengeResultReceiver resultReceiver_, ISequencerInbox sequencerInbox_, IBridge bridge_, IOneStepProofEntry osp_ ) external override onlyDelegated { require(address(resultReceiver) == address(0), "ALREADY_INIT"); require(address(resultReceiver_) != address(0), "NO_RESULT_RECEIVER"); resultReceiver = resultReceiver_; sequencerInbox = sequencerInbox_; bridge = bridge_; osp = osp_; } function createChallenge( bytes32 wasmModuleRoot_, MachineStatus[2] calldata startAndEndMachineStatuses_, GlobalState[2] calldata startAndEndGlobalStates_, uint64 numBlocks, address asserter_, address challenger_, uint256 asserterTimeLeft_, uint256 challengerTimeLeft_ ) external override returns (uint64) { require(msg.sender == address(resultReceiver), "ONLY_ROLLUP_CHAL"); bytes32[] memory segments = new bytes32[](2); segments[0] = ChallengeLib.blockStateHash( startAndEndMachineStatuses_[0], startAndEndGlobalStates_[0].hash() ); segments[1] = ChallengeLib.blockStateHash( startAndEndMachineStatuses_[1], startAndEndGlobalStates_[1].hash() ); uint64 challengeIndex = ++totalChallengesCreated; // The following is an assertion since it should never be possible, but it's an important invariant assert(challengeIndex != NO_CHAL_INDEX); ChallengeLib.Challenge storage challenge = challenges[challengeIndex]; challenge.wasmModuleRoot = wasmModuleRoot_; // See validator/assertion.go ExecutionState RequiredBatches() for reasoning uint64 maxInboxMessagesRead = startAndEndGlobalStates_[1].getInboxPosition(); if ( startAndEndMachineStatuses_[1] == MachineStatus.ERRORED || startAndEndGlobalStates_[1].getPositionInMessage() > 0 ) { maxInboxMessagesRead++; } challenge.maxInboxMessages = maxInboxMessagesRead; challenge.next = ChallengeLib.Participant({addr: asserter_, timeLeft: asserterTimeLeft_}); challenge.current = ChallengeLib.Participant({ addr: challenger_, timeLeft: challengerTimeLeft_ }); challenge.lastMoveTimestamp = block.timestamp; challenge.mode = ChallengeLib.ChallengeMode.BLOCK; emit InitiatedChallenge( challengeIndex, startAndEndGlobalStates_[0], startAndEndGlobalStates_[1] ); completeBisection(challengeIndex, 0, numBlocks, segments); return challengeIndex; } /** * @notice Initiate the next round in the bisection by objecting to execution correctness with a bisection * of an execution segment with the same length but a different endpoint. This is either the initial move * or follows another execution objection */ function bisectExecution( uint64 challengeIndex, ChallengeLib.SegmentSelection calldata selection, bytes32[] calldata newSegments ) external takeTurn(challengeIndex, selection, ChallengeModeRequirement.ANY) { (uint256 challengeStart, uint256 challengeLength) = ChallengeLib.extractChallengeSegment( selection ); require(challengeLength > 1, "TOO_SHORT"); { uint256 expectedDegree = challengeLength; if (expectedDegree > MAX_CHALLENGE_DEGREE) { expectedDegree = MAX_CHALLENGE_DEGREE; } require(newSegments.length == expectedDegree + 1, "WRONG_DEGREE"); } requireValidBisection(selection, newSegments[0], newSegments[newSegments.length - 1]); completeBisection(challengeIndex, challengeStart, challengeLength, newSegments); } function challengeExecution( uint64 challengeIndex, ChallengeLib.SegmentSelection calldata selection, MachineStatus[2] calldata machineStatuses, bytes32[2] calldata globalStateHashes, uint256 numSteps ) external takeTurn(challengeIndex, selection, ChallengeModeRequirement.BLOCK) { require(numSteps >= 1, "CHALLENGE_TOO_SHORT"); require(numSteps <= OneStepProofEntryLib.MAX_STEPS, "CHALLENGE_TOO_LONG"); requireValidBisection( selection, ChallengeLib.blockStateHash(machineStatuses[0], globalStateHashes[0]), ChallengeLib.blockStateHash(machineStatuses[1], globalStateHashes[1]) ); ChallengeLib.Challenge storage challenge = challenges[challengeIndex]; (uint256 executionChallengeAtSteps, uint256 challengeLength) = ChallengeLib .extractChallengeSegment(selection); require(challengeLength == 1, "TOO_LONG"); if (machineStatuses[0] != MachineStatus.FINISHED) { // If the machine is in a halted state, it can't change require( machineStatuses[0] == machineStatuses[1] && globalStateHashes[0] == globalStateHashes[1], "HALTED_CHANGE" ); _currentWin(challengeIndex, ChallengeTerminationType.BLOCK_PROOF); return; } if (machineStatuses[1] == MachineStatus.ERRORED) { // If the machine errors, it must return to the previous global state require(globalStateHashes[0] == globalStateHashes[1], "ERROR_CHANGE"); } bytes32[] memory segments = new bytes32[](2); segments[0] = ChallengeLib.getStartMachineHash( globalStateHashes[0], challenge.wasmModuleRoot ); segments[1] = ChallengeLib.getEndMachineHash(machineStatuses[1], globalStateHashes[1]); challenge.mode = ChallengeLib.ChallengeMode.EXECUTION; completeBisection(challengeIndex, 0, numSteps, segments); emit ExecutionChallengeBegun(challengeIndex, executionChallengeAtSteps); } function oneStepProveExecution( uint64 challengeIndex, ChallengeLib.SegmentSelection calldata selection, bytes calldata proof ) external takeTurn(challengeIndex, selection, ChallengeModeRequirement.EXECUTION) { ChallengeLib.Challenge storage challenge = challenges[challengeIndex]; uint256 challengeStart; { uint256 challengeLength; (challengeStart, challengeLength) = ChallengeLib.extractChallengeSegment(selection); require(challengeLength == 1, "TOO_LONG"); } bytes32 afterHash = osp.proveOneStep( ExecutionContext({maxInboxMessagesRead: challenge.maxInboxMessages, bridge: bridge}), challengeStart, selection.oldSegments[selection.challengePosition], proof ); require( afterHash != selection.oldSegments[selection.challengePosition + 1], "SAME_OSP_END" ); emit OneStepProofCompleted(challengeIndex); _currentWin(challengeIndex, ChallengeTerminationType.EXECUTION_PROOF); } function timeout(uint64 challengeIndex) external override { require(challenges[challengeIndex].mode != ChallengeLib.ChallengeMode.NONE, NO_CHAL); require(isTimedOut(challengeIndex), "TIMEOUT_DEADLINE"); _nextWin(challengeIndex, ChallengeTerminationType.TIMEOUT); } function clearChallenge(uint64 challengeIndex) external override { require(msg.sender == address(resultReceiver), "NOT_RES_RECEIVER"); require(challenges[challengeIndex].mode != ChallengeLib.ChallengeMode.NONE, NO_CHAL); delete challenges[challengeIndex]; emit ChallengeEnded(challengeIndex, ChallengeTerminationType.CLEARED); } function currentResponder(uint64 challengeIndex) public view override returns (address) { return challenges[challengeIndex].current.addr; } function currentResponderTimeLeft(uint64 challengeIndex) public view override returns (uint256) { return challenges[challengeIndex].current.timeLeft; } function isTimedOut(uint64 challengeIndex) public view override returns (bool) { return challenges[challengeIndex].isTimedOut(); } function requireValidBisection( ChallengeLib.SegmentSelection calldata selection, bytes32 startHash, bytes32 endHash ) private pure { require(selection.oldSegments[selection.challengePosition] == startHash, "WRONG_START"); require(selection.oldSegments[selection.challengePosition + 1] != endHash, "SAME_END"); } function completeBisection( uint64 challengeIndex, uint256 challengeStart, uint256 challengeLength, bytes32[] memory newSegments ) private { assert(challengeLength >= 1); assert(newSegments.length >= 2); bytes32 challengeStateHash = ChallengeLib.hashChallengeState( challengeStart, challengeLength, newSegments ); challenges[challengeIndex].challengeStateHash = challengeStateHash; emit Bisected( challengeIndex, challengeStateHash, challengeStart, challengeLength, newSegments ); } /// @dev This function causes the mode of the challenge to be set to NONE by deleting the challenge function _nextWin(uint64 challengeIndex, ChallengeTerminationType reason) private { ChallengeLib.Challenge storage challenge = challenges[challengeIndex]; address next = challenge.next.addr; address current = challenge.current.addr; delete challenges[challengeIndex]; resultReceiver.completeChallenge(challengeIndex, next, current); emit ChallengeEnded(challengeIndex, reason); } /** * @dev this currently sets a challenge hash of 0 - no move is possible for the next participant to progress the * state. It is assumed that wherever this function is consumed, the turn is then adjusted for the opposite party * to timeout. This is done as a safety measure so challenges can only be resolved by timeouts during mainnet beta. */ function _currentWin( uint64 challengeIndex, ChallengeTerminationType /* reason */ ) private { ChallengeLib.Challenge storage challenge = challenges[challengeIndex]; challenge.challengeStateHash = bytes32(0); // address next = challenge.next.addr; // address current = challenge.current.addr; // delete challenges[challengeIndex]; // resultReceiver.completeChallenge(challengeIndex, current, next); // emit ChallengeEnded(challengeIndex, reason); } }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import {NotOwner} from "./Error.sol"; /// @dev A stateless contract that allows you to infer if the current call has been delegated or not /// Pattern used here is from UUPS implementation by the OpenZeppelin team abstract contract DelegateCallAware { address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegate call. This allows a function to be * callable on the proxy contract but not on the logic contract. */ modifier onlyDelegated() { require(address(this) != __self, "Function must be called through delegatecall"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __self, "Function must not be called through delegatecall"); _; } /// @dev Check that msg.sender is the current EIP 1967 proxy admin modifier onlyProxyOwner() { // Storage slot with the admin of the proxy contract // This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1 bytes32 slot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; address admin; assembly { admin := sload(slot) } if (msg.sender != admin) revert NotOwner(msg.sender, admin); _; } }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./IOneStepProver.sol"; library OneStepProofEntryLib { uint256 internal constant MAX_STEPS = 1 << 43; } interface IOneStepProofEntry { function proveOneStep( ExecutionContext calldata execCtx, uint256 machineStep, bytes32 beforeHash, bytes calldata proof ) external view returns (bytes32 afterHash); }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; struct GlobalState { bytes32[2] bytes32Vals; uint64[2] u64Vals; } library GlobalStateLib { uint16 internal constant BYTES32_VALS_NUM = 2; uint16 internal constant U64_VALS_NUM = 2; function hash(GlobalState memory state) internal pure returns (bytes32) { return keccak256( abi.encodePacked( "Global state:", state.bytes32Vals[0], state.bytes32Vals[1], state.u64Vals[0], state.u64Vals[1] ) ); } function getBlockHash(GlobalState memory state) internal pure returns (bytes32) { return state.bytes32Vals[0]; } function getSendRoot(GlobalState memory state) internal pure returns (bytes32) { return state.bytes32Vals[1]; } function getInboxPosition(GlobalState memory state) internal pure returns (uint64) { return state.u64Vals[0]; } function getPositionInMessage(GlobalState memory state) internal pure returns (uint64) { return state.u64Vals[1]; } function isEmpty(GlobalState calldata state) internal pure returns (bool) { return (state.bytes32Vals[0] == bytes32(0) && state.bytes32Vals[1] == bytes32(0) && state.u64Vals[0] == 0 && state.u64Vals[1] == 0); } }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; interface IChallengeResultReceiver { function completeChallenge( uint256 challengeIndex, address winner, address loser ) external; }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "../state/Machine.sol"; import "../state/GlobalState.sol"; library ChallengeLib { using MachineLib for Machine; using ChallengeLib for Challenge; /// @dev It's assumed that that uninitialzed challenges have mode NONE enum ChallengeMode { NONE, BLOCK, EXECUTION } struct Participant { address addr; uint256 timeLeft; } struct Challenge { Participant current; Participant next; uint256 lastMoveTimestamp; bytes32 wasmModuleRoot; bytes32 challengeStateHash; uint64 maxInboxMessages; ChallengeMode mode; } struct SegmentSelection { uint256 oldSegmentsStart; uint256 oldSegmentsLength; bytes32[] oldSegments; uint256 challengePosition; } function timeUsedSinceLastMove(Challenge storage challenge) internal view returns (uint256) { return block.timestamp - challenge.lastMoveTimestamp; } function isTimedOut(Challenge storage challenge) internal view returns (bool) { return challenge.timeUsedSinceLastMove() > challenge.current.timeLeft; } function getStartMachineHash(bytes32 globalStateHash, bytes32 wasmModuleRoot) internal pure returns (bytes32) { // Start the value stack with the function call ABI for the entrypoint Value[] memory startingValues = new Value[](3); startingValues[0] = ValueLib.newRefNull(); startingValues[1] = ValueLib.newI32(0); startingValues[2] = ValueLib.newI32(0); ValueArray memory valuesArray = ValueArray({inner: startingValues}); ValueStack memory values = ValueStack({proved: valuesArray, remainingHash: 0}); ValueStack memory internalStack; StackFrameWindow memory frameStack; Machine memory mach = Machine({ status: MachineStatus.RUNNING, valueStack: values, internalStack: internalStack, frameStack: frameStack, globalStateHash: globalStateHash, moduleIdx: 0, functionIdx: 0, functionPc: 0, modulesRoot: wasmModuleRoot }); return mach.hash(); } function getEndMachineHash(MachineStatus status, bytes32 globalStateHash) internal pure returns (bytes32) { if (status == MachineStatus.FINISHED) { return keccak256(abi.encodePacked("Machine finished:", globalStateHash)); } else if (status == MachineStatus.ERRORED) { return keccak256(abi.encodePacked("Machine errored:")); } else if (status == MachineStatus.TOO_FAR) { return keccak256(abi.encodePacked("Machine too far:")); } else { revert("BAD_BLOCK_STATUS"); } } function extractChallengeSegment(SegmentSelection calldata selection) internal pure returns (uint256 segmentStart, uint256 segmentLength) { uint256 oldChallengeDegree = selection.oldSegments.length - 1; segmentLength = selection.oldSegmentsLength / oldChallengeDegree; // Intentionally done before challengeLength is potentially added to for the final segment segmentStart = selection.oldSegmentsStart + segmentLength * selection.challengePosition; if (selection.challengePosition == selection.oldSegments.length - 2) { segmentLength += selection.oldSegmentsLength % oldChallengeDegree; } } function hashChallengeState( uint256 segmentsStart, uint256 segmentsLength, bytes32[] memory segments ) internal pure returns (bytes32) { return keccak256(abi.encodePacked(segmentsStart, segmentsLength, segments)); } function blockStateHash(MachineStatus status, bytes32 globalStateHash) internal pure returns (bytes32) { if (status == MachineStatus.FINISHED) { return keccak256(abi.encodePacked("Block state:", globalStateHash)); } else if (status == MachineStatus.ERRORED) { return keccak256(abi.encodePacked("Block state, errored:", globalStateHash)); } else if (status == MachineStatus.TOO_FAR) { return keccak256(abi.encodePacked("Block state, too far:")); } else { revert("BAD_BLOCK_STATUS"); } } }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "../state/Machine.sol"; import "../bridge/IBridge.sol"; import "../bridge/ISequencerInbox.sol"; import "../osp/IOneStepProofEntry.sol"; import "./IChallengeResultReceiver.sol"; import "./ChallengeLib.sol"; interface IChallengeManager { enum ChallengeTerminationType { TIMEOUT, BLOCK_PROOF, EXECUTION_PROOF, CLEARED } event InitiatedChallenge( uint64 indexed challengeIndex, GlobalState startState, GlobalState endState ); event Bisected( uint64 indexed challengeIndex, bytes32 indexed challengeRoot, uint256 challengedSegmentStart, uint256 challengedSegmentLength, bytes32[] chainHashes ); event ExecutionChallengeBegun(uint64 indexed challengeIndex, uint256 blockSteps); event OneStepProofCompleted(uint64 indexed challengeIndex); event ChallengeEnded(uint64 indexed challengeIndex, ChallengeTerminationType kind); function initialize( IChallengeResultReceiver resultReceiver_, ISequencerInbox sequencerInbox_, IBridge bridge_, IOneStepProofEntry osp_ ) external; function createChallenge( bytes32 wasmModuleRoot_, MachineStatus[2] calldata startAndEndMachineStatuses_, GlobalState[2] calldata startAndEndGlobalStates_, uint64 numBlocks, address asserter_, address challenger_, uint256 asserterTimeLeft_, uint256 challengerTimeLeft_ ) external returns (uint64); function challengeInfo(uint64 challengeIndex_) external view returns (ChallengeLib.Challenge memory); function currentResponder(uint64 challengeIndex) external view returns (address); function isTimedOut(uint64 challengeIndex) external view returns (bool); function currentResponderTimeLeft(uint64 challengeIndex_) external view returns (uint256); function clearChallenge(uint64 challengeIndex_) external; function timeout(uint64 challengeIndex_) external; }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.4; // 90% of Geth's 128KB tx size limit, leaving ~13KB for proving uint256 constant MAX_DATA_SIZE = 117964; uint64 constant NO_CHAL_INDEX = 0;
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.4; /// @dev Init was already called error AlreadyInit(); /// Init was called with param set to zero that must be nonzero error HadZeroInit(); /// @dev Thrown when non owner tries to access an only-owner function /// @param sender The msg.sender who is not the owner /// @param owner The owner address error NotOwner(address sender, address owner); /// @dev Thrown when an address that is not the rollup tries to call an only-rollup function /// @param sender The sender who is not the rollup /// @param rollup The rollup address authorized to call this function error NotRollup(address sender, address rollup); /// @dev Thrown when the contract was not called directly from the origin ie msg.sender != tx.origin error NotOrigin(); /// @dev Provided data was too large /// @param dataLength The length of the data that is too large /// @param maxDataLength The max length the data can be error DataTooLarge(uint256 dataLength, uint256 maxDataLength); /// @dev The provided is not a contract and was expected to be /// @param addr The adddress in question error NotContract(address addr); /// @dev The merkle proof provided was too long /// @param actualLength The length of the merkle proof provided /// @param maxProofLength The max length a merkle proof can have error MerkleProofTooLong(uint256 actualLength, uint256 maxProofLength); /// @dev Thrown when an un-authorized address tries to access an admin function /// @param sender The un-authorized sender /// @param rollup The rollup, which would be authorized /// @param owner The rollup's owner, which would be authorized error NotRollupOrOwner(address sender, address rollup, address owner); // Bridge Errors /// @dev Thrown when an un-authorized address tries to access an only-inbox function /// @param sender The un-authorized sender error NotDelayedInbox(address sender); /// @dev Thrown when an un-authorized address tries to access an only-sequencer-inbox function /// @param sender The un-authorized sender error NotSequencerInbox(address sender); /// @dev Thrown when an un-authorized address tries to access an only-outbox function /// @param sender The un-authorized sender error NotOutbox(address sender); /// @dev the provided outbox address isn't valid /// @param outbox address of outbox being set error InvalidOutboxSet(address outbox); // Inbox Errors /// @dev The contract is paused, so cannot be paused error AlreadyPaused(); /// @dev The contract is unpaused, so cannot be unpaused error AlreadyUnpaused(); /// @dev The contract is paused error Paused(); /// @dev msg.value sent to the inbox isn't high enough error InsufficientValue(uint256 expected, uint256 actual); /// @dev submission cost provided isn't enough to create retryable ticket error InsufficientSubmissionCost(uint256 expected, uint256 actual); /// @dev address not allowed to interact with the given contract error NotAllowedOrigin(address origin); /// @dev used to convey retryable tx data in eth calls without requiring a tx trace /// this follows a pattern similar to EIP-3668 where reverts surface call information error RetryableData( address from, address to, uint256 l2CallValue, uint256 deposit, uint256 maxSubmissionCost, address excessFeeRefundAddress, address callValueRefundAddress, uint256 gasLimit, uint256 maxFeePerGas, bytes data ); // Outbox Errors /// @dev The provided proof was too long /// @param proofLength The length of the too-long proof error ProofTooLong(uint256 proofLength); /// @dev The output index was greater than the maximum /// @param index The output index /// @param maxIndex The max the index could be error PathNotMinimal(uint256 index, uint256 maxIndex); /// @dev The calculated root does not exist /// @param root The calculated root error UnknownRoot(bytes32 root); /// @dev The record has already been spent /// @param index The index of the spent record error AlreadySpent(uint256 index); /// @dev A call to the bridge failed with no return data error BridgeCallFailed(); // Sequencer Inbox Errors /// @dev Thrown when someone attempts to read fewer messages than have already been read error DelayedBackwards(); /// @dev Thrown when someone attempts to read more messages than exist error DelayedTooFar(); /// @dev Force include can only read messages more blocks old than the delay period error ForceIncludeBlockTooSoon(); /// @dev Force include can only read messages more seconds old than the delay period error ForceIncludeTimeTooSoon(); /// @dev The message provided did not match the hash in the delayed inbox error IncorrectMessagePreimage(); /// @dev This can only be called by the batch poster error NotBatchPoster(); /// @dev The sequence number provided to this message was inconsistent with the number of batches already included error BadSequencerNumber(uint256 stored, uint256 received); /// @dev The batch data has the inbox authenticated bit set, but the batch data was not authenticated by the inbox error DataNotAuthenticated(); /// @dev Tried to create an already valid Data Availability Service keyset error AlreadyValidDASKeyset(bytes32); /// @dev Tried to use or invalidate an already invalid Data Availability Service keyset error NoSuchKeyset(bytes32);
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "../state/Machine.sol"; import "../state/Module.sol"; import "../state/Instructions.sol"; import "../bridge/ISequencerInbox.sol"; import "../bridge/IBridge.sol"; struct ExecutionContext { uint256 maxInboxMessagesRead; IBridge bridge; } abstract contract IOneStepProver { function executeOneStep( ExecutionContext memory execCtx, Machine calldata mach, Module calldata mod, Instruction calldata instruction, bytes calldata proof ) external view virtual returns (Machine memory result, Module memory resultMod); }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./ValueStack.sol"; import "./Instructions.sol"; import "./StackFrame.sol"; enum MachineStatus { RUNNING, FINISHED, ERRORED, TOO_FAR } struct Machine { MachineStatus status; ValueStack valueStack; ValueStack internalStack; StackFrameWindow frameStack; bytes32 globalStateHash; uint32 moduleIdx; uint32 functionIdx; uint32 functionPc; bytes32 modulesRoot; } library MachineLib { using StackFrameLib for StackFrameWindow; using ValueStackLib for ValueStack; function hash(Machine memory mach) internal pure returns (bytes32) { // Warning: the non-running hashes are replicated in Challenge if (mach.status == MachineStatus.RUNNING) { return keccak256( abi.encodePacked( "Machine running:", mach.valueStack.hash(), mach.internalStack.hash(), mach.frameStack.hash(), mach.globalStateHash, mach.moduleIdx, mach.functionIdx, mach.functionPc, mach.modulesRoot ) ); } else if (mach.status == MachineStatus.FINISHED) { return keccak256(abi.encodePacked("Machine finished:", mach.globalStateHash)); } else if (mach.status == MachineStatus.ERRORED) { return keccak256(abi.encodePacked("Machine errored:")); } else if (mach.status == MachineStatus.TOO_FAR) { return keccak256(abi.encodePacked("Machine too far:")); } else { revert("BAD_MACH_STATUS"); } } }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./ModuleMemory.sol"; struct Module { bytes32 globalsMerkleRoot; ModuleMemory moduleMemory; bytes32 tablesMerkleRoot; bytes32 functionsMerkleRoot; uint32 internalsOffset; } library ModuleLib { using ModuleMemoryLib for ModuleMemory; function hash(Module memory mod) internal pure returns (bytes32) { return keccak256( abi.encodePacked( "Module:", mod.globalsMerkleRoot, mod.moduleMemory.hash(), mod.tablesMerkleRoot, mod.functionsMerkleRoot, mod.internalsOffset ) ); } }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; struct Instruction { uint16 opcode; uint256 argumentData; } library Instructions { uint16 internal constant UNREACHABLE = 0x00; uint16 internal constant NOP = 0x01; uint16 internal constant RETURN = 0x0F; uint16 internal constant CALL = 0x10; uint16 internal constant CALL_INDIRECT = 0x11; uint16 internal constant LOCAL_GET = 0x20; uint16 internal constant LOCAL_SET = 0x21; uint16 internal constant GLOBAL_GET = 0x23; uint16 internal constant GLOBAL_SET = 0x24; uint16 internal constant I32_LOAD = 0x28; uint16 internal constant I64_LOAD = 0x29; uint16 internal constant F32_LOAD = 0x2A; uint16 internal constant F64_LOAD = 0x2B; uint16 internal constant I32_LOAD8_S = 0x2C; uint16 internal constant I32_LOAD8_U = 0x2D; uint16 internal constant I32_LOAD16_S = 0x2E; uint16 internal constant I32_LOAD16_U = 0x2F; uint16 internal constant I64_LOAD8_S = 0x30; uint16 internal constant I64_LOAD8_U = 0x31; uint16 internal constant I64_LOAD16_S = 0x32; uint16 internal constant I64_LOAD16_U = 0x33; uint16 internal constant I64_LOAD32_S = 0x34; uint16 internal constant I64_LOAD32_U = 0x35; uint16 internal constant I32_STORE = 0x36; uint16 internal constant I64_STORE = 0x37; uint16 internal constant F32_STORE = 0x38; uint16 internal constant F64_STORE = 0x39; uint16 internal constant I32_STORE8 = 0x3A; uint16 internal constant I32_STORE16 = 0x3B; uint16 internal constant I64_STORE8 = 0x3C; uint16 internal constant I64_STORE16 = 0x3D; uint16 internal constant I64_STORE32 = 0x3E; uint16 internal constant MEMORY_SIZE = 0x3F; uint16 internal constant MEMORY_GROW = 0x40; uint16 internal constant DROP = 0x1A; uint16 internal constant SELECT = 0x1B; uint16 internal constant I32_CONST = 0x41; uint16 internal constant I64_CONST = 0x42; uint16 internal constant F32_CONST = 0x43; uint16 internal constant F64_CONST = 0x44; uint16 internal constant I32_EQZ = 0x45; uint16 internal constant I32_RELOP_BASE = 0x46; uint16 internal constant IRELOP_EQ = 0; uint16 internal constant IRELOP_NE = 1; uint16 internal constant IRELOP_LT_S = 2; uint16 internal constant IRELOP_LT_U = 3; uint16 internal constant IRELOP_GT_S = 4; uint16 internal constant IRELOP_GT_U = 5; uint16 internal constant IRELOP_LE_S = 6; uint16 internal constant IRELOP_LE_U = 7; uint16 internal constant IRELOP_GE_S = 8; uint16 internal constant IRELOP_GE_U = 9; uint16 internal constant IRELOP_LAST = IRELOP_GE_U; uint16 internal constant I64_EQZ = 0x50; uint16 internal constant I64_RELOP_BASE = 0x51; uint16 internal constant I32_UNOP_BASE = 0x67; uint16 internal constant IUNOP_CLZ = 0; uint16 internal constant IUNOP_CTZ = 1; uint16 internal constant IUNOP_POPCNT = 2; uint16 internal constant IUNOP_LAST = IUNOP_POPCNT; uint16 internal constant I32_ADD = 0x6A; uint16 internal constant I32_SUB = 0x6B; uint16 internal constant I32_MUL = 0x6C; uint16 internal constant I32_DIV_S = 0x6D; uint16 internal constant I32_DIV_U = 0x6E; uint16 internal constant I32_REM_S = 0x6F; uint16 internal constant I32_REM_U = 0x70; uint16 internal constant I32_AND = 0x71; uint16 internal constant I32_OR = 0x72; uint16 internal constant I32_XOR = 0x73; uint16 internal constant I32_SHL = 0x74; uint16 internal constant I32_SHR_S = 0x75; uint16 internal constant I32_SHR_U = 0x76; uint16 internal constant I32_ROTL = 0x77; uint16 internal constant I32_ROTR = 0x78; uint16 internal constant I64_UNOP_BASE = 0x79; uint16 internal constant I64_ADD = 0x7C; uint16 internal constant I64_SUB = 0x7D; uint16 internal constant I64_MUL = 0x7E; uint16 internal constant I64_DIV_S = 0x7F; uint16 internal constant I64_DIV_U = 0x80; uint16 internal constant I64_REM_S = 0x81; uint16 internal constant I64_REM_U = 0x82; uint16 internal constant I64_AND = 0x83; uint16 internal constant I64_OR = 0x84; uint16 internal constant I64_XOR = 0x85; uint16 internal constant I64_SHL = 0x86; uint16 internal constant I64_SHR_S = 0x87; uint16 internal constant I64_SHR_U = 0x88; uint16 internal constant I64_ROTL = 0x89; uint16 internal constant I64_ROTR = 0x8A; uint16 internal constant I32_WRAP_I64 = 0xA7; uint16 internal constant I64_EXTEND_I32_S = 0xAC; uint16 internal constant I64_EXTEND_I32_U = 0xAD; uint16 internal constant I32_REINTERPRET_F32 = 0xBC; uint16 internal constant I64_REINTERPRET_F64 = 0xBD; uint16 internal constant F32_REINTERPRET_I32 = 0xBE; uint16 internal constant F64_REINTERPRET_I64 = 0xBF; uint16 internal constant I32_EXTEND_8S = 0xC0; uint16 internal constant I32_EXTEND_16S = 0xC1; uint16 internal constant I64_EXTEND_8S = 0xC2; uint16 internal constant I64_EXTEND_16S = 0xC3; uint16 internal constant I64_EXTEND_32S = 0xC4; uint16 internal constant INIT_FRAME = 0x8002; uint16 internal constant ARBITRARY_JUMP = 0x8003; uint16 internal constant ARBITRARY_JUMP_IF = 0x8004; uint16 internal constant MOVE_FROM_STACK_TO_INTERNAL = 0x8005; uint16 internal constant MOVE_FROM_INTERNAL_TO_STACK = 0x8006; uint16 internal constant DUP = 0x8008; uint16 internal constant CROSS_MODULE_CALL = 0x8009; uint16 internal constant CALLER_MODULE_INTERNAL_CALL = 0x800A; uint16 internal constant GET_GLOBAL_STATE_BYTES32 = 0x8010; uint16 internal constant SET_GLOBAL_STATE_BYTES32 = 0x8011; uint16 internal constant GET_GLOBAL_STATE_U64 = 0x8012; uint16 internal constant SET_GLOBAL_STATE_U64 = 0x8013; uint16 internal constant READ_PRE_IMAGE = 0x8020; uint16 internal constant READ_INBOX_MESSAGE = 0x8021; uint16 internal constant HALT_AND_SET_FINISHED = 0x8022; uint256 internal constant INBOX_INDEX_SEQUENCER = 0; uint256 internal constant INBOX_INDEX_DELAYED = 1; function hash(Instruction memory inst) internal pure returns (bytes32) { return keccak256(abi.encodePacked("Instruction:", inst.opcode, inst.argumentData)); } }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 // solhint-disable-next-line compiler-version pragma solidity >=0.6.9 <0.9.0; pragma experimental ABIEncoderV2; import "../libraries/IGasRefunder.sol"; import "./IDelayedMessageProvider.sol"; import "./IBridge.sol"; interface ISequencerInbox is IDelayedMessageProvider { struct MaxTimeVariation { uint256 delayBlocks; uint256 futureBlocks; uint256 delaySeconds; uint256 futureSeconds; } struct TimeBounds { uint64 minTimestamp; uint64 maxTimestamp; uint64 minBlockNumber; uint64 maxBlockNumber; } enum BatchDataLocation { TxInput, SeparateBatchEvent, NoData } event SequencerBatchDelivered( uint256 indexed batchSequenceNumber, bytes32 indexed beforeAcc, bytes32 indexed afterAcc, bytes32 delayedAcc, uint256 afterDelayedMessagesRead, TimeBounds timeBounds, BatchDataLocation dataLocation ); event OwnerFunctionCalled(uint256 indexed id); /// @dev a separate event that emits batch data when this isn't easily accessible in the tx.input event SequencerBatchData(uint256 indexed batchSequenceNumber, bytes data); /// @dev a valid keyset was added event SetValidKeyset(bytes32 indexed keysetHash, bytes keysetBytes); /// @dev a keyset was invalidated event InvalidateKeyset(bytes32 indexed keysetHash); function totalDelayedMessagesRead() external view returns (uint256); function bridge() external view returns (IBridge); /// @dev The size of the batch header // solhint-disable-next-line func-name-mixedcase function HEADER_LENGTH() external view returns (uint256); /// @dev If the first batch data byte after the header has this bit set, /// the sequencer inbox has authenticated the data. Currently not used. // solhint-disable-next-line func-name-mixedcase function DATA_AUTHENTICATED_FLAG() external view returns (bytes1); function rollup() external view returns (IOwnable); function isBatchPoster(address) external view returns (bool); struct DasKeySetInfo { bool isValidKeyset; uint64 creationBlock; } // https://github.com/ethereum/solidity/issues/11826 // function maxTimeVariation() external view returns (MaxTimeVariation calldata); // function dasKeySetInfo(bytes32) external view returns (DasKeySetInfo calldata); /// @notice Force messages from the delayed inbox to be included in the chain /// Callable by any address, but message can only be force-included after maxTimeVariation.delayBlocks and /// maxTimeVariation.delaySeconds has elapsed. As part of normal behaviour the sequencer will include these /// messages so it's only necessary to call this if the sequencer is down, or not including any delayed messages. /// @param _totalDelayedMessagesRead The total number of messages to read up to /// @param kind The kind of the last message to be included /// @param l1BlockAndTime The l1 block and the l1 timestamp of the last message to be included /// @param baseFeeL1 The l1 gas price of the last message to be included /// @param sender The sender of the last message to be included /// @param messageDataHash The messageDataHash of the last message to be included function forceInclusion( uint256 _totalDelayedMessagesRead, uint8 kind, uint64[2] calldata l1BlockAndTime, uint256 baseFeeL1, address sender, bytes32 messageDataHash ) external; function inboxAccs(uint256 index) external view returns (bytes32); function batchCount() external view returns (uint256); function isValidKeysetHash(bytes32 ksHash) external view returns (bool); /// @notice the creation block is intended to still be available after a keyset is deleted function getKeysetCreationBlock(bytes32 ksHash) external view returns (uint256); // ---------- BatchPoster functions ---------- function addSequencerL2BatchFromOrigin( uint256 sequenceNumber, bytes calldata data, uint256 afterDelayedMessagesRead, IGasRefunder gasRefunder ) external; function addSequencerL2Batch( uint256 sequenceNumber, bytes calldata data, uint256 afterDelayedMessagesRead, IGasRefunder gasRefunder ) external; // ---------- onlyRollupOrOwner functions ---------- /** * @notice Set max delay for sequencer inbox * @param maxTimeVariation_ the maximum time variation parameters */ function setMaxTimeVariation(MaxTimeVariation memory maxTimeVariation_) external; /** * @notice Updates whether an address is authorized to be a batch poster at the sequencer inbox * @param addr the address * @param isBatchPoster_ if the specified address should be authorized as a batch poster */ function setIsBatchPoster(address addr, bool isBatchPoster_) external; /** * @notice Makes Data Availability Service keyset valid * @param keysetBytes bytes of the serialized keyset */ function setValidKeyset(bytes calldata keysetBytes) external; /** * @notice Invalidates a Data Availability Service keyset * @param ksHash hash of the keyset */ function invalidateKeysetHash(bytes32 ksHash) external; // ---------- initializer ---------- function initialize(IBridge bridge_, MaxTimeVariation calldata maxTimeVariation_) external; }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 // solhint-disable-next-line compiler-version pragma solidity >=0.6.9 <0.9.0; import "./IOwnable.sol"; interface IBridge { event MessageDelivered( uint256 indexed messageIndex, bytes32 indexed beforeInboxAcc, address inbox, uint8 kind, address sender, bytes32 messageDataHash, uint256 baseFeeL1, uint64 timestamp ); event BridgeCallTriggered( address indexed outbox, address indexed to, uint256 value, bytes data ); event InboxToggle(address indexed inbox, bool enabled); event OutboxToggle(address indexed outbox, bool enabled); event SequencerInboxUpdated(address newSequencerInbox); function allowedDelayedInboxList(uint256) external returns (address); function allowedOutboxList(uint256) external returns (address); /// @dev Accumulator for delayed inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message. function delayedInboxAccs(uint256) external view returns (bytes32); /// @dev Accumulator for sequencer inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message. function sequencerInboxAccs(uint256) external view returns (bytes32); function rollup() external view returns (IOwnable); function sequencerInbox() external view returns (address); function activeOutbox() external view returns (address); function allowedDelayedInboxes(address inbox) external view returns (bool); function allowedOutboxes(address outbox) external view returns (bool); /** * @dev Enqueue a message in the delayed inbox accumulator. * These messages are later sequenced in the SequencerInbox, either * by the sequencer as part of a normal batch, or by force inclusion. */ function enqueueDelayedMessage( uint8 kind, address sender, bytes32 messageDataHash ) external payable returns (uint256); function executeCall( address to, uint256 value, bytes calldata data ) external returns (bool success, bytes memory returnData); function delayedMessageCount() external view returns (uint256); function sequencerMessageCount() external view returns (uint256); // ---------- onlySequencerInbox functions ---------- function enqueueSequencerMessage(bytes32 dataHash, uint256 afterDelayedMessagesRead) external returns ( uint256 seqMessageIndex, bytes32 beforeAcc, bytes32 delayedAcc, bytes32 acc ); /** * @dev Allows the sequencer inbox to submit a delayed message of the batchPostingReport type * This is done through a separate function entrypoint instead of allowing the sequencer inbox * to call `enqueueDelayedMessage` to avoid the gas overhead of an extra SLOAD in either * every delayed inbox or every sequencer inbox call. */ function submitBatchSpendingReport(address batchPoster, bytes32 dataHash) external returns (uint256 msgNum); // ---------- onlyRollupOrOwner functions ---------- function setSequencerInbox(address _sequencerInbox) external; function setDelayedInbox(address inbox, bool enabled) external; function setOutbox(address inbox, bool enabled) external; // ---------- initializer ---------- function initialize(IOwnable rollup_) external; }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./Value.sol"; import "./ValueArray.sol"; struct ValueStack { ValueArray proved; bytes32 remainingHash; } library ValueStackLib { using ValueLib for Value; using ValueArrayLib for ValueArray; function hash(ValueStack memory stack) internal pure returns (bytes32 h) { h = stack.remainingHash; uint256 len = stack.proved.length(); for (uint256 i = 0; i < len; i++) { h = keccak256(abi.encodePacked("Value stack:", stack.proved.get(i).hash(), h)); } } function peek(ValueStack memory stack) internal pure returns (Value memory) { uint256 len = stack.proved.length(); return stack.proved.get(len - 1); } function pop(ValueStack memory stack) internal pure returns (Value memory) { return stack.proved.pop(); } function push(ValueStack memory stack, Value memory val) internal pure { return stack.proved.push(val); } }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./Value.sol"; struct StackFrame { Value returnPc; bytes32 localsMerkleRoot; uint32 callerModule; uint32 callerModuleInternals; } struct StackFrameWindow { StackFrame[] proved; bytes32 remainingHash; } library StackFrameLib { using ValueLib for Value; function hash(StackFrame memory frame) internal pure returns (bytes32) { return keccak256( abi.encodePacked( "Stack frame:", frame.returnPc.hash(), frame.localsMerkleRoot, frame.callerModule, frame.callerModuleInternals ) ); } function hash(StackFrameWindow memory window) internal pure returns (bytes32 h) { h = window.remainingHash; for (uint256 i = 0; i < window.proved.length; i++) { h = keccak256(abi.encodePacked("Stack frame stack:", hash(window.proved[i]), h)); } } function peek(StackFrameWindow memory window) internal pure returns (StackFrame memory) { require(window.proved.length == 1, "BAD_WINDOW_LENGTH"); return window.proved[0]; } function pop(StackFrameWindow memory window) internal pure returns (StackFrame memory frame) { require(window.proved.length == 1, "BAD_WINDOW_LENGTH"); frame = window.proved[0]; window.proved = new StackFrame[](0); } function push(StackFrameWindow memory window, StackFrame memory frame) internal pure { StackFrame[] memory newProved = new StackFrame[](window.proved.length + 1); for (uint256 i = 0; i < window.proved.length; i++) { newProved[i] = window.proved[i]; } newProved[window.proved.length] = frame; window.proved = newProved; } }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; enum ValueType { I32, I64, F32, F64, REF_NULL, FUNC_REF, INTERNAL_REF } struct Value { ValueType valueType; uint256 contents; } library ValueLib { function hash(Value memory val) internal pure returns (bytes32) { return keccak256(abi.encodePacked("Value:", val.valueType, val.contents)); } function maxValueType() internal pure returns (ValueType) { return ValueType.INTERNAL_REF; } function assumeI32(Value memory val) internal pure returns (uint32) { uint256 uintval = uint256(val.contents); require(val.valueType == ValueType.I32, "NOT_I32"); require(uintval < (1 << 32), "BAD_I32"); return uint32(uintval); } function assumeI64(Value memory val) internal pure returns (uint64) { uint256 uintval = uint256(val.contents); require(val.valueType == ValueType.I64, "NOT_I64"); require(uintval < (1 << 64), "BAD_I64"); return uint64(uintval); } function newRefNull() internal pure returns (Value memory) { return Value({valueType: ValueType.REF_NULL, contents: 0}); } function newI32(uint32 x) internal pure returns (Value memory) { return Value({valueType: ValueType.I32, contents: uint256(x)}); } function newI64(uint64 x) internal pure returns (Value memory) { return Value({valueType: ValueType.I64, contents: uint256(x)}); } function newBoolean(bool x) internal pure returns (Value memory) { if (x) { return newI32(uint32(1)); } else { return newI32(uint32(0)); } } }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./Value.sol"; struct ValueArray { Value[] inner; } library ValueArrayLib { function get(ValueArray memory arr, uint256 index) internal pure returns (Value memory) { return arr.inner[index]; } function set( ValueArray memory arr, uint256 index, Value memory val ) internal pure { arr.inner[index] = val; } function length(ValueArray memory arr) internal pure returns (uint256) { return arr.inner.length; } function push(ValueArray memory arr, Value memory val) internal pure { Value[] memory newInner = new Value[](arr.inner.length + 1); for (uint256 i = 0; i < arr.inner.length; i++) { newInner[i] = arr.inner[i]; } newInner[arr.inner.length] = val; arr.inner = newInner; } function pop(ValueArray memory arr) internal pure returns (Value memory popped) { popped = arr.inner[arr.inner.length - 1]; Value[] memory newInner = new Value[](arr.inner.length - 1); for (uint256 i = 0; i < newInner.length; i++) { newInner[i] = arr.inner[i]; } arr.inner = newInner; } }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./MerkleProof.sol"; import "./Deserialize.sol"; struct ModuleMemory { uint64 size; uint64 maxSize; bytes32 merkleRoot; } library ModuleMemoryLib { using MerkleProofLib for MerkleProof; function hash(ModuleMemory memory mem) internal pure returns (bytes32) { return keccak256(abi.encodePacked("Memory:", mem.size, mem.maxSize, mem.merkleRoot)); } function proveLeaf( ModuleMemory memory mem, uint256 leafIdx, bytes calldata proof, uint256 startOffset ) internal pure returns ( bytes32 contents, uint256 offset, MerkleProof memory merkle ) { offset = startOffset; (contents, offset) = Deserialize.b32(proof, offset); (merkle, offset) = Deserialize.merkleProof(proof, offset); bytes32 recomputedRoot = merkle.computeRootFromMemory(leafIdx, contents); require(recomputedRoot == mem.merkleRoot, "WRONG_MEM_ROOT"); } }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./Value.sol"; import "./Instructions.sol"; import "./Module.sol"; struct MerkleProof { bytes32[] counterparts; } library MerkleProofLib { using ModuleLib for Module; using ValueLib for Value; function computeRootFromValue( MerkleProof memory proof, uint256 index, Value memory leaf ) internal pure returns (bytes32) { return computeRootUnsafe(proof, index, leaf.hash(), "Value merkle tree:"); } function computeRootFromInstruction( MerkleProof memory proof, uint256 index, Instruction memory inst ) internal pure returns (bytes32) { return computeRootUnsafe(proof, index, Instructions.hash(inst), "Instruction merkle tree:"); } function computeRootFromFunction( MerkleProof memory proof, uint256 index, bytes32 codeRoot ) internal pure returns (bytes32) { bytes32 h = keccak256(abi.encodePacked("Function:", codeRoot)); return computeRootUnsafe(proof, index, h, "Function merkle tree:"); } function computeRootFromMemory( MerkleProof memory proof, uint256 index, bytes32 contents ) internal pure returns (bytes32) { bytes32 h = keccak256(abi.encodePacked("Memory leaf:", contents)); return computeRootUnsafe(proof, index, h, "Memory merkle tree:"); } function computeRootFromElement( MerkleProof memory proof, uint256 index, bytes32 funcTypeHash, Value memory val ) internal pure returns (bytes32) { bytes32 h = keccak256(abi.encodePacked("Table element:", funcTypeHash, val.hash())); return computeRootUnsafe(proof, index, h, "Table element merkle tree:"); } function computeRootFromTable( MerkleProof memory proof, uint256 index, uint8 tableType, uint64 tableSize, bytes32 elementsRoot ) internal pure returns (bytes32) { bytes32 h = keccak256(abi.encodePacked("Table:", tableType, tableSize, elementsRoot)); return computeRootUnsafe(proof, index, h, "Table merkle tree:"); } function computeRootFromModule( MerkleProof memory proof, uint256 index, Module memory mod ) internal pure returns (bytes32) { return computeRootUnsafe(proof, index, mod.hash(), "Module merkle tree:"); } // WARNING: leafHash must be computed in such a way that it cannot be a non-leaf hash. function computeRootUnsafe( MerkleProof memory proof, uint256 index, bytes32 leafHash, string memory prefix ) internal pure returns (bytes32 h) { h = leafHash; for (uint256 layer = 0; layer < proof.counterparts.length; layer++) { if (index & 1 == 0) { h = keccak256(abi.encodePacked(prefix, h, proof.counterparts[layer])); } else { h = keccak256(abi.encodePacked(prefix, proof.counterparts[layer], h)); } index >>= 1; } } }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./Value.sol"; import "./ValueStack.sol"; import "./Machine.sol"; import "./Instructions.sol"; import "./StackFrame.sol"; import "./MerkleProof.sol"; import "./ModuleMemory.sol"; import "./Module.sol"; import "./GlobalState.sol"; library Deserialize { function u8(bytes calldata proof, uint256 startOffset) internal pure returns (uint8 ret, uint256 offset) { offset = startOffset; ret = uint8(proof[offset]); offset++; } function u16(bytes calldata proof, uint256 startOffset) internal pure returns (uint16 ret, uint256 offset) { offset = startOffset; for (uint256 i = 0; i < 16 / 8; i++) { ret <<= 8; ret |= uint8(proof[offset]); offset++; } } function u32(bytes calldata proof, uint256 startOffset) internal pure returns (uint32 ret, uint256 offset) { offset = startOffset; for (uint256 i = 0; i < 32 / 8; i++) { ret <<= 8; ret |= uint8(proof[offset]); offset++; } } function u64(bytes calldata proof, uint256 startOffset) internal pure returns (uint64 ret, uint256 offset) { offset = startOffset; for (uint256 i = 0; i < 64 / 8; i++) { ret <<= 8; ret |= uint8(proof[offset]); offset++; } } function u256(bytes calldata proof, uint256 startOffset) internal pure returns (uint256 ret, uint256 offset) { offset = startOffset; for (uint256 i = 0; i < 256 / 8; i++) { ret <<= 8; ret |= uint8(proof[offset]); offset++; } } function b32(bytes calldata proof, uint256 startOffset) internal pure returns (bytes32 ret, uint256 offset) { offset = startOffset; uint256 retInt; (retInt, offset) = u256(proof, offset); ret = bytes32(retInt); } function value(bytes calldata proof, uint256 startOffset) internal pure returns (Value memory val, uint256 offset) { offset = startOffset; uint8 typeInt = uint8(proof[offset]); offset++; require(typeInt <= uint8(ValueLib.maxValueType()), "BAD_VALUE_TYPE"); uint256 contents; (contents, offset) = u256(proof, offset); val = Value({valueType: ValueType(typeInt), contents: contents}); } function valueStack(bytes calldata proof, uint256 startOffset) internal pure returns (ValueStack memory stack, uint256 offset) { offset = startOffset; bytes32 remainingHash; (remainingHash, offset) = b32(proof, offset); uint256 provedLength; (provedLength, offset) = u256(proof, offset); Value[] memory proved = new Value[](provedLength); for (uint256 i = 0; i < proved.length; i++) { (proved[i], offset) = value(proof, offset); } stack = ValueStack({proved: ValueArray(proved), remainingHash: remainingHash}); } function instruction(bytes calldata proof, uint256 startOffset) internal pure returns (Instruction memory inst, uint256 offset) { offset = startOffset; uint16 opcode; uint256 data; (opcode, offset) = u16(proof, offset); (data, offset) = u256(proof, offset); inst = Instruction({opcode: opcode, argumentData: data}); } function stackFrame(bytes calldata proof, uint256 startOffset) internal pure returns (StackFrame memory window, uint256 offset) { offset = startOffset; Value memory returnPc; bytes32 localsMerkleRoot; uint32 callerModule; uint32 callerModuleInternals; (returnPc, offset) = value(proof, offset); (localsMerkleRoot, offset) = b32(proof, offset); (callerModule, offset) = u32(proof, offset); (callerModuleInternals, offset) = u32(proof, offset); window = StackFrame({ returnPc: returnPc, localsMerkleRoot: localsMerkleRoot, callerModule: callerModule, callerModuleInternals: callerModuleInternals }); } function stackFrameWindow(bytes calldata proof, uint256 startOffset) internal pure returns (StackFrameWindow memory window, uint256 offset) { offset = startOffset; bytes32 remainingHash; (remainingHash, offset) = b32(proof, offset); StackFrame[] memory proved; if (proof[offset] != 0) { offset++; proved = new StackFrame[](1); (proved[0], offset) = stackFrame(proof, offset); } else { offset++; proved = new StackFrame[](0); } window = StackFrameWindow({proved: proved, remainingHash: remainingHash}); } function moduleMemory(bytes calldata proof, uint256 startOffset) internal pure returns (ModuleMemory memory mem, uint256 offset) { offset = startOffset; uint64 size; uint64 maxSize; bytes32 root; (size, offset) = u64(proof, offset); (maxSize, offset) = u64(proof, offset); (root, offset) = b32(proof, offset); mem = ModuleMemory({size: size, maxSize: maxSize, merkleRoot: root}); } function module(bytes calldata proof, uint256 startOffset) internal pure returns (Module memory mod, uint256 offset) { offset = startOffset; bytes32 globalsMerkleRoot; ModuleMemory memory mem; bytes32 tablesMerkleRoot; bytes32 functionsMerkleRoot; uint32 internalsOffset; (globalsMerkleRoot, offset) = b32(proof, offset); (mem, offset) = moduleMemory(proof, offset); (tablesMerkleRoot, offset) = b32(proof, offset); (functionsMerkleRoot, offset) = b32(proof, offset); (internalsOffset, offset) = u32(proof, offset); mod = Module({ globalsMerkleRoot: globalsMerkleRoot, moduleMemory: mem, tablesMerkleRoot: tablesMerkleRoot, functionsMerkleRoot: functionsMerkleRoot, internalsOffset: internalsOffset }); } function globalState(bytes calldata proof, uint256 startOffset) internal pure returns (GlobalState memory state, uint256 offset) { offset = startOffset; // using constant ints for array size requires newer solidity bytes32[2] memory bytes32Vals; uint64[2] memory u64Vals; for (uint8 i = 0; i < GlobalStateLib.BYTES32_VALS_NUM; i++) { (bytes32Vals[i], offset) = b32(proof, offset); } for (uint8 i = 0; i < GlobalStateLib.U64_VALS_NUM; i++) { (u64Vals[i], offset) = u64(proof, offset); } state = GlobalState({bytes32Vals: bytes32Vals, u64Vals: u64Vals}); } function machine(bytes calldata proof, uint256 startOffset) internal pure returns (Machine memory mach, uint256 offset) { offset = startOffset; MachineStatus status; { uint8 statusU8; (statusU8, offset) = u8(proof, offset); if (statusU8 == 0) { status = MachineStatus.RUNNING; } else if (statusU8 == 1) { status = MachineStatus.FINISHED; } else if (statusU8 == 2) { status = MachineStatus.ERRORED; } else if (statusU8 == 3) { status = MachineStatus.TOO_FAR; } else { revert("UNKNOWN_MACH_STATUS"); } } ValueStack memory values; ValueStack memory internalStack; bytes32 globalStateHash; uint32 moduleIdx; uint32 functionIdx; uint32 functionPc; StackFrameWindow memory frameStack; bytes32 modulesRoot; (values, offset) = valueStack(proof, offset); (internalStack, offset) = valueStack(proof, offset); (frameStack, offset) = stackFrameWindow(proof, offset); (globalStateHash, offset) = b32(proof, offset); (moduleIdx, offset) = u32(proof, offset); (functionIdx, offset) = u32(proof, offset); (functionPc, offset) = u32(proof, offset); (modulesRoot, offset) = b32(proof, offset); mach = Machine({ status: status, valueStack: values, internalStack: internalStack, frameStack: frameStack, globalStateHash: globalStateHash, moduleIdx: moduleIdx, functionIdx: functionIdx, functionPc: functionPc, modulesRoot: modulesRoot }); } function merkleProof(bytes calldata proof, uint256 startOffset) internal pure returns (MerkleProof memory merkle, uint256 offset) { offset = startOffset; uint8 length; (length, offset) = u8(proof, offset); bytes32[] memory counterparts = new bytes32[](length); for (uint8 i = 0; i < length; i++) { (counterparts[i], offset) = b32(proof, offset); } merkle = MerkleProof(counterparts); } }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 // solhint-disable-next-line compiler-version pragma solidity >=0.6.9 <0.9.0; interface IGasRefunder { function onGasSpent( address payable spender, uint256 gasUsed, uint256 calldataSize ) external returns (bool success); } abstract contract GasRefundEnabled { /// @dev this refunds the sender for execution costs of the tx /// calldata costs are only refunded if `msg.sender == tx.origin` to guarantee the value refunded relates to charging /// for the `tx.input`. this avoids a possible attack where you generate large calldata from a contract and get over-refunded modifier refundsGas(IGasRefunder gasRefunder) { uint256 startGasLeft = gasleft(); _; if (address(gasRefunder) != address(0)) { uint256 calldataSize = 0; // if triggered in a contract call, the spender may be overrefunded by appending dummy data to the call // so we check if it is a top level call, which would mean the sender paid calldata as part of tx.input // solhint-disable-next-line avoid-tx-origin if (msg.sender == tx.origin) { assembly { calldataSize := calldatasize() } } gasRefunder.onGasSpent(payable(msg.sender), startGasLeft - gasleft(), calldataSize); } } }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 // solhint-disable-next-line compiler-version pragma solidity >=0.6.9 <0.9.0; interface IDelayedMessageProvider { /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator event InboxMessageDelivered(uint256 indexed messageNum, bytes data); /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator /// same as InboxMessageDelivered but the batch data is available in tx.input event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum); }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 // solhint-disable-next-line compiler-version pragma solidity >=0.4.21 <0.9.0; interface IOwnable { function owner() external view returns (address); }
{ "optimizer": { "enabled": true, "runs": 100 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"challengeIndex","type":"uint64"},{"indexed":true,"internalType":"bytes32","name":"challengeRoot","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"challengedSegmentStart","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"challengedSegmentLength","type":"uint256"},{"indexed":false,"internalType":"bytes32[]","name":"chainHashes","type":"bytes32[]"}],"name":"Bisected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"challengeIndex","type":"uint64"},{"indexed":false,"internalType":"enum IChallengeManager.ChallengeTerminationType","name":"kind","type":"uint8"}],"name":"ChallengeEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"challengeIndex","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"blockSteps","type":"uint256"}],"name":"ExecutionChallengeBegun","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"challengeIndex","type":"uint64"},{"components":[{"internalType":"bytes32[2]","name":"bytes32Vals","type":"bytes32[2]"},{"internalType":"uint64[2]","name":"u64Vals","type":"uint64[2]"}],"indexed":false,"internalType":"struct GlobalState","name":"startState","type":"tuple"},{"components":[{"internalType":"bytes32[2]","name":"bytes32Vals","type":"bytes32[2]"},{"internalType":"uint64[2]","name":"u64Vals","type":"uint64[2]"}],"indexed":false,"internalType":"struct GlobalState","name":"endState","type":"tuple"}],"name":"InitiatedChallenge","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"challengeIndex","type":"uint64"}],"name":"OneStepProofCompleted","type":"event"},{"inputs":[{"internalType":"uint64","name":"challengeIndex","type":"uint64"},{"components":[{"internalType":"uint256","name":"oldSegmentsStart","type":"uint256"},{"internalType":"uint256","name":"oldSegmentsLength","type":"uint256"},{"internalType":"bytes32[]","name":"oldSegments","type":"bytes32[]"},{"internalType":"uint256","name":"challengePosition","type":"uint256"}],"internalType":"struct ChallengeLib.SegmentSelection","name":"selection","type":"tuple"},{"internalType":"bytes32[]","name":"newSegments","type":"bytes32[]"}],"name":"bisectExecution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bridge","outputs":[{"internalType":"contract IBridge","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"challengeIndex","type":"uint64"},{"components":[{"internalType":"uint256","name":"oldSegmentsStart","type":"uint256"},{"internalType":"uint256","name":"oldSegmentsLength","type":"uint256"},{"internalType":"bytes32[]","name":"oldSegments","type":"bytes32[]"},{"internalType":"uint256","name":"challengePosition","type":"uint256"}],"internalType":"struct ChallengeLib.SegmentSelection","name":"selection","type":"tuple"},{"internalType":"enum MachineStatus[2]","name":"machineStatuses","type":"uint8[2]"},{"internalType":"bytes32[2]","name":"globalStateHashes","type":"bytes32[2]"},{"internalType":"uint256","name":"numSteps","type":"uint256"}],"name":"challengeExecution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"challengeIndex","type":"uint64"}],"name":"challengeInfo","outputs":[{"components":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"timeLeft","type":"uint256"}],"internalType":"struct ChallengeLib.Participant","name":"current","type":"tuple"},{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"timeLeft","type":"uint256"}],"internalType":"struct ChallengeLib.Participant","name":"next","type":"tuple"},{"internalType":"uint256","name":"lastMoveTimestamp","type":"uint256"},{"internalType":"bytes32","name":"wasmModuleRoot","type":"bytes32"},{"internalType":"bytes32","name":"challengeStateHash","type":"bytes32"},{"internalType":"uint64","name":"maxInboxMessages","type":"uint64"},{"internalType":"enum ChallengeLib.ChallengeMode","name":"mode","type":"uint8"}],"internalType":"struct ChallengeLib.Challenge","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"challenges","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"timeLeft","type":"uint256"}],"internalType":"struct ChallengeLib.Participant","name":"current","type":"tuple"},{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"timeLeft","type":"uint256"}],"internalType":"struct ChallengeLib.Participant","name":"next","type":"tuple"},{"internalType":"uint256","name":"lastMoveTimestamp","type":"uint256"},{"internalType":"bytes32","name":"wasmModuleRoot","type":"bytes32"},{"internalType":"bytes32","name":"challengeStateHash","type":"bytes32"},{"internalType":"uint64","name":"maxInboxMessages","type":"uint64"},{"internalType":"enum ChallengeLib.ChallengeMode","name":"mode","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"challengeIndex","type":"uint64"}],"name":"clearChallenge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"wasmModuleRoot_","type":"bytes32"},{"internalType":"enum MachineStatus[2]","name":"startAndEndMachineStatuses_","type":"uint8[2]"},{"components":[{"internalType":"bytes32[2]","name":"bytes32Vals","type":"bytes32[2]"},{"internalType":"uint64[2]","name":"u64Vals","type":"uint64[2]"}],"internalType":"struct GlobalState[2]","name":"startAndEndGlobalStates_","type":"tuple[2]"},{"internalType":"uint64","name":"numBlocks","type":"uint64"},{"internalType":"address","name":"asserter_","type":"address"},{"internalType":"address","name":"challenger_","type":"address"},{"internalType":"uint256","name":"asserterTimeLeft_","type":"uint256"},{"internalType":"uint256","name":"challengerTimeLeft_","type":"uint256"}],"name":"createChallenge","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"challengeIndex","type":"uint64"}],"name":"currentResponder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"challengeIndex","type":"uint64"}],"name":"currentResponderTimeLeft","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IChallengeResultReceiver","name":"resultReceiver_","type":"address"},{"internalType":"contract ISequencerInbox","name":"sequencerInbox_","type":"address"},{"internalType":"contract IBridge","name":"bridge_","type":"address"},{"internalType":"contract IOneStepProofEntry","name":"osp_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"challengeIndex","type":"uint64"}],"name":"isTimedOut","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"challengeIndex","type":"uint64"},{"components":[{"internalType":"uint256","name":"oldSegmentsStart","type":"uint256"},{"internalType":"uint256","name":"oldSegmentsLength","type":"uint256"},{"internalType":"bytes32[]","name":"oldSegments","type":"bytes32[]"},{"internalType":"uint256","name":"challengePosition","type":"uint256"}],"internalType":"struct ChallengeLib.SegmentSelection","name":"selection","type":"tuple"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"oneStepProveExecution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"osp","outputs":[{"internalType":"contract IOneStepProofEntry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"resultReceiver","outputs":[{"internalType":"contract IChallengeResultReceiver","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sequencerInbox","outputs":[{"internalType":"contract ISequencerInbox","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"challengeIndex","type":"uint64"}],"name":"timeout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalChallengesCreated","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040523060805234801561001457600080fd5b50608051613069610030600039600061126b01526130696000f3fe608060405234801561001057600080fd5b50600436106100eb5760003560e01c80639ede42b9116100925780639ede42b91461025c578063a521b0321461027f578063c8fdb65b14610292578063d248d124146102cd578063e78cea92146102e0578063ee35f327146102f3578063f26a62c614610306578063f8c8765e14610319578063fb7be0a11461032c57600080fd5b806314eab5e7146100f05780631b45c86a1461012057806323a9ef23146101355780633504f1d71461016057806356e9df97146101735780635ef489e6146101865780637fd07a9c146101995780638f1d3776146101b9575b600080fd5b6101036100fe36600461263e565b61033f565b6040516001600160401b0390911681526020015b60405180910390f35b61013361012e3660046126d1565b610647565b005b6101486101433660046126d1565b610717565b6040516001600160a01b039091168152602001610117565b600254610148906001600160a01b031681565b6101336101813660046126d1565b61073b565b600054610103906001600160401b031681565b6101ac6101a73660046126d1565b6108a9565b604051610117919061272e565b6102496101c73660046127a0565b6001602081815260009283526040928390208351808501855281546001600160a01b0390811682529382015481840152845180860190955260028201549093168452600381015491840191909152600481015460058201546006830154600790930154939493919290916001600160401b03811690600160401b900460ff1687565b60405161011797969594939291906127b9565b61026f61026a3660046126d1565b610982565b6040519015158152602001610117565b61013361028d366004612816565b6109a9565b6102bf6102a03660046126d1565b6001600160401b03166000908152600160208190526040909120015490565b604051908152602001610117565b6101336102db3660046128ba565b610e1f565b600454610148906001600160a01b031681565b600354610148906001600160a01b031681565b600554610148906001600160a01b031681565b61013361032736600461294c565b611260565b61013361033a3660046129a8565b6113d1565b6002546000906001600160a01b031633146103945760405162461bcd60e51b815260206004820152601060248201526f13d3931657d493d313155417d0d2105360821b60448201526064015b60405180910390fd5b6040805160028082526060820183526000926020830190803683370190505090506103ea6103c560208b018b612a4c565b6103e58a60005b608002018036038101906103e09190612b0b565b611a41565b611ac2565b816000815181106103fd576103fd612a36565b602090810291909101015261042c8960016020020160208101906104219190612a4c565b6103e58a60016103cc565b8160018151811061043f5761043f612a36565b60209081029190910101526000805481908190610464906001600160401b0316612bb9565b91906101000a8154816001600160401b0302191690836001600160401b031602179055905060006001600160401b0316816001600160401b031614156104ac576104ac612be0565b6001600160401b0381166000908152600160205260408120600581018d9055906104e66104e1368d90038d0160808e01612b0b565b611be6565b905060026104fa60408e0160208f01612a4c565b600381111561050b5761050b612704565b14806105395750600061052e610529368e90038e0160808f01612b0b565b611bfb565b6001600160401b0316115b1561054c578061054881612bb9565b9150505b6007820180546040805180820182526001600160a01b038d811680835260209283018d90526002880180546001600160a01b03199081169092179055600388018d905583518085018552918e16808352919092018b90528654909116178555600185018990554260048601556001600160401b0384811668ffffffffffffffffff1990931692909217600160401b179092559051908416907f76604fe17af46c9b5f53ffe99ff23e0f655dab91886b07ac1fc0254319f7145a90610616908e906080820190612c40565b60405180910390a26106348360008c6001600160401b031687611c0a565b5090925050505b98975050505050505050565b60006001600160401b038216600090815260016020526040902060070154600160401b900460ff16600281111561068057610680612704565b1415604051806040016040528060078152602001661393d7d0d2105360ca1b815250906106c05760405162461bcd60e51b815260040161038b9190612c5c565b506106ca81610982565b6107095760405162461bcd60e51b815260206004820152601060248201526f54494d454f55545f444541444c494e4560801b604482015260640161038b565b610714816000611ca0565b50565b6001600160401b03166000908152600160205260409020546001600160a01b031690565b6002546001600160a01b031633146107885760405162461bcd60e51b815260206004820152601060248201526f2727aa2fa922a9afa922a1a2a4ab22a960811b604482015260640161038b565b60006001600160401b038216600090815260016020526040902060070154600160401b900460ff1660028111156107c1576107c1612704565b1415604051806040016040528060078152602001661393d7d0d2105360ca1b815250906108015760405162461bcd60e51b815260040161038b9190612c5c565b506001600160401b038116600081815260016020819052604080832080546001600160a01b031990811682559281018490556002810180549093169092556003808301849055600483018490556005830184905560068301939093556007909101805468ffffffffffffffffff19169055517ffdaece6c274a4b56af16761f83fd6b1062823192630ea08e019fdf9b2d747f409161089e91612cb1565b60405180910390a250565b6108b1612599565b6001600160401b0382811660009081526001602081815260409283902083516101208101855281546001600160a01b0390811660e0830190815294830154610100830152938152845180860186526002808401549095168152600383015481850152928101929092526004810154938201939093526005830154606082015260068301546080820152600783015493841660a08201529260c0840191600160401b90910460ff169081111561096857610968612704565b600281111561097957610979612704565b90525092915050565b6001600160401b03811660009081526001602052604081206109a390611dce565b92915050565b6001600160401b0384166000908152600160205260408120859185916109ce84610717565b6001600160a01b0316336001600160a01b0316146109fe5760405162461bcd60e51b815260040161038b90612ccb565b610a0784610982565b15610a245760405162461bcd60e51b815260040161038b90612cf0565b6000826002811115610a3857610a38612704565b1415610aa65760006007820154600160401b900460ff166002811115610a6057610a60612704565b1415604051806040016040528060078152602001661393d7d0d2105360ca1b81525090610aa05760405162461bcd60e51b815260040161038b9190612c5c565b50610b65565b6001826002811115610aba57610aba612704565b1415610b045760016007820154600160401b900460ff166002811115610ae257610ae2612704565b14610aff5760405162461bcd60e51b815260040161038b90612d17565b610b65565b6002826002811115610b1857610b18612704565b1415610b5d5760026007820154600160401b900460ff166002811115610b4057610b40612704565b14610aff5760405162461bcd60e51b815260040161038b90612d3f565b610b65612be0565b610bb383356020850135610b7c6040870187612d6b565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611de692505050565b816006015414610bd55760405162461bcd60e51b815260040161038b90612dbb565b6002610be46040850185612d6b565b90501080610c0f57506001610bfc6040850185612d6b565b610c07929150612dde565b836060013510155b15610c2c5760405162461bcd60e51b815260040161038b90612df5565b600080610c3889611e1d565b9150915060018111610c785760405162461bcd60e51b81526020600482015260096024820152681513d3d7d4d213d49560ba1b604482015260640161038b565b806028811115610c86575060285b610c91816001612e20565b8814610cce5760405162461bcd60e51b815260206004820152600c60248201526b57524f4e475f44454752454560a01b604482015260640161038b565b50610d188989896000818110610ce657610ce6612a36565b602002919091013590508a8a610cfd600182612dde565b818110610d0c57610d0c612a36565b90506020020135611eae565b610d578a83838b8b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611c0a92505050565b50600090505b6007820154600160401b900460ff166002811115610d7d57610d7d612704565b1415610d895750610e16565b6040805180820190915281546001600160a01b03168152600182015460208201526004820154610db99042612dde565b81602001818151610dca9190612dde565b90525060028201805483546001600160a01b038083166001600160a01b031992831617865560038601805460018801558551929093169116179091556020909101519055426004909101555b50505050505050565b6001600160401b038416600090815260016020526040902084908490600290610e4784610717565b6001600160a01b0316336001600160a01b031614610e775760405162461bcd60e51b815260040161038b90612ccb565b610e8084610982565b15610e9d5760405162461bcd60e51b815260040161038b90612cf0565b6000826002811115610eb157610eb1612704565b1415610f1f5760006007820154600160401b900460ff166002811115610ed957610ed9612704565b1415604051806040016040528060078152602001661393d7d0d2105360ca1b81525090610f195760405162461bcd60e51b815260040161038b9190612c5c565b50610fde565b6001826002811115610f3357610f33612704565b1415610f7d5760016007820154600160401b900460ff166002811115610f5b57610f5b612704565b14610f785760405162461bcd60e51b815260040161038b90612d17565b610fde565b6002826002811115610f9157610f91612704565b1415610fd65760026007820154600160401b900460ff166002811115610fb957610fb9612704565b14610f785760405162461bcd60e51b815260040161038b90612d3f565b610fde612be0565b610ff583356020850135610b7c6040870187612d6b565b8160060154146110175760405162461bcd60e51b815260040161038b90612dbb565b60026110266040850185612d6b565b905010806110515750600161103e6040850185612d6b565b611049929150612dde565b836060013510155b1561106e5760405162461bcd60e51b815260040161038b90612df5565b6001600160401b038816600090815260016020526040812090806110918a611e1d565b9092509050600181146110b65760405162461bcd60e51b815260040161038b90612e38565b5060055460408051808201825260078501546001600160401b031681526004546001600160a01b0390811660208301526000931691635d3adcfb91908590611100908f018f612d6b565b8f6060013581811061111457611114612a36565b905060200201358d8d6040518663ffffffff1660e01b815260040161113d959493929190612e5a565b60206040518083038186803b15801561115557600080fd5b505afa158015611169573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118d9190612eb1565b905061119c60408b018b612d6b565b6111ab60608d01356001612e20565b8181106111ba576111ba612a36565b905060200201358114156111ff5760405162461bcd60e51b815260206004820152600c60248201526b14d0535157d3d4d417d1539160a21b604482015260640161038b565b6040516001600160401b038c16907fc2cc42e04ff8c36de71c6a2937ea9f161dd0dd9e175f00caa26e5200643c781e90600090a26112548b6001600160401b0316600090815260016020526040812060060155565b5060009150610d5d9050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614156112ee5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b19195b1959d85d1958d85b1b60a21b606482015260840161038b565b6002546001600160a01b0316156113365760405162461bcd60e51b815260206004820152600c60248201526b1053149150511657d253925560a21b604482015260640161038b565b6001600160a01b0384166113815760405162461bcd60e51b81526020600482015260126024820152712727afa922a9aaa62a2fa922a1a2a4ab22a960711b604482015260640161038b565b600280546001600160a01b039586166001600160a01b0319918216179091556003805494861694821694909417909355600480549285169284169290921790915560058054919093169116179055565b6001600160401b0385166000908152600160208190526040909120869186916113f984610717565b6001600160a01b0316336001600160a01b0316146114295760405162461bcd60e51b815260040161038b90612ccb565b61143284610982565b1561144f5760405162461bcd60e51b815260040161038b90612cf0565b600082600281111561146357611463612704565b14156114d15760006007820154600160401b900460ff16600281111561148b5761148b612704565b1415604051806040016040528060078152602001661393d7d0d2105360ca1b815250906114cb5760405162461bcd60e51b815260040161038b9190612c5c565b50611590565b60018260028111156114e5576114e5612704565b141561152f5760016007820154600160401b900460ff16600281111561150d5761150d612704565b1461152a5760405162461bcd60e51b815260040161038b90612d17565b611590565b600282600281111561154357611543612704565b14156115885760026007820154600160401b900460ff16600281111561156b5761156b612704565b1461152a5760405162461bcd60e51b815260040161038b90612d3f565b611590612be0565b6115a783356020850135610b7c6040870187612d6b565b8160060154146115c95760405162461bcd60e51b815260040161038b90612dbb565b60026115d86040850185612d6b565b90501080611603575060016115f06040850185612d6b565b6115fb929150612dde565b836060013510155b156116205760405162461bcd60e51b815260040161038b90612df5565b60018510156116675760405162461bcd60e51b815260206004820152601360248201527210d2105313115391d157d513d3d7d4d213d495606a1b604482015260640161038b565b650800000000008511156116b25760405162461bcd60e51b81526020600482015260126024820152714348414c4c454e47455f544f4f5f4c4f4e4760701b604482015260640161038b565b6116f4886116d46116c660208b018b612a4c565b8960005b6020020135611ac2565b6116ef6116e760408c0160208d01612a4c565b8a60016116ca565b611eae565b6001600160401b038916600090815260016020526040812090806117178b611e1d565b915091508060011461173b5760405162461bcd60e51b815260040161038b90612e38565b600161174a60208c018c612a4c565b600381111561175b5761175b612704565b146118155761177060408b0160208c01612a4c565b600381111561178157611781612704565b61178e60208c018c612a4c565b600381111561179f5761179f612704565b1480156117b05750883560208a0135145b6117ec5760405162461bcd60e51b815260206004820152600d60248201526c48414c5445445f4348414e474560981b604482015260640161038b565b61180d8c6001600160401b0316600090815260016020526040812060060155565b50505061197c565b600261182760408c0160208d01612a4c565b600381111561183857611838612704565b141561188157883560208a0135146118815760405162461bcd60e51b815260206004820152600c60248201526b4552524f525f4348414e474560a01b604482015260640161038b565b60408051600280825260608201835260009260208301908036833750505060058501549091506118b3908b3590611f83565b816000815181106118c6576118c6612a36565b60209081029190910101526118f48b60016020020160208101906118ea9190612a4c565b60208c013561210f565b8160018151811061190757611907612a36565b602090810291909101015260078401805460ff60401b1916600160411b1790556119348d60008b84611c0a565b8c6001600160401b03167f24e032e170243bbea97e140174b22dc7e54fb85925afbf52c70e001cd6af16db8460405161196f91815260200190565b60405180910390a2505050505b60006007820154600160401b900460ff16600281111561199e5761199e612704565b14156119aa5750611a37565b6040805180820190915281546001600160a01b031681526001820154602082015260048201546119da9042612dde565b816020018181516119eb9190612dde565b90525060028201805483546001600160a01b038083166001600160a01b031992831617865560038601805460018801558551929093169116179091556020909101519055426004909101555b5050505050505050565b80518051602091820151828401518051908401516040516c23b637b130b61039ba30ba329d60991b95810195909552602d850193909352604d8401919091526001600160c01b031960c091821b8116606d85015291901b166075820152600090607d015b604051602081830303815290604052805190602001209050919050565b60006001836003811115611ad857611ad8612704565b1415611b1e576040516b213637b1b59039ba30ba329d60a11b6020820152602c8101839052604c015b6040516020818303038152906040528051906020012090506109a3565b6002836003811115611b3257611b32612704565b1415611b685760405174213637b1b59039ba30ba32961032b93937b932b21d60591b602082015260358101839052605501611b01565b6003836003811115611b7c57611b7c612704565b1415611bab5760405174213637b1b59039ba30ba3296103a37b7903330b91d60591b6020820152603501611b01565b60405162461bcd60e51b815260206004820152601060248201526f4241445f424c4f434b5f53544154555360801b604482015260640161038b565b6020810151600090815b602002015192915050565b60208101516000906001611bf0565b6001821015611c1b57611c1b612be0565b600281511015611c2d57611c2d612be0565b6000611c3a848484611de6565b6001600160401b038616600081815260016020526040908190206006018390555191925082917f86b34e9455464834eca718f62d4481437603bb929d8a78ccde5d1bc79fa06d6890611c9190889088908890612eca565b60405180910390a35050505050565b6001600160401b03821660008181526001602081905260408083206002808201805483546001600160a01b0319808216865596850188905595811690915560038301869055600480840187905560058401879055600684019690965560078301805468ffffffffffffffffff1916905590549251630357aa4960e01b8152948501959095526001600160a01b03948516602485018190529285166044850181905290949293909290911690630357aa4990606401600060405180830381600087803b158015611d6e57600080fd5b505af1158015611d82573d6000803e3d6000fd5b50505050846001600160401b03167ffdaece6c274a4b56af16761f83fd6b1062823192630ea08e019fdf9b2d747f4085604051611dbf9190612cb1565b60405180910390a25050505050565b6001810154600090611ddf836121b8565b1192915050565b6000838383604051602001611dfd93929190612f1f565b6040516020818303038152906040528051906020012090505b9392505050565b600080806001611e306040860186612d6b565b611e3b929150612dde565b9050611e4b816020860135612f77565b9150611e5b606085013583612f8b565b611e66908535612e20565b92506002611e776040860186612d6b565b611e82929150612dde565b84606001351415611ea857611e9b816020860135612faa565b611ea59083612e20565b91505b50915091565b81611ebc6040850185612d6b565b8560600135818110611ed057611ed0612a36565b9050602002013514611f125760405162461bcd60e51b815260206004820152600b60248201526a15d493d391d7d4d510549560aa1b604482015260640161038b565b80611f206040850185612d6b565b611f2f60608701356001612e20565b818110611f3e57611f3e612a36565b905060200201351415611f7e5760405162461bcd60e51b815260206004820152600860248201526714d0535157d1539160c21b604482015260640161038b565b505050565b60408051600380825260808201909252600091829190816020015b6040805180820190915260008082526020820152815260200190600190039081611f9e57505060408051808201825260008082526020918201819052825180840190935260048352908201529091508160008151811061200057612000612a36565b602002602001018190525061201560006121ca565b8160018151811061202857612028612a36565b602002602001018190525061203d60006121ca565b8160028151811061205057612050612a36565b60209081029190910181019190915260408051808301825283815281518083019092528082526000928201929092526120a060408051606080820183529181019182529081526000602082015290565b604080518082018252606080825260006020808401829052845161012081018652828152908101879052938401859052908301829052608083018a905260a0830181905260c0830181905260e0830152610100820188905290612102816121fd565b9998505050505050505050565b6000600183600381111561212557612125612704565b141561213c5781604051602001611b019190612fbe565b600283600381111561215057612150612704565b141561217a576040516f26b0b1b434b7329032b93937b932b21d60811b6020820152603001611b01565b600383600381111561218e5761218e612704565b1415611bab576040516f26b0b1b434b732903a37b7903330b91d60811b6020820152603001611b01565b60008160040154426109a39190612dde565b604080518082019091526000808252602082015250604080518082019091526000815263ffffffff909116602082015290565b6000808251600381111561221357612213612704565b14156122c95761222682602001516123b6565b61223383604001516123b6565b612240846060015161243b565b608085015160a086015160c087015160e0808901516101008a01516040516f26b0b1b434b73290393ab73734b7339d60811b602082015260308101999099526050890197909752607088019590955260908701939093526001600160e01b031991831b821660b0870152821b811660b486015291901b1660b883015260bc82015260dc01611aa5565b6001825160038111156122de576122de612704565b14156122f9578160800151604051602001611aa59190612fbe565b60028251600381111561230e5761230e612704565b1415612338576040516f26b0b1b434b7329032b93937b932b21d60811b6020820152603001611aa5565b60038251600381111561234d5761234d612704565b1415612377576040516f26b0b1b434b732903a37b7903330b91d60811b6020820152603001611aa5565b60405162461bcd60e51b815260206004820152600f60248201526e4241445f4d4143485f53544154555360881b604482015260640161038b565b919050565b60208101518151515160005b818110156124345783516123df906123da90836124d4565b61250c565b6040516b2b30b63ab29039ba30b1b59d60a11b6020820152602c810191909152604c8101849052606c01604051602081830303815290604052805190602001209250808061242c90612fe3565b9150506123c2565b5050919050565b602081015160005b8251518110156124ce576124738360000151828151811061246657612466612a36565b6020026020010151612529565b6040517129ba30b1b590333930b6b29039ba30b1b59d60711b602082015260328101919091526052810183905260720160405160208183030381529060405280519060200120915080806124c690612fe3565b915050612443565b50919050565b604080518082019091526000808252602082015282518051839081106124fc576124fc612a36565b6020026020010151905092915050565b600081600001518260200151604051602001611aa5929190612ffe565b6000612538826000015161250c565b602080840151604080860151606087015191516b29ba30b1b590333930b6b29d60a11b94810194909452602c840194909452604c8301919091526001600160e01b031960e093841b8116606c840152921b9091166070820152607401611aa5565b604080516101208101909152600060e08201818152610100830191909152819081526020016125d8604080518082019091526000808252602082015290565b815260006020820181905260408201819052606082018190526080820181905260a09091015290565b80604081018310156109a357600080fd5b80356001600160401b03811681146123b157600080fd5b6001600160a01b038116811461071457600080fd5b600080600080600080600080610200898b03121561265b57600080fd5b8835975061266c8a60208b01612601565b965061016089018a81111561268057600080fd5b60608a01965061268f81612612565b9550506101808901356126a181612629565b93506101a08901356126b281612629565b979a96995094979396929592945050506101c0820135916101e0013590565b6000602082840312156126e357600080fd5b611e1682612612565b80516001600160a01b03168252602090810151910152565b634e487b7160e01b600052602160045260246000fd5b6003811061272a5761272a612704565b9052565b6000610120820190506127428284516126ec565b602083015161275460408401826126ec565b5060408301516080830152606083015160a0830152608083015160c08301526001600160401b0360a08401511660e083015260c083015161279961010084018261271a565b5092915050565b6000602082840312156127b257600080fd5b5035919050565b61012081016127c8828a6126ec565b6127d560408301896126ec565b8660808301528560a08301528460c08301526001600160401b03841660e083015261063b61010083018461271a565b6000608082840312156124ce57600080fd5b6000806000806060858703121561282c57600080fd5b61283585612612565b935060208501356001600160401b038082111561285157600080fd5b61285d88838901612804565b9450604087013591508082111561287357600080fd5b818701915087601f83011261288757600080fd5b81358181111561289657600080fd5b8860208260051b85010111156128ab57600080fd5b95989497505060200194505050565b600080600080606085870312156128d057600080fd5b6128d985612612565b935060208501356001600160401b03808211156128f557600080fd5b61290188838901612804565b9450604087013591508082111561291757600080fd5b818701915087601f83011261292b57600080fd5b81358181111561293a57600080fd5b8860208285010111156128ab57600080fd5b6000806000806080858703121561296257600080fd5b843561296d81612629565b9350602085013561297d81612629565b9250604085013561298d81612629565b9150606085013561299d81612629565b939692955090935050565b600080600080600060e086880312156129c057600080fd5b6129c986612612565b945060208601356001600160401b038111156129e457600080fd5b6129f088828901612804565b945050612a008760408801612601565b9250612a0f8760808801612601565b9497939650919460c0013592915050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a5e57600080fd5b813560048110611e1657600080fd5b604080519081016001600160401b0381118282101715612a8f57612a8f612a20565b60405290565b600082601f830112612aa657600080fd5b604051604081018181106001600160401b0382111715612ac857612ac8612a20565b8060405250806040840185811115612adf57600080fd5b845b81811015612b0057612af281612612565b835260209283019201612ae1565b509195945050505050565b600060808284031215612b1d57600080fd5b604051604081018181106001600160401b0382111715612b3f57612b3f612a20565b604052601f83018413612b5157600080fd5b612b59612a6d565b806040850186811115612b6b57600080fd5b855b81811015612b85578035845260209384019301612b6d565b50818452612b938782612a95565b6020850152509195945050505050565b634e487b7160e01b600052601160045260246000fd5b60006001600160401b0380831681811415612bd657612bd6612ba3565b6001019392505050565b634e487b7160e01b600052600160045260246000fd5b604081833760006040838101828152908301915b6002811015612c39576001600160401b03612c2484612612565b16825260209283019290910190600101612c0a565b5050505050565b6101008101612c4f8285612bf6565b611e166080830184612bf6565b600060208083528351808285015260005b81811015612c8957858101830151858201604001528201612c6d565b81811115612c9b576000604083870101525b50601f01601f1916929092016040019392505050565b6020810160048310612cc557612cc5612704565b91905290565b6020808252600b908201526a21a420a62fa9a2a72222a960a91b604082015260600190565b6020808252600d908201526c4348414c5f444541444c494e4560981b604082015260600190565b6020808252600e908201526d4348414c5f4e4f545f424c4f434b60901b604082015260600190565b60208082526012908201527121a420a62fa727aa2fa2ac22a1aaaa24a7a760711b604082015260600190565b6000808335601e19843603018112612d8257600080fd5b8301803591506001600160401b03821115612d9c57600080fd5b6020019150600581901b3603821315612db457600080fd5b9250929050565b6020808252600990820152684249535f535441544560b81b604082015260600190565b600082821015612df057612df0612ba3565b500390565b6020808252601190820152704241445f4348414c4c454e47455f504f5360781b604082015260600190565b60008219821115612e3357612e33612ba3565b500190565b602080825260089082015267544f4f5f4c4f4e4760c01b604082015260600190565b8551815260018060a01b03602087015116602082015284604082015283606082015260a060808201528160a0820152818360c0830137600081830160c090810191909152601f909201601f19160101949350505050565b600060208284031215612ec357600080fd5b5051919050565b6000606082018583526020858185015260606040850152818551808452608086019150828701935060005b81811015612f1157845183529383019391830191600101612ef5565b509098975050505050505050565b83815260006020848184015260408301845182860160005b82811015612f5357815184529284019290840190600101612f37565b509198975050505050505050565b634e487b7160e01b600052601260045260246000fd5b600082612f8657612f86612f61565b500490565b6000816000190483118215151615612fa557612fa5612ba3565b500290565b600082612fb957612fb9612f61565b500690565b7026b0b1b434b732903334b734b9b432b21d60791b8152601181019190915260310190565b6000600019821415612ff757612ff7612ba3565b5060010190565b652b30b63ab29d60d11b815260006007841061301c5761301c612704565b5060f89290921b600683015260078201526027019056fea2646970667358221220a60bbeb03ccfae7e130a4b359d44672ad8ca4aa7a6c8f0e8b0df3351a625276c64736f6c63430008090033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100eb5760003560e01c80639ede42b9116100925780639ede42b91461025c578063a521b0321461027f578063c8fdb65b14610292578063d248d124146102cd578063e78cea92146102e0578063ee35f327146102f3578063f26a62c614610306578063f8c8765e14610319578063fb7be0a11461032c57600080fd5b806314eab5e7146100f05780631b45c86a1461012057806323a9ef23146101355780633504f1d71461016057806356e9df97146101735780635ef489e6146101865780637fd07a9c146101995780638f1d3776146101b9575b600080fd5b6101036100fe36600461263e565b61033f565b6040516001600160401b0390911681526020015b60405180910390f35b61013361012e3660046126d1565b610647565b005b6101486101433660046126d1565b610717565b6040516001600160a01b039091168152602001610117565b600254610148906001600160a01b031681565b6101336101813660046126d1565b61073b565b600054610103906001600160401b031681565b6101ac6101a73660046126d1565b6108a9565b604051610117919061272e565b6102496101c73660046127a0565b6001602081815260009283526040928390208351808501855281546001600160a01b0390811682529382015481840152845180860190955260028201549093168452600381015491840191909152600481015460058201546006830154600790930154939493919290916001600160401b03811690600160401b900460ff1687565b60405161011797969594939291906127b9565b61026f61026a3660046126d1565b610982565b6040519015158152602001610117565b61013361028d366004612816565b6109a9565b6102bf6102a03660046126d1565b6001600160401b03166000908152600160208190526040909120015490565b604051908152602001610117565b6101336102db3660046128ba565b610e1f565b600454610148906001600160a01b031681565b600354610148906001600160a01b031681565b600554610148906001600160a01b031681565b61013361032736600461294c565b611260565b61013361033a3660046129a8565b6113d1565b6002546000906001600160a01b031633146103945760405162461bcd60e51b815260206004820152601060248201526f13d3931657d493d313155417d0d2105360821b60448201526064015b60405180910390fd5b6040805160028082526060820183526000926020830190803683370190505090506103ea6103c560208b018b612a4c565b6103e58a60005b608002018036038101906103e09190612b0b565b611a41565b611ac2565b816000815181106103fd576103fd612a36565b602090810291909101015261042c8960016020020160208101906104219190612a4c565b6103e58a60016103cc565b8160018151811061043f5761043f612a36565b60209081029190910101526000805481908190610464906001600160401b0316612bb9565b91906101000a8154816001600160401b0302191690836001600160401b031602179055905060006001600160401b0316816001600160401b031614156104ac576104ac612be0565b6001600160401b0381166000908152600160205260408120600581018d9055906104e66104e1368d90038d0160808e01612b0b565b611be6565b905060026104fa60408e0160208f01612a4c565b600381111561050b5761050b612704565b14806105395750600061052e610529368e90038e0160808f01612b0b565b611bfb565b6001600160401b0316115b1561054c578061054881612bb9565b9150505b6007820180546040805180820182526001600160a01b038d811680835260209283018d90526002880180546001600160a01b03199081169092179055600388018d905583518085018552918e16808352919092018b90528654909116178555600185018990554260048601556001600160401b0384811668ffffffffffffffffff1990931692909217600160401b179092559051908416907f76604fe17af46c9b5f53ffe99ff23e0f655dab91886b07ac1fc0254319f7145a90610616908e906080820190612c40565b60405180910390a26106348360008c6001600160401b031687611c0a565b5090925050505b98975050505050505050565b60006001600160401b038216600090815260016020526040902060070154600160401b900460ff16600281111561068057610680612704565b1415604051806040016040528060078152602001661393d7d0d2105360ca1b815250906106c05760405162461bcd60e51b815260040161038b9190612c5c565b506106ca81610982565b6107095760405162461bcd60e51b815260206004820152601060248201526f54494d454f55545f444541444c494e4560801b604482015260640161038b565b610714816000611ca0565b50565b6001600160401b03166000908152600160205260409020546001600160a01b031690565b6002546001600160a01b031633146107885760405162461bcd60e51b815260206004820152601060248201526f2727aa2fa922a9afa922a1a2a4ab22a960811b604482015260640161038b565b60006001600160401b038216600090815260016020526040902060070154600160401b900460ff1660028111156107c1576107c1612704565b1415604051806040016040528060078152602001661393d7d0d2105360ca1b815250906108015760405162461bcd60e51b815260040161038b9190612c5c565b506001600160401b038116600081815260016020819052604080832080546001600160a01b031990811682559281018490556002810180549093169092556003808301849055600483018490556005830184905560068301939093556007909101805468ffffffffffffffffff19169055517ffdaece6c274a4b56af16761f83fd6b1062823192630ea08e019fdf9b2d747f409161089e91612cb1565b60405180910390a250565b6108b1612599565b6001600160401b0382811660009081526001602081815260409283902083516101208101855281546001600160a01b0390811660e0830190815294830154610100830152938152845180860186526002808401549095168152600383015481850152928101929092526004810154938201939093526005830154606082015260068301546080820152600783015493841660a08201529260c0840191600160401b90910460ff169081111561096857610968612704565b600281111561097957610979612704565b90525092915050565b6001600160401b03811660009081526001602052604081206109a390611dce565b92915050565b6001600160401b0384166000908152600160205260408120859185916109ce84610717565b6001600160a01b0316336001600160a01b0316146109fe5760405162461bcd60e51b815260040161038b90612ccb565b610a0784610982565b15610a245760405162461bcd60e51b815260040161038b90612cf0565b6000826002811115610a3857610a38612704565b1415610aa65760006007820154600160401b900460ff166002811115610a6057610a60612704565b1415604051806040016040528060078152602001661393d7d0d2105360ca1b81525090610aa05760405162461bcd60e51b815260040161038b9190612c5c565b50610b65565b6001826002811115610aba57610aba612704565b1415610b045760016007820154600160401b900460ff166002811115610ae257610ae2612704565b14610aff5760405162461bcd60e51b815260040161038b90612d17565b610b65565b6002826002811115610b1857610b18612704565b1415610b5d5760026007820154600160401b900460ff166002811115610b4057610b40612704565b14610aff5760405162461bcd60e51b815260040161038b90612d3f565b610b65612be0565b610bb383356020850135610b7c6040870187612d6b565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611de692505050565b816006015414610bd55760405162461bcd60e51b815260040161038b90612dbb565b6002610be46040850185612d6b565b90501080610c0f57506001610bfc6040850185612d6b565b610c07929150612dde565b836060013510155b15610c2c5760405162461bcd60e51b815260040161038b90612df5565b600080610c3889611e1d565b9150915060018111610c785760405162461bcd60e51b81526020600482015260096024820152681513d3d7d4d213d49560ba1b604482015260640161038b565b806028811115610c86575060285b610c91816001612e20565b8814610cce5760405162461bcd60e51b815260206004820152600c60248201526b57524f4e475f44454752454560a01b604482015260640161038b565b50610d188989896000818110610ce657610ce6612a36565b602002919091013590508a8a610cfd600182612dde565b818110610d0c57610d0c612a36565b90506020020135611eae565b610d578a83838b8b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611c0a92505050565b50600090505b6007820154600160401b900460ff166002811115610d7d57610d7d612704565b1415610d895750610e16565b6040805180820190915281546001600160a01b03168152600182015460208201526004820154610db99042612dde565b81602001818151610dca9190612dde565b90525060028201805483546001600160a01b038083166001600160a01b031992831617865560038601805460018801558551929093169116179091556020909101519055426004909101555b50505050505050565b6001600160401b038416600090815260016020526040902084908490600290610e4784610717565b6001600160a01b0316336001600160a01b031614610e775760405162461bcd60e51b815260040161038b90612ccb565b610e8084610982565b15610e9d5760405162461bcd60e51b815260040161038b90612cf0565b6000826002811115610eb157610eb1612704565b1415610f1f5760006007820154600160401b900460ff166002811115610ed957610ed9612704565b1415604051806040016040528060078152602001661393d7d0d2105360ca1b81525090610f195760405162461bcd60e51b815260040161038b9190612c5c565b50610fde565b6001826002811115610f3357610f33612704565b1415610f7d5760016007820154600160401b900460ff166002811115610f5b57610f5b612704565b14610f785760405162461bcd60e51b815260040161038b90612d17565b610fde565b6002826002811115610f9157610f91612704565b1415610fd65760026007820154600160401b900460ff166002811115610fb957610fb9612704565b14610f785760405162461bcd60e51b815260040161038b90612d3f565b610fde612be0565b610ff583356020850135610b7c6040870187612d6b565b8160060154146110175760405162461bcd60e51b815260040161038b90612dbb565b60026110266040850185612d6b565b905010806110515750600161103e6040850185612d6b565b611049929150612dde565b836060013510155b1561106e5760405162461bcd60e51b815260040161038b90612df5565b6001600160401b038816600090815260016020526040812090806110918a611e1d565b9092509050600181146110b65760405162461bcd60e51b815260040161038b90612e38565b5060055460408051808201825260078501546001600160401b031681526004546001600160a01b0390811660208301526000931691635d3adcfb91908590611100908f018f612d6b565b8f6060013581811061111457611114612a36565b905060200201358d8d6040518663ffffffff1660e01b815260040161113d959493929190612e5a565b60206040518083038186803b15801561115557600080fd5b505afa158015611169573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118d9190612eb1565b905061119c60408b018b612d6b565b6111ab60608d01356001612e20565b8181106111ba576111ba612a36565b905060200201358114156111ff5760405162461bcd60e51b815260206004820152600c60248201526b14d0535157d3d4d417d1539160a21b604482015260640161038b565b6040516001600160401b038c16907fc2cc42e04ff8c36de71c6a2937ea9f161dd0dd9e175f00caa26e5200643c781e90600090a26112548b6001600160401b0316600090815260016020526040812060060155565b5060009150610d5d9050565b306001600160a01b037f0000000000000000000000001c78b622961f27ccc2f9ba65e2ba5d5eb301a4451614156112ee5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b19195b1959d85d1958d85b1b60a21b606482015260840161038b565b6002546001600160a01b0316156113365760405162461bcd60e51b815260206004820152600c60248201526b1053149150511657d253925560a21b604482015260640161038b565b6001600160a01b0384166113815760405162461bcd60e51b81526020600482015260126024820152712727afa922a9aaa62a2fa922a1a2a4ab22a960711b604482015260640161038b565b600280546001600160a01b039586166001600160a01b0319918216179091556003805494861694821694909417909355600480549285169284169290921790915560058054919093169116179055565b6001600160401b0385166000908152600160208190526040909120869186916113f984610717565b6001600160a01b0316336001600160a01b0316146114295760405162461bcd60e51b815260040161038b90612ccb565b61143284610982565b1561144f5760405162461bcd60e51b815260040161038b90612cf0565b600082600281111561146357611463612704565b14156114d15760006007820154600160401b900460ff16600281111561148b5761148b612704565b1415604051806040016040528060078152602001661393d7d0d2105360ca1b815250906114cb5760405162461bcd60e51b815260040161038b9190612c5c565b50611590565b60018260028111156114e5576114e5612704565b141561152f5760016007820154600160401b900460ff16600281111561150d5761150d612704565b1461152a5760405162461bcd60e51b815260040161038b90612d17565b611590565b600282600281111561154357611543612704565b14156115885760026007820154600160401b900460ff16600281111561156b5761156b612704565b1461152a5760405162461bcd60e51b815260040161038b90612d3f565b611590612be0565b6115a783356020850135610b7c6040870187612d6b565b8160060154146115c95760405162461bcd60e51b815260040161038b90612dbb565b60026115d86040850185612d6b565b90501080611603575060016115f06040850185612d6b565b6115fb929150612dde565b836060013510155b156116205760405162461bcd60e51b815260040161038b90612df5565b60018510156116675760405162461bcd60e51b815260206004820152601360248201527210d2105313115391d157d513d3d7d4d213d495606a1b604482015260640161038b565b650800000000008511156116b25760405162461bcd60e51b81526020600482015260126024820152714348414c4c454e47455f544f4f5f4c4f4e4760701b604482015260640161038b565b6116f4886116d46116c660208b018b612a4c565b8960005b6020020135611ac2565b6116ef6116e760408c0160208d01612a4c565b8a60016116ca565b611eae565b6001600160401b038916600090815260016020526040812090806117178b611e1d565b915091508060011461173b5760405162461bcd60e51b815260040161038b90612e38565b600161174a60208c018c612a4c565b600381111561175b5761175b612704565b146118155761177060408b0160208c01612a4c565b600381111561178157611781612704565b61178e60208c018c612a4c565b600381111561179f5761179f612704565b1480156117b05750883560208a0135145b6117ec5760405162461bcd60e51b815260206004820152600d60248201526c48414c5445445f4348414e474560981b604482015260640161038b565b61180d8c6001600160401b0316600090815260016020526040812060060155565b50505061197c565b600261182760408c0160208d01612a4c565b600381111561183857611838612704565b141561188157883560208a0135146118815760405162461bcd60e51b815260206004820152600c60248201526b4552524f525f4348414e474560a01b604482015260640161038b565b60408051600280825260608201835260009260208301908036833750505060058501549091506118b3908b3590611f83565b816000815181106118c6576118c6612a36565b60209081029190910101526118f48b60016020020160208101906118ea9190612a4c565b60208c013561210f565b8160018151811061190757611907612a36565b602090810291909101015260078401805460ff60401b1916600160411b1790556119348d60008b84611c0a565b8c6001600160401b03167f24e032e170243bbea97e140174b22dc7e54fb85925afbf52c70e001cd6af16db8460405161196f91815260200190565b60405180910390a2505050505b60006007820154600160401b900460ff16600281111561199e5761199e612704565b14156119aa5750611a37565b6040805180820190915281546001600160a01b031681526001820154602082015260048201546119da9042612dde565b816020018181516119eb9190612dde565b90525060028201805483546001600160a01b038083166001600160a01b031992831617865560038601805460018801558551929093169116179091556020909101519055426004909101555b5050505050505050565b80518051602091820151828401518051908401516040516c23b637b130b61039ba30ba329d60991b95810195909552602d850193909352604d8401919091526001600160c01b031960c091821b8116606d85015291901b166075820152600090607d015b604051602081830303815290604052805190602001209050919050565b60006001836003811115611ad857611ad8612704565b1415611b1e576040516b213637b1b59039ba30ba329d60a11b6020820152602c8101839052604c015b6040516020818303038152906040528051906020012090506109a3565b6002836003811115611b3257611b32612704565b1415611b685760405174213637b1b59039ba30ba32961032b93937b932b21d60591b602082015260358101839052605501611b01565b6003836003811115611b7c57611b7c612704565b1415611bab5760405174213637b1b59039ba30ba3296103a37b7903330b91d60591b6020820152603501611b01565b60405162461bcd60e51b815260206004820152601060248201526f4241445f424c4f434b5f53544154555360801b604482015260640161038b565b6020810151600090815b602002015192915050565b60208101516000906001611bf0565b6001821015611c1b57611c1b612be0565b600281511015611c2d57611c2d612be0565b6000611c3a848484611de6565b6001600160401b038616600081815260016020526040908190206006018390555191925082917f86b34e9455464834eca718f62d4481437603bb929d8a78ccde5d1bc79fa06d6890611c9190889088908890612eca565b60405180910390a35050505050565b6001600160401b03821660008181526001602081905260408083206002808201805483546001600160a01b0319808216865596850188905595811690915560038301869055600480840187905560058401879055600684019690965560078301805468ffffffffffffffffff1916905590549251630357aa4960e01b8152948501959095526001600160a01b03948516602485018190529285166044850181905290949293909290911690630357aa4990606401600060405180830381600087803b158015611d6e57600080fd5b505af1158015611d82573d6000803e3d6000fd5b50505050846001600160401b03167ffdaece6c274a4b56af16761f83fd6b1062823192630ea08e019fdf9b2d747f4085604051611dbf9190612cb1565b60405180910390a25050505050565b6001810154600090611ddf836121b8565b1192915050565b6000838383604051602001611dfd93929190612f1f565b6040516020818303038152906040528051906020012090505b9392505050565b600080806001611e306040860186612d6b565b611e3b929150612dde565b9050611e4b816020860135612f77565b9150611e5b606085013583612f8b565b611e66908535612e20565b92506002611e776040860186612d6b565b611e82929150612dde565b84606001351415611ea857611e9b816020860135612faa565b611ea59083612e20565b91505b50915091565b81611ebc6040850185612d6b565b8560600135818110611ed057611ed0612a36565b9050602002013514611f125760405162461bcd60e51b815260206004820152600b60248201526a15d493d391d7d4d510549560aa1b604482015260640161038b565b80611f206040850185612d6b565b611f2f60608701356001612e20565b818110611f3e57611f3e612a36565b905060200201351415611f7e5760405162461bcd60e51b815260206004820152600860248201526714d0535157d1539160c21b604482015260640161038b565b505050565b60408051600380825260808201909252600091829190816020015b6040805180820190915260008082526020820152815260200190600190039081611f9e57505060408051808201825260008082526020918201819052825180840190935260048352908201529091508160008151811061200057612000612a36565b602002602001018190525061201560006121ca565b8160018151811061202857612028612a36565b602002602001018190525061203d60006121ca565b8160028151811061205057612050612a36565b60209081029190910181019190915260408051808301825283815281518083019092528082526000928201929092526120a060408051606080820183529181019182529081526000602082015290565b604080518082018252606080825260006020808401829052845161012081018652828152908101879052938401859052908301829052608083018a905260a0830181905260c0830181905260e0830152610100820188905290612102816121fd565b9998505050505050505050565b6000600183600381111561212557612125612704565b141561213c5781604051602001611b019190612fbe565b600283600381111561215057612150612704565b141561217a576040516f26b0b1b434b7329032b93937b932b21d60811b6020820152603001611b01565b600383600381111561218e5761218e612704565b1415611bab576040516f26b0b1b434b732903a37b7903330b91d60811b6020820152603001611b01565b60008160040154426109a39190612dde565b604080518082019091526000808252602082015250604080518082019091526000815263ffffffff909116602082015290565b6000808251600381111561221357612213612704565b14156122c95761222682602001516123b6565b61223383604001516123b6565b612240846060015161243b565b608085015160a086015160c087015160e0808901516101008a01516040516f26b0b1b434b73290393ab73734b7339d60811b602082015260308101999099526050890197909752607088019590955260908701939093526001600160e01b031991831b821660b0870152821b811660b486015291901b1660b883015260bc82015260dc01611aa5565b6001825160038111156122de576122de612704565b14156122f9578160800151604051602001611aa59190612fbe565b60028251600381111561230e5761230e612704565b1415612338576040516f26b0b1b434b7329032b93937b932b21d60811b6020820152603001611aa5565b60038251600381111561234d5761234d612704565b1415612377576040516f26b0b1b434b732903a37b7903330b91d60811b6020820152603001611aa5565b60405162461bcd60e51b815260206004820152600f60248201526e4241445f4d4143485f53544154555360881b604482015260640161038b565b919050565b60208101518151515160005b818110156124345783516123df906123da90836124d4565b61250c565b6040516b2b30b63ab29039ba30b1b59d60a11b6020820152602c810191909152604c8101849052606c01604051602081830303815290604052805190602001209250808061242c90612fe3565b9150506123c2565b5050919050565b602081015160005b8251518110156124ce576124738360000151828151811061246657612466612a36565b6020026020010151612529565b6040517129ba30b1b590333930b6b29039ba30b1b59d60711b602082015260328101919091526052810183905260720160405160208183030381529060405280519060200120915080806124c690612fe3565b915050612443565b50919050565b604080518082019091526000808252602082015282518051839081106124fc576124fc612a36565b6020026020010151905092915050565b600081600001518260200151604051602001611aa5929190612ffe565b6000612538826000015161250c565b602080840151604080860151606087015191516b29ba30b1b590333930b6b29d60a11b94810194909452602c840194909452604c8301919091526001600160e01b031960e093841b8116606c840152921b9091166070820152607401611aa5565b604080516101208101909152600060e08201818152610100830191909152819081526020016125d8604080518082019091526000808252602082015290565b815260006020820181905260408201819052606082018190526080820181905260a09091015290565b80604081018310156109a357600080fd5b80356001600160401b03811681146123b157600080fd5b6001600160a01b038116811461071457600080fd5b600080600080600080600080610200898b03121561265b57600080fd5b8835975061266c8a60208b01612601565b965061016089018a81111561268057600080fd5b60608a01965061268f81612612565b9550506101808901356126a181612629565b93506101a08901356126b281612629565b979a96995094979396929592945050506101c0820135916101e0013590565b6000602082840312156126e357600080fd5b611e1682612612565b80516001600160a01b03168252602090810151910152565b634e487b7160e01b600052602160045260246000fd5b6003811061272a5761272a612704565b9052565b6000610120820190506127428284516126ec565b602083015161275460408401826126ec565b5060408301516080830152606083015160a0830152608083015160c08301526001600160401b0360a08401511660e083015260c083015161279961010084018261271a565b5092915050565b6000602082840312156127b257600080fd5b5035919050565b61012081016127c8828a6126ec565b6127d560408301896126ec565b8660808301528560a08301528460c08301526001600160401b03841660e083015261063b61010083018461271a565b6000608082840312156124ce57600080fd5b6000806000806060858703121561282c57600080fd5b61283585612612565b935060208501356001600160401b038082111561285157600080fd5b61285d88838901612804565b9450604087013591508082111561287357600080fd5b818701915087601f83011261288757600080fd5b81358181111561289657600080fd5b8860208260051b85010111156128ab57600080fd5b95989497505060200194505050565b600080600080606085870312156128d057600080fd5b6128d985612612565b935060208501356001600160401b03808211156128f557600080fd5b61290188838901612804565b9450604087013591508082111561291757600080fd5b818701915087601f83011261292b57600080fd5b81358181111561293a57600080fd5b8860208285010111156128ab57600080fd5b6000806000806080858703121561296257600080fd5b843561296d81612629565b9350602085013561297d81612629565b9250604085013561298d81612629565b9150606085013561299d81612629565b939692955090935050565b600080600080600060e086880312156129c057600080fd5b6129c986612612565b945060208601356001600160401b038111156129e457600080fd5b6129f088828901612804565b945050612a008760408801612601565b9250612a0f8760808801612601565b9497939650919460c0013592915050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a5e57600080fd5b813560048110611e1657600080fd5b604080519081016001600160401b0381118282101715612a8f57612a8f612a20565b60405290565b600082601f830112612aa657600080fd5b604051604081018181106001600160401b0382111715612ac857612ac8612a20565b8060405250806040840185811115612adf57600080fd5b845b81811015612b0057612af281612612565b835260209283019201612ae1565b509195945050505050565b600060808284031215612b1d57600080fd5b604051604081018181106001600160401b0382111715612b3f57612b3f612a20565b604052601f83018413612b5157600080fd5b612b59612a6d565b806040850186811115612b6b57600080fd5b855b81811015612b85578035845260209384019301612b6d565b50818452612b938782612a95565b6020850152509195945050505050565b634e487b7160e01b600052601160045260246000fd5b60006001600160401b0380831681811415612bd657612bd6612ba3565b6001019392505050565b634e487b7160e01b600052600160045260246000fd5b604081833760006040838101828152908301915b6002811015612c39576001600160401b03612c2484612612565b16825260209283019290910190600101612c0a565b5050505050565b6101008101612c4f8285612bf6565b611e166080830184612bf6565b600060208083528351808285015260005b81811015612c8957858101830151858201604001528201612c6d565b81811115612c9b576000604083870101525b50601f01601f1916929092016040019392505050565b6020810160048310612cc557612cc5612704565b91905290565b6020808252600b908201526a21a420a62fa9a2a72222a960a91b604082015260600190565b6020808252600d908201526c4348414c5f444541444c494e4560981b604082015260600190565b6020808252600e908201526d4348414c5f4e4f545f424c4f434b60901b604082015260600190565b60208082526012908201527121a420a62fa727aa2fa2ac22a1aaaa24a7a760711b604082015260600190565b6000808335601e19843603018112612d8257600080fd5b8301803591506001600160401b03821115612d9c57600080fd5b6020019150600581901b3603821315612db457600080fd5b9250929050565b6020808252600990820152684249535f535441544560b81b604082015260600190565b600082821015612df057612df0612ba3565b500390565b6020808252601190820152704241445f4348414c4c454e47455f504f5360781b604082015260600190565b60008219821115612e3357612e33612ba3565b500190565b602080825260089082015267544f4f5f4c4f4e4760c01b604082015260600190565b8551815260018060a01b03602087015116602082015284604082015283606082015260a060808201528160a0820152818360c0830137600081830160c090810191909152601f909201601f19160101949350505050565b600060208284031215612ec357600080fd5b5051919050565b6000606082018583526020858185015260606040850152818551808452608086019150828701935060005b81811015612f1157845183529383019391830191600101612ef5565b509098975050505050505050565b83815260006020848184015260408301845182860160005b82811015612f5357815184529284019290840190600101612f37565b509198975050505050505050565b634e487b7160e01b600052601260045260246000fd5b600082612f8657612f86612f61565b500490565b6000816000190483118215151615612fa557612fa5612ba3565b500290565b600082612fb957612fb9612f61565b500690565b7026b0b1b434b732903334b734b9b432b21d60791b8152601181019190915260310190565b6000600019821415612ff757612ff7612ba3565b5060010190565b652b30b63ab29d60d11b815260006007841061301c5761301c612704565b5060f89290921b600683015260078201526027019056fea2646970667358221220a60bbeb03ccfae7e130a4b359d44672ad8ca4aa7a6c8f0e8b0df3351a625276c64736f6c63430008090033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.