Source Code
Overview
WEMIX Balance
More Info
ContractCreator
Latest 25 from a total of 1,174 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Vote To Bless | 78469328 | 11 days ago | IN | 0 WEMIX | 0.0042722 | ||||
Vote To Bless | 78469155 | 11 days ago | IN | 0 WEMIX | 0.0042722 | ||||
Vote To Bless | 78469146 | 11 days ago | IN | 0 WEMIX | 0.0042722 | ||||
Vote To Bless | 78469145 | 11 days ago | IN | 0 WEMIX | 0.0057765 | ||||
Vote To Bless | 78469136 | 11 days ago | IN | 0 WEMIX | 0.0057765 | ||||
Vote To Bless | 78468973 | 11 days ago | IN | 0 WEMIX | 0.0057765 | ||||
Vote To Bless | 78468840 | 11 days ago | IN | 0 WEMIX | 0.0042722 | ||||
Vote To Bless | 78468839 | 11 days ago | IN | 0 WEMIX | 0.0057765 | ||||
Vote To Bless | 78467768 | 11 days ago | IN | 0 WEMIX | 0.0042722 | ||||
Vote To Bless | 78467680 | 11 days ago | IN | 0 WEMIX | 0.0042722 | ||||
Vote To Bless | 78467678 | 11 days ago | IN | 0 WEMIX | 0.0057765 | ||||
Vote To Bless | 78467413 | 11 days ago | IN | 0 WEMIX | 0.0057765 | ||||
Vote To Bless | 78467238 | 11 days ago | IN | 0 WEMIX | 0.004271 | ||||
Vote To Bless | 78467215 | 11 days ago | IN | 0 WEMIX | 0.0057753 | ||||
Vote To Bless | 78465907 | 11 days ago | IN | 0 WEMIX | 0.0042722 | ||||
Vote To Bless | 78465904 | 11 days ago | IN | 0 WEMIX | 0.0057765 | ||||
Vote To Bless | 78465879 | 11 days ago | IN | 0 WEMIX | 0.0042722 | ||||
Vote To Bless | 78465877 | 11 days ago | IN | 0 WEMIX | 0.0057765 | ||||
Vote To Bless | 76335419 | 36 days ago | IN | 0 WEMIX | 0.0042722 | ||||
Vote To Bless | 76335300 | 36 days ago | IN | 0 WEMIX | 0.0057765 | ||||
Vote To Bless | 76335288 | 36 days ago | IN | 0 WEMIX | 0.0042722 | ||||
Vote To Bless | 76335169 | 36 days ago | IN | 0 WEMIX | 0.0057765 | ||||
Vote To Bless | 76333891 | 36 days ago | IN | 0 WEMIX | 0.0042722 | ||||
Vote To Bless | 76333773 | 36 days ago | IN | 0 WEMIX | 0.0057765 | ||||
Vote To Bless | 76333536 | 36 days ago | IN | 0 WEMIX | 0.0042722 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
79458002 | 21 secs ago | 0 WEMIX | ||||
79457873 | 2 mins ago | 0 WEMIX | ||||
79457813 | 3 mins ago | 0 WEMIX | ||||
79457761 | 4 mins ago | 0 WEMIX | ||||
79457701 | 5 mins ago | 0 WEMIX | ||||
79457693 | 5 mins ago | 0 WEMIX | ||||
79457573 | 7 mins ago | 0 WEMIX | ||||
79457521 | 8 mins ago | 0 WEMIX | ||||
79457513 | 8 mins ago | 0 WEMIX | ||||
79457461 | 9 mins ago | 0 WEMIX | ||||
79457453 | 9 mins ago | 0 WEMIX | ||||
79457401 | 10 mins ago | 0 WEMIX | ||||
79457393 | 10 mins ago | 0 WEMIX | ||||
79457341 | 11 mins ago | 0 WEMIX | ||||
79457153 | 14 mins ago | 0 WEMIX | ||||
79456973 | 17 mins ago | 0 WEMIX | ||||
79456733 | 21 mins ago | 0 WEMIX | ||||
79456681 | 22 mins ago | 0 WEMIX | ||||
79456673 | 22 mins ago | 0 WEMIX | ||||
79456621 | 23 mins ago | 0 WEMIX | ||||
79456613 | 23 mins ago | 0 WEMIX | ||||
79456561 | 24 mins ago | 0 WEMIX | ||||
79456553 | 24 mins ago | 0 WEMIX | ||||
79456441 | 26 mins ago | 0 WEMIX | ||||
79456433 | 26 mins ago | 0 WEMIX |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
RMN
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 26000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; import {IRMN} from "./interfaces/IRMN.sol"; import {OwnerIsCreator} from "./../shared/access/OwnerIsCreator.sol"; import {EnumerableSet} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; // An active curse on this subject will cause isCursed() to return true. Use this subject if there is an issue with a // remote chain, for which there exists a legacy lane contract deployed on the same chain as this RMN contract is // deployed, relying on isCursed(). bytes16 constant LEGACY_CURSE_SUBJECT = 0x01000000000000000000000000000000; // An active curse on this subject will cause isCursed() and isCursed(bytes32) to return true. Use this subject for // issues affecting all of CCIP chains, or pertaining to the chain that this contract is deployed on, instead of using // the local chain selector as a subject. bytes16 constant GLOBAL_CURSE_SUBJECT = 0x01000000000000000000000000000001; // The curse vote address representing the owner in data structures, events and recorded votes. Remains constant, even // if the owner changes. address constant OWNER_CURSE_VOTE_ADDR = address(~uint160(0)); // 0xff...ff // The curse vote address used in an OwnerUnvoteToCurseRequest to lift a curse, if there is no active curse votes for // the subject that we are able to unvote, but the conditions for an active curse no longer hold. address constant LIFT_CURSE_VOTE_ADDR = address(0); /// @dev This contract is owned by RMN, if changing, please notify the RMN maintainers. // solhint-disable chainlink-solidity/explicit-returns contract RMN is IRMN, OwnerIsCreator, ITypeAndVersion { using EnumerableSet for EnumerableSet.AddressSet; // STATIC CONFIG string public constant override typeAndVersion = "RMN 1.5.0"; uint256 private constant MAX_NUM_VOTERS = 16; // MAGIC VALUES bytes28 private constant NO_VOTES_CURSES_HASH = bytes28(0); // DYNAMIC CONFIG /// @notice blessVoteAddr and curseVoteAddr can't be 0. Additionally curseVoteAddr can't be LIFT_CURSE_VOTE_ADDR or /// OWNER_CURSE_VOTE_ADDR. At least one of blessWeight & curseWeight must be non-zero, i.e., a voter could only vote /// to bless, or only vote to curse, or both vote to bless and vote to curse. struct Voter { // This is the address the voter should use to call voteToBless. address blessVoteAddr; // This is the address the voter should use to call voteToCurse. address curseVoteAddr; // The weight of this voter's vote for blessing. uint8 blessWeight; // The weight of this voter's vote for cursing. uint8 curseWeight; } struct Config { Voter[] voters; // When the total weight of voters that have voted to bless a tagged root reaches // or exceeds blessWeightThreshold, the tagged root becomes blessed. uint16 blessWeightThreshold; // When the total weight of voters that have voted to curse a subject reaches or // exceeds curseWeightThreshold, the subject becomes cursed. uint16 curseWeightThreshold; } struct VersionedConfig { Config config; // The version is incremented every time the config changes. // The initial configuration on the contract will have configVersion == 1. uint32 configVersion; // The block number at which the config was last set. Helps the offchain // code check that the config was set in a stable block or double-check // that it has the correct config by querying logs at that block number. uint32 blockNumber; } VersionedConfig private s_versionedConfig; // STATE struct BlesserRecord { // The config version at which this BlesserRecord was last set. A blesser // is considered active iff this configVersion equals // s_versionedConfig.configVersion. uint32 configVersion; uint8 weight; uint8 index; } mapping(address blessVoteAddr => BlesserRecord blesserRecord) private s_blesserRecords; struct BlessVoteProgress { // This particular ordering saves us ~400 gas per voteToBless call, compared to the bool being at the bottom, even // though the size of the struct is the same. bool weightThresholdMet; // A BlessVoteProgress is considered invalid if weightThresholdMet is false when // s_versionedConfig.configVersion changes. we don't want old in-progress // votes to continue when we set a new config! // The config version at which the bless vote for a tagged root was initiated. uint32 configVersion; uint16 accumulatedWeight; // Care must be taken that the bitmap has at least as many bits as MAX_NUM_VOTERS. // uint200 is much larger than we need, but it saves us ~100 gas per voteToBless call to fill the word instead of // using a smaller type. // _bitmapGet(voterBitmap, i) = true indicates that the i-th voter has voted to bless uint200 voterBitmap; } mapping(bytes32 taggedRootHash => BlessVoteProgress blessVoteProgress) private s_blessVoteProgressByTaggedRootHash; // Any tagged root with a commit store included in s_permaBlessedCommitStores will be considered automatically // blessed. EnumerableSet.AddressSet private s_permaBlessedCommitStores; struct CurserRecord { bool active; uint8 weight; mapping(bytes16 curseId => bool used) usedCurseIds; // retained across config changes } mapping(address curseVoteAddr => CurserRecord curserRecord) private s_curserRecords; struct ConfigVersionAndCursesHash { uint32 configVersion; // configVersion != s_versionedConfig.configVersion means no active vote bytes28 cursesHash; // bytes28(0) means no active vote; truncated so that ConfigVersionAndCursesHash fits in a word } struct CurseVoteProgress { uint32 configVersion; // upon config change, lazy set to new config version uint16 curseWeightThreshold; // upon config change, lazy set to new config value uint16 accumulatedWeight; // upon config change, lazy set to 0 // A curse becomes active after either: // - sum([voter.weight for voter who voted in current config]) >= curseWeightThreshold // - ownerCurse is invoked // Once a curse is active, only the owner can lift it. bool curseActive; // retained across config changes mapping(address => ConfigVersionAndCursesHash) latestVoteToCurseByCurseVoteAddr; // retained across config changes } mapping(bytes16 subject => CurseVoteProgress curseVoteProgress) private s_potentiallyOutdatedCurseVoteProgressBySubject; // We intentionally use a struct here, even though it contains a single field, to make it obvious to future editors // that there is space for more fields. struct CurseHotVars { uint64 numSubjectsCursed; // incremented by voteToCurse, ownerCurse; decremented by ownerUnvoteToCurse } CurseHotVars private s_curseHotVars; enum RecordedCurseRelatedOpTag { // A vote to curse, through either voteToCurse or ownerCurse. VoteToCurse, // An unvote to curse, through unvoteToCurse. UnvoteToCurse, // An unvote to curse, through ownerUnvoteToCurse, which was not forced (forceUnvote=false). OwnerUnvoteToCurseUnforced, // An unvote to curse, through ownerUnvoteToCurse, which was forced (forceUnvote=true). OwnerUnvoteToCurseForced, // A configuration change. // // For subjects that are not cursed when this happens, past votes do not get accounted for in the new configuration. // If a voter votes during the new configuration, their curses hash will restart from NO_VOTES_CURSES_HASH. // // For subjects that are cursed when this happens, past votes get accounted for. // If a voter votes during the new configuration, their curses hash will continue from its old value. SetConfig } /// @notice Provides the ability to quickly reconstruct the curse-related state of the contract offchain, without /// having to replay all past events. Replaying past events often takes long, and in some cases might even be /// infeasible due to log pruning. /// /// @dev We could save some gas by omitting some fields and instead using them as mapping keys, but we would lose the /// cross-voter ordering, or cross-subject ordering, or cross-vote/unvote ordering. struct RecordedCurseRelatedOp { RecordedCurseRelatedOpTag tag; uint64 blockTimestamp; bool cursed; // whether the subject is cursed after this op; if tag in {SetConfig}, will be false address curseVoteAddr; // if tag in {SetConfig}, will be address(0) bytes16 subject; // if tag in {SetConfig}, will be bytes16(0) bytes16 curseId; // if tag in {SetConfig, UnvoteToCurse, OwnerUnvoteToCurseUnforced, OwnerUnvoteToCurseForced}, will be bytes16(0) } RecordedCurseRelatedOp[] private s_recordedCurseRelatedOps; /// @dev This function is to _ONLY_ be called in order to determine if a curse should become active upon a /// vote-to-curse, or a curse should be deactivated upon an owner-unvote-to-curse. /// Other reasons for a curse to be active, which are not covered here: /// 1. Cursedness is retained from a prior config. /// 2. The curse weight threshold was met at some point, which activated a curse, and enough voters unvoted to curse /// such that the curse weight threshold is no longer met. function _shouldCurseBeActive(CurseVoteProgress storage sptr_upToDateCurseVoteProgress) internal view returns (bool) { return sptr_upToDateCurseVoteProgress.latestVoteToCurseByCurseVoteAddr[OWNER_CURSE_VOTE_ADDR].cursesHash != NO_VOTES_CURSES_HASH || sptr_upToDateCurseVoteProgress.accumulatedWeight >= sptr_upToDateCurseVoteProgress.curseWeightThreshold; } /// @dev It might be the case that due to the lazy update of curseVoteProgress, a curse is active even though /// _shouldCurseBeActive(curseVoteProgress) is false, i.e., the owner has no active vote to curse and the curse /// weight threshold has not been met. function _getUpToDateCurseVoteProgress( uint32 configVersion, bytes16 subject ) internal returns (CurseVoteProgress storage) { CurseVoteProgress storage sptr_curseVoteProgress = s_potentiallyOutdatedCurseVoteProgressBySubject[subject]; if (configVersion != sptr_curseVoteProgress.configVersion) { sptr_curseVoteProgress.configVersion = configVersion; sptr_curseVoteProgress.curseWeightThreshold = s_versionedConfig.config.curseWeightThreshold; sptr_curseVoteProgress.accumulatedWeight = 0; if (sptr_curseVoteProgress.curseActive) { // If a curse was active, count past votes to curse and retain the curses hash for cursers who are part of the // new config. Config storage sptr_config = s_versionedConfig.config; for (uint256 i = 0; i < sptr_config.voters.length; ++i) { Voter storage sptr_voter = sptr_config.voters[i]; ConfigVersionAndCursesHash storage sptr_cvch = sptr_curseVoteProgress.latestVoteToCurseByCurseVoteAddr[sptr_voter.curseVoteAddr]; if (sptr_cvch.configVersion < configVersion && sptr_cvch.cursesHash != NO_VOTES_CURSES_HASH) { // `< configVersion` instead of `== configVersion-1`, because there might have been multiple config changes // without a lazy update of our subject. This has the side effect of retaining votes from very old configs // that we might not really intend to retain, but these can be removed by the owner later. sptr_cvch.configVersion = configVersion; sptr_curseVoteProgress.accumulatedWeight += sptr_voter.curseWeight; } } // We don't need to think about OWNER_CURSE_VOTE_ADDR here, because its ConfigVersionAndCursesHash counts even // if the configVersion is not the current config version, in contrast to regular voters. // It's an irregularity, but it saves us > 5k gas (if the owner had previously voted) for the unlucky voter who // enters this branch. } else { // If a curse was not active, we don't count past votes to curse for voters who are part of the new config. // Their curses hash will be restart from NO_VOTES_CURSES_HASH when they vote to curse again. // We expect that the offchain code will revote to curse in case it voted to curse, and the vote to curse was // lost due to any reason, including a config change when the curse was not yet active. } } return sptr_curseVoteProgress; } // EVENTS, ERRORS event ConfigSet(uint32 indexed configVersion, Config config); error InvalidConfig(); event TaggedRootBlessed(uint32 indexed configVersion, IRMN.TaggedRoot taggedRoot, uint16 accumulatedWeight); event TaggedRootBlessVotesReset(uint32 indexed configVersion, IRMN.TaggedRoot taggedRoot, bool wasBlessed); event VotedToBless(uint32 indexed configVersion, address indexed voter, IRMN.TaggedRoot taggedRoot, uint8 weight); event VotedToCurse( uint32 indexed configVersion, address indexed voter, bytes16 subject, bytes16 curseId, uint8 weight, uint64 blockTimestamp, bytes28 cursesHash, uint16 accumulatedWeight ); event UnvotedToCurse( uint32 indexed configVersion, address indexed voter, bytes16 subject, uint8 weight, bytes28 cursesHash, uint16 remainingAccumulatedWeight ); event SkippedUnvoteToCurse(address indexed voter, bytes16 subject, bytes28 onchainCursesHash, bytes28 cursesHash); event Cursed(uint32 indexed configVersion, bytes16 subject, uint64 blockTimestamp); event CurseLifted(bytes16 subject); // These events make it easier for offchain logic to discover that it performs // the same actions multiple times. event AlreadyVotedToBless(uint32 indexed configVersion, address indexed voter, IRMN.TaggedRoot taggedRoot); event AlreadyBlessed(uint32 indexed configVersion, address indexed voter, IRMN.TaggedRoot taggedRoot); // Emitted by ownerRemoveThenAddPermaBlessedCommitStores. event PermaBlessedCommitStoreAdded(address commitStore); event PermaBlessedCommitStoreRemoved(address commitStore); error ReusedCurseId(address voter, bytes16 curseId); error UnauthorizedVoter(address voter); error VoteToBlessNoop(); error VoteToCurseNoop(); error UnvoteToCurseNoop(); error VoteToBlessForbiddenDuringActiveGlobalCurse(); /// @notice Thrown when subjects are not a strictly increasing monotone sequence. // Prevents a subject from receiving multiple votes to curse with the same curse id. error SubjectsMustBeStrictlyIncreasing(); constructor(Config memory config) { { // Ensure that the bitmap is large enough to hold MAX_NUM_VOTERS. // We do this in the constructor because MAX_NUM_VOTERS is constant. BlessVoteProgress memory vp = BlessVoteProgress({ configVersion: 0, voterBitmap: type(uint200).max, // will not compile if it doesn't fit accumulatedWeight: 0, weightThresholdMet: false }); assert(vp.voterBitmap >> (MAX_NUM_VOTERS - 1) >= 1); } _setConfig(config); } function _bitmapGet(uint200 bitmap, uint8 index) internal pure returns (bool) { assert(index < MAX_NUM_VOTERS); return bitmap & (uint200(1) << index) != 0; } function _bitmapSet(uint200 bitmap, uint8 index) internal pure returns (uint200) { assert(index < MAX_NUM_VOTERS); return bitmap | (uint200(1) << index); } function _bitmapCount(uint200 bitmap) internal pure returns (uint8 oneBits) { assert(bitmap < 1 << MAX_NUM_VOTERS); // https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan for (; bitmap != 0; ++oneBits) { bitmap &= bitmap - 1; } } function _taggedRootHash(IRMN.TaggedRoot memory taggedRoot) internal pure returns (bytes32) { return keccak256(abi.encode(taggedRoot.commitStore, taggedRoot.root)); } function _cursesHash(bytes28 prevCursesHash, bytes16 curseId) internal pure returns (bytes28) { return bytes28(keccak256(abi.encode(prevCursesHash, curseId))); } function _blockTimestamp() internal view returns (uint64) { return uint64(block.timestamp); } /// @param taggedRoots A tagged root is hashed as `keccak256(abi.encode(taggedRoot.commitStore /// /* address */, taggedRoot.root /* bytes32 */))`. /// @notice Tagged roots which are already (voted to be) blessed are skipped and emit corresponding events. In case /// the call has no effect, i.e., all passed tagged roots are skipped, the function reverts with a `VoteToBlessNoop`. function voteToBless(IRMN.TaggedRoot[] calldata taggedRoots) external { // If we have an active global curse, something is really wrong. Let's err on the // side of caution and not accept further blessings during this time of // uncertainty. if (isCursed(GLOBAL_CURSE_SUBJECT)) revert VoteToBlessForbiddenDuringActiveGlobalCurse(); uint32 configVersion = s_versionedConfig.configVersion; BlesserRecord memory blesserRecord = s_blesserRecords[msg.sender]; if (blesserRecord.configVersion != configVersion) revert UnauthorizedVoter(msg.sender); bool noop = true; for (uint256 i = 0; i < taggedRoots.length; ++i) { IRMN.TaggedRoot memory taggedRoot = taggedRoots[i]; bytes32 taggedRootHash = _taggedRootHash(taggedRoot); BlessVoteProgress memory voteProgress = s_blessVoteProgressByTaggedRootHash[taggedRootHash]; if (voteProgress.weightThresholdMet) { // We don't revert here because it's unreasonable to expect from the // voter to know exactly when to stop voting. Most likely when they // voted they didn't realize the threshold would be reached by the time // their vote was counted. // Additionally, there might be other tagged roots for which votes might // count, and we want to allow that to happen. emit AlreadyBlessed(configVersion, msg.sender, taggedRoot); continue; } else if (voteProgress.configVersion != configVersion) { // Note that voteProgress.weightThresholdMet must be false at this point // If votes were received while an older config was in effect, // invalidate them and start from scratch. // If votes were never received, set the current config version. voteProgress = BlessVoteProgress({ configVersion: configVersion, voterBitmap: 0, accumulatedWeight: 0, weightThresholdMet: false }); } else if (_bitmapGet(voteProgress.voterBitmap, blesserRecord.index)) { // We don't revert here because there might be other tagged roots for // which votes might count, and we want to allow that to happen. emit AlreadyVotedToBless(configVersion, msg.sender, taggedRoot); continue; } noop = false; voteProgress.voterBitmap = _bitmapSet(voteProgress.voterBitmap, blesserRecord.index); voteProgress.accumulatedWeight += blesserRecord.weight; emit VotedToBless(configVersion, msg.sender, taggedRoot, blesserRecord.weight); if (voteProgress.accumulatedWeight >= s_versionedConfig.config.blessWeightThreshold) { voteProgress.weightThresholdMet = true; emit TaggedRootBlessed(configVersion, taggedRoot, voteProgress.accumulatedWeight); } s_blessVoteProgressByTaggedRootHash[taggedRootHash] = voteProgress; } if (noop) { revert VoteToBlessNoop(); } } /// @notice Can be called by the owner to remove unintentionally voted or even blessed tagged roots in a recovery /// scenario. The owner must ensure that there are no in-flight transactions by RMN nodes voting for any of the /// taggedRoots before calling this function, as such in-flight transactions could lead to the roots becoming /// re-blessed shortly after the call to this function, contrary to the original intention. function ownerResetBlessVotes(IRMN.TaggedRoot[] calldata taggedRoots) external onlyOwner { uint32 configVersion = s_versionedConfig.configVersion; for (uint256 i = 0; i < taggedRoots.length; ++i) { IRMN.TaggedRoot memory taggedRoot = taggedRoots[i]; bytes32 taggedRootHash = _taggedRootHash(taggedRoot); BlessVoteProgress memory voteProgress = s_blessVoteProgressByTaggedRootHash[taggedRootHash]; delete s_blessVoteProgressByTaggedRootHash[taggedRootHash]; bool wasBlessed = voteProgress.weightThresholdMet; if (voteProgress.configVersion == configVersion || wasBlessed) { emit TaggedRootBlessVotesReset(configVersion, taggedRoot, wasBlessed); } } } struct UnvoteToCurseRequest { bytes16 subject; bytes28 cursesHash; } // For use in internal calls. enum Privilege { Owner, Voter } function _authorizedUnvoteToCurse( Privilege priv, // Privilege.Owner during an ownerUnvoteToCurse call, Privilege.Voter during a unvoteToCurse call uint32 configVersion, address curseVoteAddr, UnvoteToCurseRequest memory req, bool forceUnvote, // true only during an ownerUnvoteToCurse call, when OwnerUnvoteToCurseRequest.forceUnvote is true CurserRecord storage sptr_curserRecord, CurseVoteProgress storage sptr_curseVoteProgress ) internal returns (bool unvoted, bool curseLifted) { { assert(priv == Privilege.Voter || priv == Privilege.Owner); // sanity check // Check that the supplied arguments are feasible for our privilege. if (forceUnvote || curseVoteAddr == OWNER_CURSE_VOTE_ADDR || curseVoteAddr == LIFT_CURSE_VOTE_ADDR) { assert(priv == Privilege.Owner); } } ConfigVersionAndCursesHash memory cvch = sptr_curseVoteProgress.latestVoteToCurseByCurseVoteAddr[curseVoteAddr]; // First, try to unvote. if ( sptr_curserRecord.active && (curseVoteAddr == OWNER_CURSE_VOTE_ADDR || cvch.configVersion == configVersion) && cvch.cursesHash != NO_VOTES_CURSES_HASH && (cvch.cursesHash == req.cursesHash || forceUnvote) ) { unvoted = true; delete sptr_curseVoteProgress.latestVoteToCurseByCurseVoteAddr[curseVoteAddr]; // Assumes: s_curserRecords[OWNER_CURSE_VOTE_ADDR].weight == 0, enforced by _setConfig sptr_curseVoteProgress.accumulatedWeight -= sptr_curserRecord.weight; emit UnvotedToCurse( configVersion, curseVoteAddr, req.subject, sptr_curserRecord.weight, req.cursesHash, sptr_curseVoteProgress.accumulatedWeight ); } // If we have owner privilege, and the conditions for the curse to be active no longer hold, we are able to lift the // curse. bool shouldTryToLiftCurse = priv == Privilege.Owner && (unvoted || curseVoteAddr == LIFT_CURSE_VOTE_ADDR); if (shouldTryToLiftCurse && sptr_curseVoteProgress.curseActive && !_shouldCurseBeActive(sptr_curseVoteProgress)) { curseLifted = true; sptr_curseVoteProgress.curseActive = false; --s_curseHotVars.numSubjectsCursed; emit CurseLifted(req.subject); } if (unvoted || curseLifted) { RecordedCurseRelatedOpTag tag; if (priv == Privilege.Owner) { if (forceUnvote) { tag = RecordedCurseRelatedOpTag.OwnerUnvoteToCurseForced; } else { tag = RecordedCurseRelatedOpTag.OwnerUnvoteToCurseUnforced; } } else if (priv == Privilege.Voter) { tag = RecordedCurseRelatedOpTag.UnvoteToCurse; } else { // solhint-disable-next-line gas-custom-errors, reason-string revert(); // assumption violation } s_recordedCurseRelatedOps.push( RecordedCurseRelatedOp({ tag: tag, cursed: sptr_curseVoteProgress.curseActive, curseVoteAddr: curseVoteAddr, curseId: bytes16(0), subject: req.subject, blockTimestamp: _blockTimestamp() }) ); } else { emit SkippedUnvoteToCurse(curseVoteAddr, req.subject, cvch.cursesHash, req.cursesHash); } } /// @notice Can be called by a curser to remove unintentional votes to curse. /// We expect this to be called very rarely, e.g. in case of a bug in the /// offchain code causing false voteToCurse calls. /// @notice Should be called from curser's corresponding curseVoteAddr. function unvoteToCurse(UnvoteToCurseRequest[] memory unvoteToCurseRequests) external { address curseVoteAddr = msg.sender; CurserRecord storage sptr_curserRecord = s_curserRecords[curseVoteAddr]; if (!sptr_curserRecord.active) revert UnauthorizedVoter(curseVoteAddr); uint32 configVersion = s_versionedConfig.configVersion; bool anyVoteWasUnvoted = false; for (uint256 i = 0; i < unvoteToCurseRequests.length; ++i) { UnvoteToCurseRequest memory req = unvoteToCurseRequests[i]; CurseVoteProgress storage sptr_curseVoteProgress = _getUpToDateCurseVoteProgress(configVersion, req.subject); (bool unvoted, bool curseLifted) = _authorizedUnvoteToCurse( Privilege.Voter, configVersion, curseVoteAddr, req, false, sptr_curserRecord, sptr_curseVoteProgress ); assert(!curseLifted); // assumption violation: voters can't lift curses anyVoteWasUnvoted = anyVoteWasUnvoted || unvoted; } if (!anyVoteWasUnvoted) { revert UnvoteToCurseNoop(); } } /// @notice A vote to curse is appropriate during unhealthy blockchain conditions /// (eg. finality violations). function voteToCurse(bytes16 curseId, bytes16[] memory subjects) external { address curseVoteAddr = msg.sender; assert(curseVoteAddr != OWNER_CURSE_VOTE_ADDR); CurserRecord storage sptr_curserRecord = s_curserRecords[curseVoteAddr]; if (!sptr_curserRecord.active) revert UnauthorizedVoter(curseVoteAddr); _authorizedVoteToCurse(curseVoteAddr, curseId, subjects, sptr_curserRecord); } function _authorizedVoteToCurse( address curseVoteAddr, bytes16 curseId, bytes16[] memory subjects, CurserRecord storage sptr_curserRecord ) internal { if (subjects.length == 0) revert VoteToCurseNoop(); if (sptr_curserRecord.usedCurseIds[curseId]) revert ReusedCurseId(curseVoteAddr, curseId); sptr_curserRecord.usedCurseIds[curseId] = true; // NOTE: We could pack configVersion into CurserRecord that we already load in the beginning of this function to // avoid the following extra storage read for it, but since voteToCurse is not on the hot path we'd rather keep // things simple. uint32 configVersion = s_versionedConfig.configVersion; for (uint256 i = 0; i < subjects.length; ++i) { if (i >= 1 && !(subjects[i - 1] < subjects[i])) { // Prevents a subject from receiving multiple votes to curse with the same curse id. revert SubjectsMustBeStrictlyIncreasing(); } bytes16 subject = subjects[i]; CurseVoteProgress storage sptr_curseVoteProgress = _getUpToDateCurseVoteProgress(configVersion, subject); ConfigVersionAndCursesHash memory cvch = sptr_curseVoteProgress.latestVoteToCurseByCurseVoteAddr[curseVoteAddr]; bytes28 prevCursesHash; if ( (curseVoteAddr != OWNER_CURSE_VOTE_ADDR && cvch.configVersion < configVersion) || cvch.cursesHash == NO_VOTES_CURSES_HASH ) { // if owner's first vote, or if voter's first vote in this config version prevCursesHash = NO_VOTES_CURSES_HASH; // start hashchain from scratch, explicit sptr_curseVoteProgress.accumulatedWeight += sptr_curserRecord.weight; } else { // we've already accounted for the weight prevCursesHash = cvch.cursesHash; } sptr_curseVoteProgress.latestVoteToCurseByCurseVoteAddr[curseVoteAddr] = cvch = ConfigVersionAndCursesHash({configVersion: configVersion, cursesHash: _cursesHash(prevCursesHash, curseId)}); emit VotedToCurse( configVersion, curseVoteAddr, subject, curseId, sptr_curserRecord.weight, _blockTimestamp(), cvch.cursesHash, sptr_curseVoteProgress.accumulatedWeight ); if ( prevCursesHash == NO_VOTES_CURSES_HASH && !sptr_curseVoteProgress.curseActive && _shouldCurseBeActive(sptr_curseVoteProgress) ) { sptr_curseVoteProgress.curseActive = true; ++s_curseHotVars.numSubjectsCursed; emit Cursed(configVersion, subject, _blockTimestamp()); } s_recordedCurseRelatedOps.push( RecordedCurseRelatedOp({ tag: RecordedCurseRelatedOpTag.VoteToCurse, cursed: sptr_curseVoteProgress.curseActive, curseVoteAddr: curseVoteAddr, curseId: curseId, subject: subject, blockTimestamp: _blockTimestamp() }) ); } } /// @notice Enables the owner to immediately have the system enter the cursed state. function ownerCurse(bytes16 curseId, bytes16[] memory subjects) external onlyOwner { address curseVoteAddr = OWNER_CURSE_VOTE_ADDR; CurserRecord storage sptr_curserRecord = s_curserRecords[curseVoteAddr]; // no need to check if sptr_curserRecord.active, we must have the onlyOwner modifier _authorizedVoteToCurse(curseVoteAddr, curseId, subjects, sptr_curserRecord); } // Set curseVoteAddr=LIFT_CURSE_VOTE_ADDR, cursesHash=bytes28(0), to reset curseActive if it can be reset. Useful if // all voters have unvoted to curse on their own and the curse can now be lifted without any individual votes that can // be unvoted. // solhint-disable-next-line gas-struct-packing struct OwnerUnvoteToCurseRequest { address curseVoteAddr; UnvoteToCurseRequest unit; bool forceUnvote; } /// @notice Enables the owner to remove curse votes. After the curse votes are removed, /// this function will check whether the curse is still valid and restore the uncursed state if possible. /// This function also enables the owner to lift a curse created through ownerCurse. function ownerUnvoteToCurse(OwnerUnvoteToCurseRequest[] memory ownerUnvoteToCurseRequests) external onlyOwner { bool anyCurseWasLifted = false; bool anyVoteWasUnvoted = false; uint32 configVersion = s_versionedConfig.configVersion; for (uint256 i = 0; i < ownerUnvoteToCurseRequests.length; ++i) { OwnerUnvoteToCurseRequest memory req = ownerUnvoteToCurseRequests[i]; CurseVoteProgress storage sptr_curseVoteProgress = _getUpToDateCurseVoteProgress(configVersion, req.unit.subject); (bool unvoted, bool curseLifted) = _authorizedUnvoteToCurse( Privilege.Owner, configVersion, req.curseVoteAddr, req.unit, req.forceUnvote, s_curserRecords[req.curseVoteAddr], sptr_curseVoteProgress ); anyVoteWasUnvoted = anyVoteWasUnvoted || unvoted; anyCurseWasLifted = anyCurseWasLifted || curseLifted; } if (anyCurseWasLifted) { // Invalidate all in-progress votes to bless or curse by bumping the config version. // They might have been based on false information about the source chain // (e.g. in case of a finality violation). _setConfig(s_versionedConfig.config); } if (!(anyVoteWasUnvoted || anyCurseWasLifted)) { revert UnvoteToCurseNoop(); } } function setConfig(Config memory config) external onlyOwner { _setConfig(config); } /// @notice Any tagged root with a commit store included in this array will be considered automatically blessed. function getPermaBlessedCommitStores() external view returns (address[] memory) { return s_permaBlessedCommitStores.values(); } /// @notice The ordering of parameters is important. First come the commit stores to remove, then the commit stores to /// add. function ownerRemoveThenAddPermaBlessedCommitStores( address[] memory removes, address[] memory adds ) external onlyOwner { for (uint256 i = 0; i < removes.length; ++i) { if (s_permaBlessedCommitStores.remove(removes[i])) { emit PermaBlessedCommitStoreRemoved(removes[i]); } } for (uint256 i = 0; i < adds.length; ++i) { if (s_permaBlessedCommitStores.add(adds[i])) { emit PermaBlessedCommitStoreAdded(adds[i]); } } } /// @inheritdoc IRMN function isBlessed(IRMN.TaggedRoot calldata taggedRoot) external view returns (bool) { return s_blessVoteProgressByTaggedRootHash[_taggedRootHash(taggedRoot)].weightThresholdMet || s_permaBlessedCommitStores.contains(taggedRoot.commitStore); } /// @inheritdoc IRMN function isCursed() external view returns (bool) { if (s_curseHotVars.numSubjectsCursed == 0) { return false; // happy path costs a single SLOAD } else { return s_potentiallyOutdatedCurseVoteProgressBySubject[GLOBAL_CURSE_SUBJECT].curseActive || s_potentiallyOutdatedCurseVoteProgressBySubject[LEGACY_CURSE_SUBJECT].curseActive; } } /// @inheritdoc IRMN function isCursed(bytes16 subject) public view returns (bool) { if (s_curseHotVars.numSubjectsCursed == 0) { return false; // happy path costs a single SLOAD } else { return s_potentiallyOutdatedCurseVoteProgressBySubject[GLOBAL_CURSE_SUBJECT].curseActive || s_potentiallyOutdatedCurseVoteProgressBySubject[subject].curseActive; } } /// @notice Config version might be incremented for many reasons, including /// the lifting of a curse, or a regular config change. function getConfigDetails() external view returns (uint32 version, uint32 blockNumber, Config memory config) { version = s_versionedConfig.configVersion; blockNumber = s_versionedConfig.blockNumber; config = s_versionedConfig.config; } /// @return blessVoteAddrs addresses of voters, will be empty if voting took place with an older config version /// @return accumulatedWeight sum of weights of voters, will be zero if voting took place with an older config version /// @return blessed will be accurate regardless of when voting took place /// @dev This is a helper method for offchain code so efficiency is not really a concern. function getBlessProgress(IRMN.TaggedRoot calldata taggedRoot) external view returns (address[] memory blessVoteAddrs, uint16 accumulatedWeight, bool blessed) { bytes32 taggedRootHash = _taggedRootHash(taggedRoot); BlessVoteProgress memory progress = s_blessVoteProgressByTaggedRootHash[taggedRootHash]; blessed = progress.weightThresholdMet; if (progress.configVersion == s_versionedConfig.configVersion) { accumulatedWeight = progress.accumulatedWeight; uint200 bitmap = progress.voterBitmap; blessVoteAddrs = new address[](_bitmapCount(bitmap)); Voter[] memory voters = s_versionedConfig.config.voters; uint256 j = 0; for (uint8 i = 0; i < voters.length; ++i) { if (_bitmapGet(bitmap, i)) { blessVoteAddrs[j] = voters[i].blessVoteAddr; ++j; } } } } /// @return curseVoteAddrs the curseVoteAddr of each voter with an active vote to curse /// @return cursesHashes the i-th value is the curses hash of curseVoteAddrs[i] /// @return accumulatedWeight the accumulated weight of all voters with an active vote to curse who are part of the /// current config /// @return cursed might be true even if the owner has no active vote and accumulatedWeight < curseWeightThreshold, /// due to a retained curse from a prior config /// @dev This is a helper method for offchain code so efficiency is not really a concern. function getCurseProgress(bytes16 subject) external view returns (address[] memory curseVoteAddrs, bytes28[] memory cursesHashes, uint16 accumulatedWeight, bool cursed) { uint32 configVersion = s_versionedConfig.configVersion; Config memory config = s_versionedConfig.config; // Can't use _getUpToDateCurseVoteProgress here because we can't call a non-view function from within a view. // So we get to repeat some accounting. CurseVoteProgress storage outdatedCurseVoteProgress = s_potentiallyOutdatedCurseVoteProgressBySubject[subject]; cursed = outdatedCurseVoteProgress.curseActive; // See _getUpToDateCurseVoteProgress for more context. bool shouldCountVotesFromOlderConfigs = outdatedCurseVoteProgress.configVersion < configVersion && cursed; // A play in two acts, because we can't push to arrays in memory, so we need to precompute the array's length. // First act: we count the number of cursers, i.e., voters with active vote. // Second act: push the cursers to the arrays, sum their weights. uint256 numCursers = 0; // we reuse this variable for writing to perserve stack space accumulatedWeight = 0; for (uint256 act = 1; act <= 2; ++act) { uint256 i = config.voters.length; // not config.voters.length-1 to account for the owner while (true) { address curseVoteAddr; uint8 weight; if (i < config.voters.length) { curseVoteAddr = config.voters[i].curseVoteAddr; weight = config.voters[i].curseWeight; } else { // Allows us to include the owner's vote and curses hash in the result. curseVoteAddr = OWNER_CURSE_VOTE_ADDR; weight = 0; } ConfigVersionAndCursesHash memory cvch = outdatedCurseVoteProgress.latestVoteToCurseByCurseVoteAddr[curseVoteAddr]; bool hasActiveVote = ( shouldCountVotesFromOlderConfigs || cvch.configVersion == configVersion || curseVoteAddr == OWNER_CURSE_VOTE_ADDR ) && cvch.cursesHash != NO_VOTES_CURSES_HASH; if (hasActiveVote) { if (act == 1) { ++numCursers; } else if (act == 2) { accumulatedWeight += weight; --numCursers; curseVoteAddrs[numCursers] = curseVoteAddr; cursesHashes[numCursers] = cvch.cursesHash; } else { // solhint-disable-next-line gas-custom-errors, reason-string revert(); // assumption violation } } if (i > 0) { --i; } else { break; } } if (act == 1) { // We are done counting at this point, initialize the arrays for the second act that follows immediately after. curseVoteAddrs = new address[](numCursers); cursesHashes = new bytes28[](numCursers); } } } /// @notice Returns the number of subjects that are currently cursed. function getCursedSubjectsCount() external view returns (uint256) { return s_curseHotVars.numSubjectsCursed; } /// @dev This is a helper method for offchain code to know what arguments to use for getRecordedCurseRelatedOps. function getRecordedCurseRelatedOpsCount() external view returns (uint256) { return s_recordedCurseRelatedOps.length; } /// @dev This is a helper method for offchain code so efficiency is not really a concern. /// @dev Returns s_recordedCurseRelatedOps[offset:offset+limit]. function getRecordedCurseRelatedOps( uint256 offset, uint256 limit ) external view returns (RecordedCurseRelatedOp[] memory) { uint256 pageLen; if (offset + limit <= s_recordedCurseRelatedOps.length) { pageLen = limit; } else if (offset < s_recordedCurseRelatedOps.length) { pageLen = s_recordedCurseRelatedOps.length - offset; } else { pageLen = 0; } RecordedCurseRelatedOp[] memory page = new RecordedCurseRelatedOp[](pageLen); for (uint256 i = 0; i < pageLen; ++i) { page[i] = s_recordedCurseRelatedOps[offset + i]; } return page; } function _validateConfig(Config memory config) internal pure returns (bool) { if ( config.voters.length == 0 || config.voters.length > MAX_NUM_VOTERS || config.blessWeightThreshold == 0 || config.curseWeightThreshold == 0 ) { return false; } uint256 totalBlessWeight = 0; uint256 totalCurseWeight = 0; address[] memory allAddrs = new address[](2 * config.voters.length); for (uint256 i = 0; i < config.voters.length; ++i) { Voter memory voter = config.voters[i]; // The owner can always curse using the ownerCurse method, and is not supposed to be included in the voters list. // Even though the intent is for the actual owner address to NOT be included in the voters list, we don't // explicitly disallow curseVoteAddr == owner() here. Even if we did, the owner could transfer ownership of the // contract, and so we couldn't guarantee that the owner is not eventually included in the voters list. if ( voter.blessVoteAddr == address(0) || voter.curseVoteAddr == address(0) || voter.curseVoteAddr == LIFT_CURSE_VOTE_ADDR || voter.curseVoteAddr == OWNER_CURSE_VOTE_ADDR || (voter.blessWeight == 0 && voter.curseWeight == 0) ) { return false; } allAddrs[2 * i + 0] = voter.blessVoteAddr; allAddrs[2 * i + 1] = voter.curseVoteAddr; totalBlessWeight += voter.blessWeight; totalCurseWeight += voter.curseWeight; } for (uint256 i = 0; i < allAddrs.length; ++i) { address allAddrs_i = allAddrs[i]; for (uint256 j = i + 1; j < allAddrs.length; ++j) { if (allAddrs_i == allAddrs[j]) { return false; } } } return totalBlessWeight >= config.blessWeightThreshold && totalCurseWeight >= config.curseWeightThreshold; } function _setConfig(Config memory config) private { if (!_validateConfig(config)) revert InvalidConfig(); // We can't directly assign s_versionedConfig.config to config // because copying a memory array into storage is not supported. { s_versionedConfig.config.blessWeightThreshold = config.blessWeightThreshold; s_versionedConfig.config.curseWeightThreshold = config.curseWeightThreshold; while (s_versionedConfig.config.voters.length != 0) { Voter memory voter = s_versionedConfig.config.voters[s_versionedConfig.config.voters.length - 1]; delete s_blesserRecords[voter.blessVoteAddr]; delete s_curserRecords[voter.curseVoteAddr]; // usedCurseIds mapping is retained, as intended s_versionedConfig.config.voters.pop(); } for (uint256 i = 0; i < config.voters.length; ++i) { s_versionedConfig.config.voters.push(config.voters[i]); } } ++s_versionedConfig.configVersion; uint32 configVersion = s_versionedConfig.configVersion; for (uint8 i = 0; i < config.voters.length; ++i) { Voter memory voter = config.voters[i]; s_blesserRecords[voter.blessVoteAddr] = BlesserRecord({configVersion: configVersion, index: i, weight: voter.blessWeight}); { CurserRecord storage sptr_curserRecord = s_curserRecords[voter.curseVoteAddr]; // Solidity will not let us initialize as CurserRecord({...}) due to the nested mapping sptr_curserRecord.active = true; sptr_curserRecord.weight = voter.curseWeight; } } { // Initialize the owner's CurserRecord // We could in principle perform this initialization once in the constructor instead, and save a small bit of gas. // But configuration changes are relatively infrequent, and keeping the initialization here makes the contract's // correctness easier to reason about. CurserRecord storage sptr_ownerCurserRecord = s_curserRecords[OWNER_CURSE_VOTE_ADDR]; sptr_ownerCurserRecord.active = true; // Assumed by vote/unvote-to-curse logic sptr_ownerCurserRecord.weight = 0; // Assumed by vote/unvote-to-curse logic } s_versionedConfig.blockNumber = uint32(block.number); emit ConfigSet(configVersion, config); s_recordedCurseRelatedOps.push( RecordedCurseRelatedOp({ tag: RecordedCurseRelatedOpTag.SetConfig, blockTimestamp: _blockTimestamp(), cursed: false, curseVoteAddr: address(0), curseId: bytes16(0), subject: bytes16(0) }) ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ITypeAndVersion { function typeAndVersion() external pure returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice This interface contains the only RMN-related functions that might be used on-chain by other CCIP contracts. interface IRMN { /// @notice A Merkle root tagged with the address of the commit store contract it is destined for. struct TaggedRoot { address commitStore; bytes32 root; } /// @notice Callers MUST NOT cache the return value as a blessed tagged root could become unblessed. function isBlessed(TaggedRoot calldata taggedRoot) external view returns (bool); /// @notice Iff there is an active global or legacy curse, this function returns true. function isCursed() external view returns (bool); /// @notice Iff there is an active global curse, or an active curse for `subject`, this function returns true. /// @param subject To check whether a particular chain is cursed, set to bytes16(uint128(chainSelector)). function isCursed(bytes16 subject) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {ConfirmedOwner} from "./ConfirmedOwner.sol"; /// @title The OwnerIsCreator contract /// @notice A contract with helpers for basic contract ownership. contract OwnerIsCreator is ConfirmedOwner { constructor() ConfirmedOwner(msg.sender) {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {ConfirmedOwnerWithProposal} from "./ConfirmedOwnerWithProposal.sol"; /// @title The ConfirmedOwner contract /// @notice A contract with helpers for basic contract ownership. contract ConfirmedOwner is ConfirmedOwnerWithProposal { constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IOwnable} from "../interfaces/IOwnable.sol"; /// @title The ConfirmedOwner contract /// @notice A contract with helpers for basic contract ownership. contract ConfirmedOwnerWithProposal is IOwnable { address private s_owner; address private s_pendingOwner; event OwnershipTransferRequested(address indexed from, address indexed to); event OwnershipTransferred(address indexed from, address indexed to); constructor(address newOwner, address pendingOwner) { // solhint-disable-next-line gas-custom-errors require(newOwner != address(0), "Cannot set owner to zero"); s_owner = newOwner; if (pendingOwner != address(0)) { _transferOwnership(pendingOwner); } } /// @notice Allows an owner to begin transferring ownership to a new address. function transferOwnership(address to) public override onlyOwner { _transferOwnership(to); } /// @notice Allows an ownership transfer to be completed by the recipient. function acceptOwnership() external override { // solhint-disable-next-line gas-custom-errors require(msg.sender == s_pendingOwner, "Must be proposed owner"); address oldOwner = s_owner; s_owner = msg.sender; s_pendingOwner = address(0); emit OwnershipTransferred(oldOwner, msg.sender); } /// @notice Get the current owner function owner() public view override returns (address) { return s_owner; } /// @notice validate, transfer ownership, and emit relevant events function _transferOwnership(address to) private { // solhint-disable-next-line gas-custom-errors require(to != msg.sender, "Cannot transfer to self"); s_pendingOwner = to; emit OwnershipTransferRequested(s_owner, to); } /// @notice validate access function _validateOwnership() internal view { // solhint-disable-next-line gas-custom-errors require(msg.sender == s_owner, "Only callable by owner"); } /// @notice Reverts if called by anyone other than the contract owner. modifier onlyOwner() { _validateOwnership(); _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IOwnable { function owner() external returns (address); function transferOwnership(address recipient) external; function acceptOwnership() external; }
{ "remappings": [ "forge-std/=src/v0.8/vendor/forge-std/src/", "@openzeppelin/=node_modules/@openzeppelin/", "@arbitrum/=node_modules/@arbitrum/", "hardhat/=node_modules/hardhat/", "@eth-optimism/=node_modules/@eth-optimism/", "@scroll-tech/=node_modules/@scroll-tech/", "@offchainlabs/=node_modules/@offchainlabs/" ], "optimizer": { "enabled": true, "runs": 26000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": {} }
[{"inputs":[{"components":[{"components":[{"internalType":"address","name":"blessVoteAddr","type":"address"},{"internalType":"address","name":"curseVoteAddr","type":"address"},{"internalType":"uint8","name":"blessWeight","type":"uint8"},{"internalType":"uint8","name":"curseWeight","type":"uint8"}],"internalType":"struct RMN.Voter[]","name":"voters","type":"tuple[]"},{"internalType":"uint16","name":"blessWeightThreshold","type":"uint16"},{"internalType":"uint16","name":"curseWeightThreshold","type":"uint16"}],"internalType":"struct RMN.Config","name":"config","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidConfig","type":"error"},{"inputs":[{"internalType":"address","name":"voter","type":"address"},{"internalType":"bytes16","name":"curseId","type":"bytes16"}],"name":"ReusedCurseId","type":"error"},{"inputs":[],"name":"SubjectsMustBeStrictlyIncreasing","type":"error"},{"inputs":[{"internalType":"address","name":"voter","type":"address"}],"name":"UnauthorizedVoter","type":"error"},{"inputs":[],"name":"UnvoteToCurseNoop","type":"error"},{"inputs":[],"name":"VoteToBlessForbiddenDuringActiveGlobalCurse","type":"error"},{"inputs":[],"name":"VoteToBlessNoop","type":"error"},{"inputs":[],"name":"VoteToCurseNoop","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"configVersion","type":"uint32"},{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"components":[{"internalType":"address","name":"commitStore","type":"address"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"indexed":false,"internalType":"struct IRMN.TaggedRoot","name":"taggedRoot","type":"tuple"}],"name":"AlreadyBlessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"configVersion","type":"uint32"},{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"components":[{"internalType":"address","name":"commitStore","type":"address"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"indexed":false,"internalType":"struct IRMN.TaggedRoot","name":"taggedRoot","type":"tuple"}],"name":"AlreadyVotedToBless","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"configVersion","type":"uint32"},{"components":[{"components":[{"internalType":"address","name":"blessVoteAddr","type":"address"},{"internalType":"address","name":"curseVoteAddr","type":"address"},{"internalType":"uint8","name":"blessWeight","type":"uint8"},{"internalType":"uint8","name":"curseWeight","type":"uint8"}],"internalType":"struct RMN.Voter[]","name":"voters","type":"tuple[]"},{"internalType":"uint16","name":"blessWeightThreshold","type":"uint16"},{"internalType":"uint16","name":"curseWeightThreshold","type":"uint16"}],"indexed":false,"internalType":"struct RMN.Config","name":"config","type":"tuple"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes16","name":"subject","type":"bytes16"}],"name":"CurseLifted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"configVersion","type":"uint32"},{"indexed":false,"internalType":"bytes16","name":"subject","type":"bytes16"},{"indexed":false,"internalType":"uint64","name":"blockTimestamp","type":"uint64"}],"name":"Cursed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"commitStore","type":"address"}],"name":"PermaBlessedCommitStoreAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"commitStore","type":"address"}],"name":"PermaBlessedCommitStoreRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"bytes16","name":"subject","type":"bytes16"},{"indexed":false,"internalType":"bytes28","name":"onchainCursesHash","type":"bytes28"},{"indexed":false,"internalType":"bytes28","name":"cursesHash","type":"bytes28"}],"name":"SkippedUnvoteToCurse","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"configVersion","type":"uint32"},{"components":[{"internalType":"address","name":"commitStore","type":"address"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"indexed":false,"internalType":"struct IRMN.TaggedRoot","name":"taggedRoot","type":"tuple"},{"indexed":false,"internalType":"bool","name":"wasBlessed","type":"bool"}],"name":"TaggedRootBlessVotesReset","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"configVersion","type":"uint32"},{"components":[{"internalType":"address","name":"commitStore","type":"address"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"indexed":false,"internalType":"struct IRMN.TaggedRoot","name":"taggedRoot","type":"tuple"},{"indexed":false,"internalType":"uint16","name":"accumulatedWeight","type":"uint16"}],"name":"TaggedRootBlessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"configVersion","type":"uint32"},{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"bytes16","name":"subject","type":"bytes16"},{"indexed":false,"internalType":"uint8","name":"weight","type":"uint8"},{"indexed":false,"internalType":"bytes28","name":"cursesHash","type":"bytes28"},{"indexed":false,"internalType":"uint16","name":"remainingAccumulatedWeight","type":"uint16"}],"name":"UnvotedToCurse","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"configVersion","type":"uint32"},{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"components":[{"internalType":"address","name":"commitStore","type":"address"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"indexed":false,"internalType":"struct IRMN.TaggedRoot","name":"taggedRoot","type":"tuple"},{"indexed":false,"internalType":"uint8","name":"weight","type":"uint8"}],"name":"VotedToBless","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"configVersion","type":"uint32"},{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"bytes16","name":"subject","type":"bytes16"},{"indexed":false,"internalType":"bytes16","name":"curseId","type":"bytes16"},{"indexed":false,"internalType":"uint8","name":"weight","type":"uint8"},{"indexed":false,"internalType":"uint64","name":"blockTimestamp","type":"uint64"},{"indexed":false,"internalType":"bytes28","name":"cursesHash","type":"bytes28"},{"indexed":false,"internalType":"uint16","name":"accumulatedWeight","type":"uint16"}],"name":"VotedToCurse","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"commitStore","type":"address"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"internalType":"struct IRMN.TaggedRoot","name":"taggedRoot","type":"tuple"}],"name":"getBlessProgress","outputs":[{"internalType":"address[]","name":"blessVoteAddrs","type":"address[]"},{"internalType":"uint16","name":"accumulatedWeight","type":"uint16"},{"internalType":"bool","name":"blessed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConfigDetails","outputs":[{"internalType":"uint32","name":"version","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"components":[{"components":[{"internalType":"address","name":"blessVoteAddr","type":"address"},{"internalType":"address","name":"curseVoteAddr","type":"address"},{"internalType":"uint8","name":"blessWeight","type":"uint8"},{"internalType":"uint8","name":"curseWeight","type":"uint8"}],"internalType":"struct RMN.Voter[]","name":"voters","type":"tuple[]"},{"internalType":"uint16","name":"blessWeightThreshold","type":"uint16"},{"internalType":"uint16","name":"curseWeightThreshold","type":"uint16"}],"internalType":"struct RMN.Config","name":"config","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes16","name":"subject","type":"bytes16"}],"name":"getCurseProgress","outputs":[{"internalType":"address[]","name":"curseVoteAddrs","type":"address[]"},{"internalType":"bytes28[]","name":"cursesHashes","type":"bytes28[]"},{"internalType":"uint16","name":"accumulatedWeight","type":"uint16"},{"internalType":"bool","name":"cursed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCursedSubjectsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPermaBlessedCommitStores","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"offset","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"getRecordedCurseRelatedOps","outputs":[{"components":[{"internalType":"enum RMN.RecordedCurseRelatedOpTag","name":"tag","type":"uint8"},{"internalType":"uint64","name":"blockTimestamp","type":"uint64"},{"internalType":"bool","name":"cursed","type":"bool"},{"internalType":"address","name":"curseVoteAddr","type":"address"},{"internalType":"bytes16","name":"subject","type":"bytes16"},{"internalType":"bytes16","name":"curseId","type":"bytes16"}],"internalType":"struct RMN.RecordedCurseRelatedOp[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRecordedCurseRelatedOpsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"commitStore","type":"address"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"internalType":"struct IRMN.TaggedRoot","name":"taggedRoot","type":"tuple"}],"name":"isBlessed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes16","name":"subject","type":"bytes16"}],"name":"isCursed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isCursed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes16","name":"curseId","type":"bytes16"},{"internalType":"bytes16[]","name":"subjects","type":"bytes16[]"}],"name":"ownerCurse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"removes","type":"address[]"},{"internalType":"address[]","name":"adds","type":"address[]"}],"name":"ownerRemoveThenAddPermaBlessedCommitStores","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"commitStore","type":"address"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"internalType":"struct IRMN.TaggedRoot[]","name":"taggedRoots","type":"tuple[]"}],"name":"ownerResetBlessVotes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"curseVoteAddr","type":"address"},{"components":[{"internalType":"bytes16","name":"subject","type":"bytes16"},{"internalType":"bytes28","name":"cursesHash","type":"bytes28"}],"internalType":"struct RMN.UnvoteToCurseRequest","name":"unit","type":"tuple"},{"internalType":"bool","name":"forceUnvote","type":"bool"}],"internalType":"struct RMN.OwnerUnvoteToCurseRequest[]","name":"ownerUnvoteToCurseRequests","type":"tuple[]"}],"name":"ownerUnvoteToCurse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"blessVoteAddr","type":"address"},{"internalType":"address","name":"curseVoteAddr","type":"address"},{"internalType":"uint8","name":"blessWeight","type":"uint8"},{"internalType":"uint8","name":"curseWeight","type":"uint8"}],"internalType":"struct RMN.Voter[]","name":"voters","type":"tuple[]"},{"internalType":"uint16","name":"blessWeightThreshold","type":"uint16"},{"internalType":"uint16","name":"curseWeightThreshold","type":"uint16"}],"internalType":"struct RMN.Config","name":"config","type":"tuple"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes16","name":"subject","type":"bytes16"},{"internalType":"bytes28","name":"cursesHash","type":"bytes28"}],"internalType":"struct RMN.UnvoteToCurseRequest[]","name":"unvoteToCurseRequests","type":"tuple[]"}],"name":"unvoteToCurse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"commitStore","type":"address"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"internalType":"struct IRMN.TaggedRoot[]","name":"taggedRoots","type":"tuple[]"}],"name":"voteToBless","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes16","name":"curseId","type":"bytes16"},{"internalType":"bytes16[]","name":"subjects","type":"bytes16[]"}],"name":"voteToCurse","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b506040516200596238038062005962833981016040819052620000349162000aff565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be8162000138565b505060408051608081018252600080825260208201819052918101919091526001600160c81b03606082015290506001620000fb81601062000c7d565b82606001516001600160c81b0316901c6001600160c81b0316101562000125576200012562000c99565b506200013181620001e3565b5062000e14565b336001600160a01b03821603620001925760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b620001ee816200071d565b6200020c576040516306b7c75960e31b815260040160405180910390fd5b602081015160038054604084015161ffff908116620100000263ffffffff199092169316929092179190911790555b60025415620003465760028054600091906200025a9060019062000c7d565b815481106200026d576200026d62000caf565b6000918252602080832060408051608081018252600294850290920180546001600160a01b0390811680855260019092015480821685870190815260ff600160a01b8304811687870152600160a81b909204909116606086015291875260058552828720805465ffffffffffff19169055905116855260099092529220805461ffff191690558054919250908062000309576200030962000cc5565b60008281526020902060026000199092019182020180546001600160a01b031916815560010180546001600160b01b03191690559055506200023b565b60005b81515181101562000403578151805160029190839081106200036f576200036f62000caf565b602090810291909101810151825460018181018555600094855293839020825160029092020180546001600160a01b039283166001600160a01b0319909116178155928201519284018054604084015160609094015160ff908116600160a81b0260ff60a81b1991909516600160a01b026001600160a81b0319909216959093169490941793909317161790550162000349565b50600480546000906200041c9063ffffffff1662000cdb565b82546101009290920a63ffffffff8181021990931691831602179091556004541660005b82515160ff821610156200054157600083600001518260ff16815181106200046c576200046c62000caf565b602090810291909101810151604080516060808201835263ffffffff80891683528385015160ff90811684880190815289821685870190815287516001600160a01b03908116600090815260058b5288812097518854945193518616650100000000000260ff60281b199487166401000000000264ffffffffff1990961691909716179390931791909116939093179094558587015190911683526009909552919020805491909201519092166101000261ffff1990921691909117600117905550620005398162000d01565b905062000440565b506001600160a01b0360005260096020527f3bddde647ecb7992f4c710d4e1d59d07614508581f7c22c879a79d28544538a7805461ffff191660011790556004805463ffffffff4381166401000000000263ffffffff60201b1990921691909117909155604051908216907f8c49fda8177c5c8c768eb39634bc6773695c7181711537b822451c12b2efd2a990620005db90859062000d23565b60405180910390a26040805160c08101825260048082526001600160401b03421660208301526000928201839052606082018390526080820183905260a08201839052600c80546001808201835591909452825160029094027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7018054939490939092849260ff19909216919084908111156200067c576200067c62000dce565b021790555060208201518154604084015160608501516001600160a01b03166a010000000000000000000002600160501b600160f01b031991151569010000000000000000000260ff60481b196001600160401b039095166101000294909416610100600160501b031990931692909217929092179190911617815560808083015160a090930151811c600160801b0292901c919091176001909101555050565b80515160009015806200073257508151516010105b80620007445750602082015161ffff16155b80620007565750604082015161ffff16155b156200076457506000919050565b600080600084600001515160026200077d919062000de4565b6001600160401b0381111562000797576200079762000a24565b604051908082528060200260200182016040528015620007c1578160200160208202803683370190505b50905060005b8551518110156200095457600086600001518281518110620007ed57620007ed62000caf565b6020026020010151905060006001600160a01b031681600001516001600160a01b0316148062000828575060208101516001600160a01b0316155b806200083f575060208101516001600160a01b0316155b8062000858575060208101516001600160a01b03908116145b806200087a5750604081015160ff161580156200087a5750606081015160ff16155b156200088d575060009695505050505050565b8051836200089d84600262000de4565b620008aa90600062000dfe565b81518110620008bd57620008bd62000caf565b6001600160a01b0390921660209283029190910182015281015183620008e584600262000de4565b620008f290600162000dfe565b8151811062000905576200090562000caf565b6001600160a01b03909216602092830291909101909101526040810151620009319060ff168662000dfe565b9450806060015160ff168462000948919062000dfe565b935050600101620007c7565b5060005b8151811015620009f957600082828151811062000979576200097962000caf565b60200260200101519050600082600162000994919062000dfe565b90505b8351811015620009ee57838181518110620009b657620009b662000caf565b60200260200101516001600160a01b0316826001600160a01b031603620009e557506000979650505050505050565b60010162000997565b505060010162000958565b50846020015161ffff16831015801562000a1b5750846040015161ffff168210155b95945050505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171562000a5f5762000a5f62000a24565b60405290565b604051608081016001600160401b038111828210171562000a5f5762000a5f62000a24565b604051601f8201601f191681016001600160401b038111828210171562000ab55762000ab562000a24565b604052919050565b80516001600160a01b038116811462000ad557600080fd5b919050565b805160ff8116811462000ad557600080fd5b805161ffff8116811462000ad557600080fd5b6000602080838503121562000b1357600080fd5b82516001600160401b038082111562000b2b57600080fd5b8185019150606080838803121562000b4257600080fd5b62000b4c62000a3a565b83518381111562000b5c57600080fd5b8401601f8101891362000b6e57600080fd5b80518481111562000b835762000b8362000a24565b62000b93878260051b0162000a8a565b818152878101955060079190911b82018701908a82111562000bb457600080fd5b918701915b8183101562000c33576080838c03121562000bd45760008081fd5b62000bde62000a65565b62000be98462000abd565b815262000bf889850162000abd565b89820152604062000c0b81860162000ada565b9082015262000c1c84870162000ada565b818701528652948701946080929092019162000bb9565b83525062000c45905084860162000aec565b8582015262000c576040850162000aec565b6040820152979650505050505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111562000c935762000c9362000c67565b92915050565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b600063ffffffff80831681810362000cf75762000cf762000c67565b6001019392505050565b600060ff821660ff810362000d1a5762000d1a62000c67565b60010192915050565b60006020808352608080840185516060808588015282825180855260a0890191508684019450600093505b8084101562000da157845180516001600160a01b03908116845288820151168884015260408082015160ff9081169185019190915290840151168383015293860193600193909301929085019062000d4e565b509488015161ffff8116604089015294604089015161ffff811660608a0152955098975050505050505050565b634e487b7160e01b600052602160045260246000fd5b808202811582820484141762000c935762000c9362000c67565b8082018082111562000c935762000c9362000c67565b614b3e8062000e246000396000f3fe608060405234801561001057600080fd5b50600436106101825760003560e01c8063631ec73e116100d8578063979986111161008c578063d927f26711610066578063d927f26714610354578063f2fde38b14610374578063f33f28951461038757600080fd5b8063979986111461030b578063ba86a1f01461031e578063bd147ef41461033157600080fd5b806379ba5097116100bd57806379ba5097146102d35780638da5cb5b146102db578063970b8fc21461030357600080fd5b8063631ec73e146102ad5780636ba0526d146102c057600080fd5b8063397796f71161013a5780634102e4f4116101145780634102e4f4146102745780634d61677114610287578063586abe3c1461029a57600080fd5b8063397796f7146102425780633d0cf6101461024a5780633f42ab731461025d57600080fd5b8063181f5a771161016b578063181f5a77146101ba5780632cbc26bb14610203578063328d716c1461022657600080fd5b80630b009be21461018757806315c65588146101a5575b600080fd5b61018f6103a9565b60405161019c9190613e3f565b60405180910390f35b6101b86101b3366004613fdd565b6103ba565b005b6101f66040518060400160405280600981526020017f524d4e20312e352e30000000000000000000000000000000000000000000000081525081565b60405161019c9190614083565b6102166102113660046140f0565b6104e6565b604051901515815260200161019c565b600b5467ffffffffffffffff165b60405190815260200161019c565b6102166105b1565b6101b86102583660046141a0565b61068b565b6102656107ff565b60405161019c939291906142b3565b6101b86102823660046142ff565b610929565b610216610295366004614439565b61093d565b6101b86102a8366004614451565b6109cd565b6101b86102bb3660046144fc565b610a87565b6101b86102ce366004614451565b610ca0565b6101b8610d13565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019c565b600c54610234565b6101b86103193660046145d0565b610e10565b6101b861032c3660046145d0565b611368565b61034461033f3660046140f0565b61150d565b60405161019c9493929190614645565b6103676103623660046146b6565b611946565b60405161019c9190614707565b6101b8610382366004614800565b611b68565b61039a610395366004614439565b611b79565b60405161019c9392919061481b565b60606103b56007611de1565b905090565b336000818152600960205260409020805460ff16610421576040517f85412e7f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b60045463ffffffff166000805b85518110156104a757600086828151811061044b5761044b614849565b602002602001015190506000610465858360000151611df5565b905060008061047b6001888b8760008d89611fd6565b91509150801561048d5761048d614878565b85806104965750815b95505050505080600101905061042e565b50806104df576040517ffb106b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b600b5460009067ffffffffffffffff16810361050457506000919050565b7f0100000000000000000000000000000100000000000000000000000000000000600052600a6020527fcf943f0e419056430919a3fdfd72276bc0b123ebdd670f4152b82bffbfb8bb385468010000000000000000900460ff16806105a657507fffffffffffffffffffffffffffffffff0000000000000000000000000000000082166000908152600a602052604090205468010000000000000000900460ff165b92915050565b919050565b600b5460009067ffffffffffffffff1681036105cd5750600090565b7f0100000000000000000000000000000100000000000000000000000000000000600052600a6020527fcf943f0e419056430919a3fdfd72276bc0b123ebdd670f4152b82bffbfb8bb385468010000000000000000900460ff16806103b55750507f0100000000000000000000000000000000000000000000000000000000000000600052600a6020527f1d4cd6d2639449a552dbfb463b59316946d78c518b3170daa4a4c217bef019ba5468010000000000000000900460ff1690565b6106936126a4565b60005b8251811015610746576106cc8382815181106106b4576106b4614849565b6020026020010151600761272790919063ffffffff16565b1561073e577fdca892154bbc36d0c05ccd01b3d0411875cb1b841fcdeebb384e5d0d6eb06b4483828151811061070457610704614849565b6020026020010151604051610735919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180910390a15b600101610696565b5060005b81518110156107fa5761078082828151811061076857610768614849565b6020026020010151600761274990919063ffffffff16565b156107f2577f66b4b4752c65ae8cd2f3a0a48c7dc8b2118c60d5ea15514992eb2ddf56c9cb158282815181106107b8576107b8614849565b60200260200101516040516107e9919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180910390a15b60010161074a565b505050565b6040805160608082018352808252600060208084018290528385018290526004548551600280549384028201608090810190985294810183815263ffffffff808416986401000000009094041696959194919385939192859285015b828210156108f95760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff740100000000000000000000000000000000000000008204811693850193909352750100000000000000000000000000000000000000000090049091166060830152908352909201910161085b565b505050908252506001919091015461ffff8082166020840152620100009091041660409091015292939192919050565b6109316126a4565b61093a8161276b565b50565b600060068161099b610954368690038601866148a7565b80516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b815260208101919091526040016000205460ff16806105a657506105a66109c56020840184614800565b600790612eef565b337fffffffffffffffffffffffff000000000000000000000000000000000000000181016109fd576109fd614878565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600960205260409020805460ff16610a75576040517f85412e7f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610418565b610a8182858584612f1e565b50505050565b610a8f6126a4565b600454600090819063ffffffff16815b8451811015610b66576000858281518110610abc57610abc614849565b602002602001015190506000610ada84836020015160000151611df5565b9050600080610b3d600087866000015187602001518860400151600960008b6000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002089611fd6565b915091508680610b4a5750815b96508780610b555750805b975050505050806001019050610a9f565b508215610c615760408051600280546080602082028401810190945260608301818152610c61948492849160009085015b82821015610c355760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff7401000000000000000000000000000000000000000082048116938501939093527501000000000000000000000000000000000000000000900490911660608301529083529092019101610b97565b505050908252506001919091015461ffff8082166020840152620100009091041660409091015261276b565b8180610c6a5750825b610a81576040517ffb106b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca86126a4565b73ffffffffffffffffffffffffffffffffffffffff60005260096020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f3bddde647ecb7992f4c710d4e1d59d07614508581f7c22c879a79d28544538a7610a8182858584612f1e565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d94576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610418565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e397f01000000000000000000000000000001000000000000000000000000000000006104e6565b15610e70576040517fcde2d97c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454336000908152600560209081526040918290208251606081018452905463ffffffff81811680845260ff64010000000084048116958501959095526501000000000090920490931693820193909352921691908214610f00576040517f85412e7f000000000000000000000000000000000000000000000000000000008152336004820152602401610418565b600160005b8481101561132f576000868683818110610f2157610f21614849565b905060400201803603810190610f3791906148a7565b90506000610f868280516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b6000818152600660209081526040918290208251608081018452905460ff81161580158352610100820463ffffffff169383019390935265010000000000810461ffff169382019390935267010000000000000090920478ffffffffffffffffffffffffffffffffffffffffffffffffff16606083015291925090611062573373ffffffffffffffffffffffffffffffffffffffff168763ffffffff167f274d6d5b916b0a53974b7ab86c844b97a2e03a60f658cd9a4b1c028b604d7bf18560405161105291906148e0565b60405180910390a3505050611327565b8663ffffffff16816020015163ffffffff16146110a8575060408051608081018252600080825263ffffffff89166020830152918101829052606081019190915261110c565b6110ba816060015187604001516136d6565b1561110c573373ffffffffffffffffffffffffffffffffffffffff168763ffffffff167f6dfbb745226fa630aeb1b9557d17d508ddb789a04f0cb873ec16e58beb8beead8560405161105291906148e0565b6000945061112281606001518760400151613718565b78ffffffffffffffffffffffffffffffffffffffffffffffffff166060820152602086015160408201805160ff9092169161115e90839061493c565b61ffff1690525060208681015160408051865173ffffffffffffffffffffffffffffffffffffffff168152868401519381019390935260ff9091168282015251339163ffffffff8a16917f2a08a2bd2798f0aae9a843f0f4ad4de488c1b3d5f04049940cfed736ad69fb979181900360600190a3600354604082015161ffff91821691161061125757600181526040808201518151855173ffffffffffffffffffffffffffffffffffffffff1681526020808701519082015261ffff90911681830152905163ffffffff8916917f8257378aa73bf8e4ada848713526584a3dcee0fd3db3beed7397f7a7f5067cc9919081900360600190a25b60009182526006602090815260409283902082518154928401519484015160609094015178ffffffffffffffffffffffffffffffffffffffffffffffffff166701000000000000000266ffffffffffffff61ffff90951665010000000000029490941664ffffffffff63ffffffff909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000090941693909317179390931617179055505b600101610f05565b5080156104df576040517f604c767700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113706126a4565b60045463ffffffff1660005b82811015610a8157600084848381811061139857611398614849565b9050604002018036038101906113ae91906148a7565b905060006113fd8280516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b60008181526006602081815260408084208151608081018352815460ff811615158252610100810463ffffffff90811683870190815265010000000000830461ffff169584019590955267010000000000000090910478ffffffffffffffffffffffffffffffffffffffffffffffffff16606083015287875294909352939093558051925193945092878216911614806114945750805b156114fe5760408051855173ffffffffffffffffffffffffffffffffffffffff1681526020808701519082015282151581830152905163ffffffff8816917f7d15a6eebaa019ea7d5b7d38937c51ebd3befbfdf51bb630a694fd28635bbcba919081900360600190a25b5050505080600101905061137c565b600454604080516002805460806020820284018101909452606083810182815290958695600095869563ffffffff9093169486949193928492918491879085015b828210156115ec5760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff740100000000000000000000000000000000000000008204811693850193909352750100000000000000000000000000000000000000000090049091166060830152908352909201910161154e565b505050908252506001919091015461ffff80821660208085019190915262010000909204166040928301527fffffffffffffffffffffffffffffffff000000000000000000000000000000008a166000908152600a909152908120805460ff6801000000000000000082041696509293509163ffffffff80861691161080156116725750845b6000965090508560015b60028111611939578451515b6000808760000151518310156116e35787518051849081106116ac576116ac614849565b6020026020010151602001519150876000015183815181106116d0576116d0614849565b602002602001015160600151905061170a565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905060005b73ffffffffffffffffffffffffffffffffffffffff82166000908152600188016020908152604080832081518083019092525463ffffffff811682526401000000009004821b63ffffffff19169181019190915290878061177a57508a63ffffffff16826000015163ffffffff16145b8061179a575073ffffffffffffffffffffffffffffffffffffffff848116145b80156117b05750602082015163ffffffff191615155b9050801561186d57856001036117d0576117c987614957565b965061186d565b85600203610182576117e560ff84168e61493c565b9c506117f08761498f565b9650838f888151811061180557611805614849565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505081602001518e888151811061185657611856614849565b63ffffffff19909216602092830291909101909101525b84156118835761187c8561498f565b945061188c565b50505050611895565b50505050611688565b81600103611928578267ffffffffffffffff8111156118b6576118b6613e52565b6040519080825280602002602001820160405280156118df578160200160208202803683370190505b509a508267ffffffffffffffff8111156118fb576118fb613e52565b604051908082528060200260200182016040528015611924578160200160208202803683370190505b5099505b5061193281614957565b905061167c565b5050505050509193509193565b600c5460609060009061195984866149c4565b11611965575081611988565b600c5484101561198457600c5461197d9085906149d7565b9050611988565b5060005b60008167ffffffffffffffff8111156119a3576119a3613e52565b604051908082528060200260200182016040528015611a2157816020015b6040805160c08101825260008082526020808301829052928201819052606082018190526080820181905260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816119c15790505b50905060005b82811015611b5f57600c611a3b82886149c4565b81548110611a4b57611a4b614849565b600091825260209091206040805160c081019091526002909202018054829060ff166004811115611a7e57611a7e6146d8565b6004811115611a8f57611a8f6146d8565b81528154610100810467ffffffffffffffff1660208301526901000000000000000000810460ff16151560408301526a0100000000000000000000900473ffffffffffffffffffffffffffffffffffffffff166060820152600190910154608081811b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000090811682850152700100000000000000000000000000000000909204901b1660a0909101528251839083908110611b4c57611b4c614849565b6020908102919091010152600101611a27565b50949350505050565b611b706126a4565b61093a8161373b565b606060008080611b91610954368790038701876148a7565b6000818152600660209081526040918290208251608081018452905460ff81161515808352610100820463ffffffff90811694840185905265010000000000830461ffff169584019590955267010000000000000090910478ffffffffffffffffffffffffffffffffffffffffffffffffff166060830152600454909650939450929091169003611dd85760408101516060820151909450611c3281613830565b60ff1667ffffffffffffffff811115611c4d57611c4d613e52565b604051908082528060200260200182016040528015611c76578160200160208202803683370190505b506002805460408051602080840282018101909252828152939950600093929190849084015b82821015611d3a5760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff7401000000000000000000000000000000000000000082048116938501939093527501000000000000000000000000000000000000000000900490911660608301529083529092019101611c9c565b5050505090506000805b82518160ff161015611dd357611d5a84826136d6565b15611dc357828160ff1681518110611d7457611d74614849565b602002602001015160000151898381518110611d9257611d92614849565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152611dc082614957565b91505b611dcc816149ea565b9050611d44565b505050505b50509193909250565b60606000611dee8361389f565b9392505050565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000081166000908152600a60205260408120805463ffffffff858116911614611dee57805463ffffffff19811663ffffffff861690811783556003547fffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000909216176201000090910461ffff1664010000000002177fffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffff1680825568010000000000000000900460ff1615611dee57600260005b8154811015611fcd576000826000018281548110611ee657611ee6614849565b6000918252602080832060016002909302018281015473ffffffffffffffffffffffffffffffffffffffff1684529187019052604090912080549192509063ffffffff808a169116108015611f4d57508054640100000000900460201b63ffffffff191615155b15611fc357805463ffffffff191663ffffffff891617815560018201548554750100000000000000000000000000000000000000000090910460ff16908690600690611fa89084906601000000000000900461ffff1661493c565b92506101000a81548161ffff021916908361ffff1602179055505b5050600101611ec6565b50509392505050565b6000806001896001811115611fed57611fed6146d8565b148061200a57506000896001811115612008576120086146d8565b145b61201657612016614878565b8480612037575073ffffffffffffffffffffffffffffffffffffffff878116145b80612056575073ffffffffffffffffffffffffffffffffffffffff8716155b1561207c57600089600181111561206f5761206f6146d8565b1461207c5761207c614878565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260018401602090815260409182902082518084019093525463ffffffff811683526401000000009004811b63ffffffff191690820152845460ff16801561210d575073ffffffffffffffffffffffffffffffffffffffff888116148061210d57508863ffffffff16816000015163ffffffff16145b80156121235750602081015163ffffffff191615155b801561214b5750866020015163ffffffff1916816020015163ffffffff1916148061214b5750855b156122765773ffffffffffffffffffffffffffffffffffffffff881660009081526001858101602052604082209190915585548554919450610100900460ff169085906006906121aa9084906601000000000000900461ffff16614a09565b825461010092830a61ffff818102199092169282160291909117909255895188546020808d01518a54604080517fffffffffffffffffffffffffffffffff0000000000000000000000000000000090961686529590930460ff169184019190915263ffffffff1916828401526601000000000000900490921660608301525173ffffffffffffffffffffffffffffffffffffffff8b16925063ffffffff8c16917fa96a155bd67c927a6c056befbd979b78465e2b2f1276bf7d4e90a31d4f430aa8919081900360800190a35b6000808b600181111561228b5761228b6146d8565b1480156122b3575083806122b3575073ffffffffffffffffffffffffffffffffffffffff8916155b90508080156122cf5750845468010000000000000000900460ff165b80156122e157506122df856138fb565b155b156123b45784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555600b80546001945060009061232a9067ffffffffffffffff16614a24565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f65d0e78c3625f0956f58610cf0fb157eaf627683258875ef29af2f71d25ac8fd88600001516040516123ab91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b60405180910390a15b83806123bd5750825b15612605576000808c60018111156123d7576123d76146d8565b036123f25787156123ea5750600361240f565b50600261240f565b60018c6001811115612406576124066146d8565b03610182575060015b600c6040518060c0016040528083600481111561242e5761242e6146d8565b81526020014267ffffffffffffffff168152885468010000000000000000900460ff16151560208083019190915273ffffffffffffffffffffffffffffffffffffffff8e1660408301528c517fffffffffffffffffffffffffffffffff00000000000000000000000000000000166060830152600060809092018290528354600180820186559483529120825160029092020180549293909283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836004811115612500576125006146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c9190911760019091015550612696565b8751602080840151818b0151604080517fffffffffffffffffffffffffffffffff00000000000000000000000000000000909516855263ffffffff1992831693850193909352169082015273ffffffffffffffffffffffffffffffffffffffff8a16907fbabb0d7099e6ca14a29fad2a2cfb4fda2bd30f97cb3c27e546174bfb4277c1cc9060600160405180910390a25b505097509795505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612725576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610418565b565b6000611dee8373ffffffffffffffffffffffffffffffffffffffff841661395c565b6000611dee8373ffffffffffffffffffffffffffffffffffffffff8416613a56565b61277481613aa5565b6127aa576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015160038054604084015161ffff908116620100000263ffffffff199092169316929092179190911790555b6002541561298e5760028054600091906127f5906001906149d7565b8154811061280557612805614849565b60009182526020808320604080516080810182526002948502909201805473ffffffffffffffffffffffffffffffffffffffff90811680855260019092015480821685870190815260ff740100000000000000000000000000000000000000008304811687870152750100000000000000000000000000000000000000000090920490911660608601529187526005855282872080547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000016905590511685526009909252922080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690558054919250908061290457612904614a66565b60008281526020902060027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019182020180547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560010180547fffffffffffffffffffff000000000000000000000000000000000000000000001690559055506127d9565b60005b815151811015612ac1578151805160029190839081106129b3576129b3614849565b6020908102919091018101518254600181810185556000948552938390208251600290920201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116178155928201519284018054604084015160609094015160ff9081167501000000000000000000000000000000000000000000027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff9190951674010000000000000000000000000000000000000000027fffffffffffffffffffffff0000000000000000000000000000000000000000009092169590931694909417939093171617905501612991565b5060048054600090612ad89063ffffffff16614a95565b82546101009290920a63ffffffff8181021990931691831602179091556004541660005b82515160ff82161015612c5557600083600001518260ff1681518110612b2457612b24614849565b602090810291909101810151604080516060808201835263ffffffff80891683528385015160ff908116848801908152898216858701908152875173ffffffffffffffffffffffffffffffffffffffff908116600090815260058b528881209751885494519351861665010000000000027fffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffff948716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009096169190971617939093179190911693909317909455858701519091168352600990955291902080549190920151909216610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090921691909117600117905550612c4e816149ea565b9050612afc565b5073ffffffffffffffffffffffffffffffffffffffff60005260096020527f3bddde647ecb7992f4c710d4e1d59d07614508581f7c22c879a79d28544538a780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660011790556004805463ffffffff438116640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff90921691909117909155604051908216907f8c49fda8177c5c8c768eb39634bc6773695c7181711537b822451c12b2efd2a990612d2f908590614ab8565b60405180910390a26040805160c081018252600480825267ffffffffffffffff421660208301526000928201839052606082018390526080820183905260a08201839052600c80546001808201835591909452825160029094027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805493949093909284927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090921691908490811115612dec57612dec6146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c919091176001909101555050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611dee565b8151600003612f59576040517f55e9b08b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008316600090815260018201602052604090205460ff1615613007576040517f078f340000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201527fffffffffffffffffffffffffffffffff0000000000000000000000000000000084166024820152604401610418565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008316600090815260018281016020526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909117905560045463ffffffff16905b83518110156136ce57600181101580156130ed575083818151811061309657613096614849565b60200260200101516fffffffffffffffffffffffffffffffff1916846001836130bf91906149d7565b815181106130cf576130cf614849565b60200260200101516fffffffffffffffffffffffffffffffff191610155b15613124576040517f2432d8ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084828151811061313857613138614849565b60200260200101519050600061314e8483611df5565b73ffffffffffffffffffffffffffffffffffffffff8981166000818152600184016020908152604080832081518083019092525463ffffffff811682526401000000009004821b63ffffffff19169181019190915293945091148015906131be5750815163ffffffff8088169116105b806131d25750602082015163ffffffff1916155b15613225575085548254600091610100900460ff169084906006906132069084906601000000000000900461ffff1661493c565b92506101000a81548161ffff021916908361ffff16021790555061322c565b5060208101515b60408051808201825263ffffffff88168152815163ffffffff1984166020828101919091527fffffffffffffffffffffffffffffffff000000000000000000000000000000008d16828501528351808303850181526060909201909352805190830120909182019063ffffffff1916905273ffffffffffffffffffffffffffffffffffffffff8b166000818152600186016020908152604090912083518285015190921c6401000000000263ffffffff92831617905589549294509091908816907f8137bc8a8d712aaa27bfc6506d5566ac405618bd53f9831b8ca6b6fe5442ee7a9087908d9060ff610100909104166133234290565b6020898101518b54604080517fffffffffffffffffffffffffffffffff000000000000000000000000000000009889168152979096169287019290925260ff9093169385019390935267ffffffffffffffff16606084015263ffffffff191660808301526601000000000000900461ffff1660a082015260c00160405180910390a363ffffffff1981161580156133c85750825468010000000000000000900460ff16155b80156133d857506133d8836138fb565b156134c35782547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff1668010000000000000000178355600b80546000906134289067ffffffffffffffff16614acb565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508563ffffffff167fcfdbfd8ce9a56b5f7c202c0e102184d24f47ca87121dc165063fc4c290957bde8561347e4290565b604080517fffffffffffffffffffffffffffffffff00000000000000000000000000000000909316835267ffffffffffffffff90911660208301520160405180910390a25b6040805160c081018252600080825267ffffffffffffffff42166020830152855460ff680100000000000000009091041615159282019290925273ffffffffffffffffffffffffffffffffffffffff8c1660608201527fffffffffffffffffffffffffffffffff0000000000000000000000000000000086811660808301528b1660a0820152600c80546001808201835591909352815160029093027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805492939092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908360048111156135c0576135c06146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c9190911760019182015594909401935061306f92505050565b505050505050565b600060108260ff16106136eb576136eb614878565b50600160ff82161b821678ffffffffffffffffffffffffffffffffffffffffffffffffff16151592915050565b600060108260ff161061372d5761372d614878565b50600160ff919091161b1790565b3373ffffffffffffffffffffffffffffffffffffffff8216036137ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610418565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006201000078ffffffffffffffffffffffffffffffffffffffffffffffffff83161061385f5761385f614878565b78ffffffffffffffffffffffffffffffffffffffffffffffffff8216156105ac5761388b600183614ae8565b90911690613898816149ea565b905061385f565b6060816000018054806020026020016040519081016040528092919081815260200182805480156138ef57602002820191906000526020600020905b8154815260200190600101908083116138db575b50505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff600090815260018201602090815260408220546401000000009004901b63ffffffff19161515806105a65750505461ffff64010000000082048116660100000000000090920416101590565b60008181526001830160205260408120548015613a455760006139806001836149d7565b8554909150600090613994906001906149d7565b90508181146139f95760008660000182815481106139b4576139b4614849565b90600052602060002001549050808760000184815481106139d7576139d7614849565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613a0a57613a0a614a66565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105a6565b60009150506105a6565b5092915050565b6000818152600183016020526040812054613a9d575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105a6565b5060006105a6565b8051516000901580613ab957508151516010105b80613aca5750602082015161ffff16155b80613adb5750604082015161ffff16155b15613ae857506000919050565b60008060008460000151516002613aff9190614b1a565b67ffffffffffffffff811115613b1757613b17613e52565b604051908082528060200260200182016040528015613b40578160200160208202803683370190505b50905060005b855151811015613d1157600086600001518281518110613b6857613b68614849565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161480613bc95750602081015173ffffffffffffffffffffffffffffffffffffffff16155b80613bec5750602081015173ffffffffffffffffffffffffffffffffffffffff16155b80613c115750602081015173ffffffffffffffffffffffffffffffffffffffff908116145b80613c315750604081015160ff16158015613c315750606081015160ff16155b15613c43575060009695505050505050565b805183613c51846002614b1a565b613c5c9060006149c4565b81518110613c6c57613c6c614849565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910182015281015183613c9f846002614b1a565b613caa9060016149c4565b81518110613cba57613cba614849565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526040810151613cf19060ff16866149c4565b9450806060015160ff1684613d0691906149c4565b935050600101613b46565b5060005b8151811015613dc3576000828281518110613d3257613d32614849565b602002602001015190506000826001613d4b91906149c4565b90505b8351811015613db957838181518110613d6957613d69614849565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613db157506000979650505050505050565b600101613d4e565b5050600101613d15565b50846020015161ffff168310158015613de45750846040015161ffff168210155b95945050505050565b60008151808452602080850194506020840160005b83811015613e3457815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613e02565b509495945050505050565b602081526000611dee6020830184613ded565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613ea457613ea4613e52565b60405290565b6040516060810167ffffffffffffffff81118282101715613ea457613ea4613e52565b6040516080810167ffffffffffffffff81118282101715613ea457613ea4613e52565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613f3757613f37613e52565b604052919050565b600067ffffffffffffffff821115613f5957613f59613e52565b5060051b60200190565b80357fffffffffffffffffffffffffffffffff00000000000000000000000000000000811681146105ac57600080fd5b600060408284031215613fa557600080fd5b613fad613e81565b9050613fb882613f63565b8152602082013563ffffffff1981168114613fd257600080fd5b602082015292915050565b60006020808385031215613ff057600080fd5b823567ffffffffffffffff81111561400757600080fd5b8301601f8101851361401857600080fd5b803561402b61402682613f3f565b613ef0565b8082825260208201915060208360061b85010192508783111561404d57600080fd5b6020840193505b82841015614078576140668885613f93565b82528482019150604084019350614054565b979650505050505050565b60006020808352835180602085015260005b818110156140b157858101830151858201604001528201614095565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60006020828403121561410257600080fd5b611dee82613f63565b803573ffffffffffffffffffffffffffffffffffffffff811681146105ac57600080fd5b600082601f83011261414057600080fd5b8135602061415061402683613f3f565b8083825260208201915060208460051b87010193508684111561417257600080fd5b602086015b84811015614195576141888161410b565b8352918301918301614177565b509695505050505050565b600080604083850312156141b357600080fd5b823567ffffffffffffffff808211156141cb57600080fd5b6141d78683870161412f565b935060208501359150808211156141ed57600080fd5b506141fa8582860161412f565b9150509250929050565b8051606080845281518482018190526000926080916020918201918388019190865b82811015614280578451805173ffffffffffffffffffffffffffffffffffffffff908116865283820151168386015260408082015160ff908116918701919091529088015116878501529381019392850192600101614226565b508781015161ffff81168a83015295505050604086015193506142a9604088018561ffff169052565b9695505050505050565b600063ffffffff808616835280851660208401525060606040830152613de46060830184614204565b803560ff811681146105ac57600080fd5b803561ffff811681146105ac57600080fd5b6000602080838503121561431257600080fd5b823567ffffffffffffffff8082111561432a57600080fd5b8185019150606080838803121561434057600080fd5b614348613eaa565b83358381111561435757600080fd5b84019250601f8301881361436a57600080fd5b823561437861402682613f3f565b81815260079190911b8401860190868101908a83111561439757600080fd5b948701945b82861015614409576080868c0312156143b55760008081fd5b6143bd613ecd565b6143c68761410b565b81526143d389880161410b565b8982015260406143e48189016142dc565b908201526143f38787016142dc565b818701528252608095909501949087019061439c565b83525061441990508486016142ed565b85820152614429604085016142ed565b6040820152979650505050505050565b60006040828403121561444b57600080fd5b50919050565b6000806040838503121561446457600080fd5b61446d83613f63565b915060208084013567ffffffffffffffff81111561448a57600080fd5b8401601f8101861361449b57600080fd5b80356144a961402682613f3f565b81815260059190911b820183019083810190888311156144c857600080fd5b928401925b828410156144ed576144de84613f63565b825292840192908401906144cd565b80955050505050509250929050565b6000602080838503121561450f57600080fd5b823567ffffffffffffffff81111561452657600080fd5b8301601f8101851361453757600080fd5b803561454561402682613f3f565b81815260079190911b8201830190838101908783111561456457600080fd5b928401925b8284101561407857608084890312156145825760008081fd5b61458a613eaa565b6145938561410b565b81526145a189878701613f93565b86820152606085013580151581146145b95760008081fd5b604082015282526080939093019290840190614569565b600080602083850312156145e357600080fd5b823567ffffffffffffffff808211156145fb57600080fd5b818501915085601f83011261460f57600080fd5b81358181111561461e57600080fd5b8660208260061b850101111561463357600080fd5b60209290920196919550909350505050565b6080815260006146586080830187613ded565b82810360208481019190915286518083528782019282019060005b8181101561469657845163ffffffff191683529383019391830191600101614673565b505061ffff96909616604085015250505090151560609091015292915050565b600080604083850312156146c957600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208082528251828201819052600091906040908185019086840185805b838110156147f2578251805160058110614766577f4e487b710000000000000000000000000000000000000000000000000000000084526021600452602484fd5b86528088015167ffffffffffffffff16888701528681015115158787015260608082015173ffffffffffffffffffffffffffffffffffffffff16908701526080808201517fffffffffffffffffffffffffffffffff000000000000000000000000000000009081169188019190915260a091820151169086015260c09094019391860191600101614725565b509298975050505050505050565b60006020828403121561481257600080fd5b611dee8261410b565b60608152600061482e6060830186613ded565b61ffff94909416602083015250901515604090910152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6000604082840312156148b957600080fd5b6148c1613e81565b6148ca8361410b565b8152602083013560208201528091505092915050565b815173ffffffffffffffffffffffffffffffffffffffff16815260208083015190820152604081016105a6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61ffff818116838216019080821115613a4f57613a4f61490d565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036149885761498861490d565b5060010190565b60008161499e5761499e61490d565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b808201808211156105a6576105a661490d565b818103818111156105a6576105a661490d565b600060ff821660ff8103614a0057614a0061490d565b60010192915050565b61ffff828116828216039080821115613a4f57613a4f61490d565b600067ffffffffffffffff821680614a3e57614a3e61490d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600063ffffffff808316818103614aae57614aae61490d565b6001019392505050565b602081526000611dee6020830184614204565b600067ffffffffffffffff808316818103614aae57614aae61490d565b78ffffffffffffffffffffffffffffffffffffffffffffffffff828116828216039080821115613a4f57613a4f61490d565b80820281158282048414176105a6576105a661490d56fea164736f6c6343000818000a00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000bf469bd18b258f1eb3710a6b53778d650d193d410000000000000000000000007be2c5c3e4b48439314119486008e2e30b32319700000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000765293e01dc24d9aaad886c5bf78767930c4b34e000000000000000000000000fd3a26bdf612494b4c7dc0b14c1e8304bbec046500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000e9005e15eff73fb2c08a44b72003c01caa7a8fb0000000000000000000000000933c057f8e10dcd733c6c836ad3a36a956fcec7300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000dffd4d4556edbb629e2d15756da736582625d318000000000000000000000000857626295e895a2f44ae1c1f57d239bb515d9cb80000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000082dd2be746810245f978a20a28e86dff8b9cfe2f0000000000000000000000001f645d004dcaa833d439fed98c07bcf6c77d7d900000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000079f44a2acd6bb225b6ec113eb435fe463b4e201b00000000000000000000000073623ccfb74e22bf8d90cca342d736b8e8ff905900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101825760003560e01c8063631ec73e116100d8578063979986111161008c578063d927f26711610066578063d927f26714610354578063f2fde38b14610374578063f33f28951461038757600080fd5b8063979986111461030b578063ba86a1f01461031e578063bd147ef41461033157600080fd5b806379ba5097116100bd57806379ba5097146102d35780638da5cb5b146102db578063970b8fc21461030357600080fd5b8063631ec73e146102ad5780636ba0526d146102c057600080fd5b8063397796f71161013a5780634102e4f4116101145780634102e4f4146102745780634d61677114610287578063586abe3c1461029a57600080fd5b8063397796f7146102425780633d0cf6101461024a5780633f42ab731461025d57600080fd5b8063181f5a771161016b578063181f5a77146101ba5780632cbc26bb14610203578063328d716c1461022657600080fd5b80630b009be21461018757806315c65588146101a5575b600080fd5b61018f6103a9565b60405161019c9190613e3f565b60405180910390f35b6101b86101b3366004613fdd565b6103ba565b005b6101f66040518060400160405280600981526020017f524d4e20312e352e30000000000000000000000000000000000000000000000081525081565b60405161019c9190614083565b6102166102113660046140f0565b6104e6565b604051901515815260200161019c565b600b5467ffffffffffffffff165b60405190815260200161019c565b6102166105b1565b6101b86102583660046141a0565b61068b565b6102656107ff565b60405161019c939291906142b3565b6101b86102823660046142ff565b610929565b610216610295366004614439565b61093d565b6101b86102a8366004614451565b6109cd565b6101b86102bb3660046144fc565b610a87565b6101b86102ce366004614451565b610ca0565b6101b8610d13565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019c565b600c54610234565b6101b86103193660046145d0565b610e10565b6101b861032c3660046145d0565b611368565b61034461033f3660046140f0565b61150d565b60405161019c9493929190614645565b6103676103623660046146b6565b611946565b60405161019c9190614707565b6101b8610382366004614800565b611b68565b61039a610395366004614439565b611b79565b60405161019c9392919061481b565b60606103b56007611de1565b905090565b336000818152600960205260409020805460ff16610421576040517f85412e7f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b60045463ffffffff166000805b85518110156104a757600086828151811061044b5761044b614849565b602002602001015190506000610465858360000151611df5565b905060008061047b6001888b8760008d89611fd6565b91509150801561048d5761048d614878565b85806104965750815b95505050505080600101905061042e565b50806104df576040517ffb106b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b600b5460009067ffffffffffffffff16810361050457506000919050565b7f0100000000000000000000000000000100000000000000000000000000000000600052600a6020527fcf943f0e419056430919a3fdfd72276bc0b123ebdd670f4152b82bffbfb8bb385468010000000000000000900460ff16806105a657507fffffffffffffffffffffffffffffffff0000000000000000000000000000000082166000908152600a602052604090205468010000000000000000900460ff165b92915050565b919050565b600b5460009067ffffffffffffffff1681036105cd5750600090565b7f0100000000000000000000000000000100000000000000000000000000000000600052600a6020527fcf943f0e419056430919a3fdfd72276bc0b123ebdd670f4152b82bffbfb8bb385468010000000000000000900460ff16806103b55750507f0100000000000000000000000000000000000000000000000000000000000000600052600a6020527f1d4cd6d2639449a552dbfb463b59316946d78c518b3170daa4a4c217bef019ba5468010000000000000000900460ff1690565b6106936126a4565b60005b8251811015610746576106cc8382815181106106b4576106b4614849565b6020026020010151600761272790919063ffffffff16565b1561073e577fdca892154bbc36d0c05ccd01b3d0411875cb1b841fcdeebb384e5d0d6eb06b4483828151811061070457610704614849565b6020026020010151604051610735919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180910390a15b600101610696565b5060005b81518110156107fa5761078082828151811061076857610768614849565b6020026020010151600761274990919063ffffffff16565b156107f2577f66b4b4752c65ae8cd2f3a0a48c7dc8b2118c60d5ea15514992eb2ddf56c9cb158282815181106107b8576107b8614849565b60200260200101516040516107e9919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180910390a15b60010161074a565b505050565b6040805160608082018352808252600060208084018290528385018290526004548551600280549384028201608090810190985294810183815263ffffffff808416986401000000009094041696959194919385939192859285015b828210156108f95760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff740100000000000000000000000000000000000000008204811693850193909352750100000000000000000000000000000000000000000090049091166060830152908352909201910161085b565b505050908252506001919091015461ffff8082166020840152620100009091041660409091015292939192919050565b6109316126a4565b61093a8161276b565b50565b600060068161099b610954368690038601866148a7565b80516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b815260208101919091526040016000205460ff16806105a657506105a66109c56020840184614800565b600790612eef565b337fffffffffffffffffffffffff000000000000000000000000000000000000000181016109fd576109fd614878565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600960205260409020805460ff16610a75576040517f85412e7f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610418565b610a8182858584612f1e565b50505050565b610a8f6126a4565b600454600090819063ffffffff16815b8451811015610b66576000858281518110610abc57610abc614849565b602002602001015190506000610ada84836020015160000151611df5565b9050600080610b3d600087866000015187602001518860400151600960008b6000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002089611fd6565b915091508680610b4a5750815b96508780610b555750805b975050505050806001019050610a9f565b508215610c615760408051600280546080602082028401810190945260608301818152610c61948492849160009085015b82821015610c355760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff7401000000000000000000000000000000000000000082048116938501939093527501000000000000000000000000000000000000000000900490911660608301529083529092019101610b97565b505050908252506001919091015461ffff8082166020840152620100009091041660409091015261276b565b8180610c6a5750825b610a81576040517ffb106b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca86126a4565b73ffffffffffffffffffffffffffffffffffffffff60005260096020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f3bddde647ecb7992f4c710d4e1d59d07614508581f7c22c879a79d28544538a7610a8182858584612f1e565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d94576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610418565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e397f01000000000000000000000000000001000000000000000000000000000000006104e6565b15610e70576040517fcde2d97c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454336000908152600560209081526040918290208251606081018452905463ffffffff81811680845260ff64010000000084048116958501959095526501000000000090920490931693820193909352921691908214610f00576040517f85412e7f000000000000000000000000000000000000000000000000000000008152336004820152602401610418565b600160005b8481101561132f576000868683818110610f2157610f21614849565b905060400201803603810190610f3791906148a7565b90506000610f868280516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b6000818152600660209081526040918290208251608081018452905460ff81161580158352610100820463ffffffff169383019390935265010000000000810461ffff169382019390935267010000000000000090920478ffffffffffffffffffffffffffffffffffffffffffffffffff16606083015291925090611062573373ffffffffffffffffffffffffffffffffffffffff168763ffffffff167f274d6d5b916b0a53974b7ab86c844b97a2e03a60f658cd9a4b1c028b604d7bf18560405161105291906148e0565b60405180910390a3505050611327565b8663ffffffff16816020015163ffffffff16146110a8575060408051608081018252600080825263ffffffff89166020830152918101829052606081019190915261110c565b6110ba816060015187604001516136d6565b1561110c573373ffffffffffffffffffffffffffffffffffffffff168763ffffffff167f6dfbb745226fa630aeb1b9557d17d508ddb789a04f0cb873ec16e58beb8beead8560405161105291906148e0565b6000945061112281606001518760400151613718565b78ffffffffffffffffffffffffffffffffffffffffffffffffff166060820152602086015160408201805160ff9092169161115e90839061493c565b61ffff1690525060208681015160408051865173ffffffffffffffffffffffffffffffffffffffff168152868401519381019390935260ff9091168282015251339163ffffffff8a16917f2a08a2bd2798f0aae9a843f0f4ad4de488c1b3d5f04049940cfed736ad69fb979181900360600190a3600354604082015161ffff91821691161061125757600181526040808201518151855173ffffffffffffffffffffffffffffffffffffffff1681526020808701519082015261ffff90911681830152905163ffffffff8916917f8257378aa73bf8e4ada848713526584a3dcee0fd3db3beed7397f7a7f5067cc9919081900360600190a25b60009182526006602090815260409283902082518154928401519484015160609094015178ffffffffffffffffffffffffffffffffffffffffffffffffff166701000000000000000266ffffffffffffff61ffff90951665010000000000029490941664ffffffffff63ffffffff909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000090941693909317179390931617179055505b600101610f05565b5080156104df576040517f604c767700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113706126a4565b60045463ffffffff1660005b82811015610a8157600084848381811061139857611398614849565b9050604002018036038101906113ae91906148a7565b905060006113fd8280516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b60008181526006602081815260408084208151608081018352815460ff811615158252610100810463ffffffff90811683870190815265010000000000830461ffff169584019590955267010000000000000090910478ffffffffffffffffffffffffffffffffffffffffffffffffff16606083015287875294909352939093558051925193945092878216911614806114945750805b156114fe5760408051855173ffffffffffffffffffffffffffffffffffffffff1681526020808701519082015282151581830152905163ffffffff8816917f7d15a6eebaa019ea7d5b7d38937c51ebd3befbfdf51bb630a694fd28635bbcba919081900360600190a25b5050505080600101905061137c565b600454604080516002805460806020820284018101909452606083810182815290958695600095869563ffffffff9093169486949193928492918491879085015b828210156115ec5760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff740100000000000000000000000000000000000000008204811693850193909352750100000000000000000000000000000000000000000090049091166060830152908352909201910161154e565b505050908252506001919091015461ffff80821660208085019190915262010000909204166040928301527fffffffffffffffffffffffffffffffff000000000000000000000000000000008a166000908152600a909152908120805460ff6801000000000000000082041696509293509163ffffffff80861691161080156116725750845b6000965090508560015b60028111611939578451515b6000808760000151518310156116e35787518051849081106116ac576116ac614849565b6020026020010151602001519150876000015183815181106116d0576116d0614849565b602002602001015160600151905061170a565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905060005b73ffffffffffffffffffffffffffffffffffffffff82166000908152600188016020908152604080832081518083019092525463ffffffff811682526401000000009004821b63ffffffff19169181019190915290878061177a57508a63ffffffff16826000015163ffffffff16145b8061179a575073ffffffffffffffffffffffffffffffffffffffff848116145b80156117b05750602082015163ffffffff191615155b9050801561186d57856001036117d0576117c987614957565b965061186d565b85600203610182576117e560ff84168e61493c565b9c506117f08761498f565b9650838f888151811061180557611805614849565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505081602001518e888151811061185657611856614849565b63ffffffff19909216602092830291909101909101525b84156118835761187c8561498f565b945061188c565b50505050611895565b50505050611688565b81600103611928578267ffffffffffffffff8111156118b6576118b6613e52565b6040519080825280602002602001820160405280156118df578160200160208202803683370190505b509a508267ffffffffffffffff8111156118fb576118fb613e52565b604051908082528060200260200182016040528015611924578160200160208202803683370190505b5099505b5061193281614957565b905061167c565b5050505050509193509193565b600c5460609060009061195984866149c4565b11611965575081611988565b600c5484101561198457600c5461197d9085906149d7565b9050611988565b5060005b60008167ffffffffffffffff8111156119a3576119a3613e52565b604051908082528060200260200182016040528015611a2157816020015b6040805160c08101825260008082526020808301829052928201819052606082018190526080820181905260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816119c15790505b50905060005b82811015611b5f57600c611a3b82886149c4565b81548110611a4b57611a4b614849565b600091825260209091206040805160c081019091526002909202018054829060ff166004811115611a7e57611a7e6146d8565b6004811115611a8f57611a8f6146d8565b81528154610100810467ffffffffffffffff1660208301526901000000000000000000810460ff16151560408301526a0100000000000000000000900473ffffffffffffffffffffffffffffffffffffffff166060820152600190910154608081811b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000090811682850152700100000000000000000000000000000000909204901b1660a0909101528251839083908110611b4c57611b4c614849565b6020908102919091010152600101611a27565b50949350505050565b611b706126a4565b61093a8161373b565b606060008080611b91610954368790038701876148a7565b6000818152600660209081526040918290208251608081018452905460ff81161515808352610100820463ffffffff90811694840185905265010000000000830461ffff169584019590955267010000000000000090910478ffffffffffffffffffffffffffffffffffffffffffffffffff166060830152600454909650939450929091169003611dd85760408101516060820151909450611c3281613830565b60ff1667ffffffffffffffff811115611c4d57611c4d613e52565b604051908082528060200260200182016040528015611c76578160200160208202803683370190505b506002805460408051602080840282018101909252828152939950600093929190849084015b82821015611d3a5760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff7401000000000000000000000000000000000000000082048116938501939093527501000000000000000000000000000000000000000000900490911660608301529083529092019101611c9c565b5050505090506000805b82518160ff161015611dd357611d5a84826136d6565b15611dc357828160ff1681518110611d7457611d74614849565b602002602001015160000151898381518110611d9257611d92614849565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152611dc082614957565b91505b611dcc816149ea565b9050611d44565b505050505b50509193909250565b60606000611dee8361389f565b9392505050565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000081166000908152600a60205260408120805463ffffffff858116911614611dee57805463ffffffff19811663ffffffff861690811783556003547fffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000909216176201000090910461ffff1664010000000002177fffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffff1680825568010000000000000000900460ff1615611dee57600260005b8154811015611fcd576000826000018281548110611ee657611ee6614849565b6000918252602080832060016002909302018281015473ffffffffffffffffffffffffffffffffffffffff1684529187019052604090912080549192509063ffffffff808a169116108015611f4d57508054640100000000900460201b63ffffffff191615155b15611fc357805463ffffffff191663ffffffff891617815560018201548554750100000000000000000000000000000000000000000090910460ff16908690600690611fa89084906601000000000000900461ffff1661493c565b92506101000a81548161ffff021916908361ffff1602179055505b5050600101611ec6565b50509392505050565b6000806001896001811115611fed57611fed6146d8565b148061200a57506000896001811115612008576120086146d8565b145b61201657612016614878565b8480612037575073ffffffffffffffffffffffffffffffffffffffff878116145b80612056575073ffffffffffffffffffffffffffffffffffffffff8716155b1561207c57600089600181111561206f5761206f6146d8565b1461207c5761207c614878565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260018401602090815260409182902082518084019093525463ffffffff811683526401000000009004811b63ffffffff191690820152845460ff16801561210d575073ffffffffffffffffffffffffffffffffffffffff888116148061210d57508863ffffffff16816000015163ffffffff16145b80156121235750602081015163ffffffff191615155b801561214b5750866020015163ffffffff1916816020015163ffffffff1916148061214b5750855b156122765773ffffffffffffffffffffffffffffffffffffffff881660009081526001858101602052604082209190915585548554919450610100900460ff169085906006906121aa9084906601000000000000900461ffff16614a09565b825461010092830a61ffff818102199092169282160291909117909255895188546020808d01518a54604080517fffffffffffffffffffffffffffffffff0000000000000000000000000000000090961686529590930460ff169184019190915263ffffffff1916828401526601000000000000900490921660608301525173ffffffffffffffffffffffffffffffffffffffff8b16925063ffffffff8c16917fa96a155bd67c927a6c056befbd979b78465e2b2f1276bf7d4e90a31d4f430aa8919081900360800190a35b6000808b600181111561228b5761228b6146d8565b1480156122b3575083806122b3575073ffffffffffffffffffffffffffffffffffffffff8916155b90508080156122cf5750845468010000000000000000900460ff165b80156122e157506122df856138fb565b155b156123b45784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555600b80546001945060009061232a9067ffffffffffffffff16614a24565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f65d0e78c3625f0956f58610cf0fb157eaf627683258875ef29af2f71d25ac8fd88600001516040516123ab91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b60405180910390a15b83806123bd5750825b15612605576000808c60018111156123d7576123d76146d8565b036123f25787156123ea5750600361240f565b50600261240f565b60018c6001811115612406576124066146d8565b03610182575060015b600c6040518060c0016040528083600481111561242e5761242e6146d8565b81526020014267ffffffffffffffff168152885468010000000000000000900460ff16151560208083019190915273ffffffffffffffffffffffffffffffffffffffff8e1660408301528c517fffffffffffffffffffffffffffffffff00000000000000000000000000000000166060830152600060809092018290528354600180820186559483529120825160029092020180549293909283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836004811115612500576125006146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c9190911760019091015550612696565b8751602080840151818b0151604080517fffffffffffffffffffffffffffffffff00000000000000000000000000000000909516855263ffffffff1992831693850193909352169082015273ffffffffffffffffffffffffffffffffffffffff8a16907fbabb0d7099e6ca14a29fad2a2cfb4fda2bd30f97cb3c27e546174bfb4277c1cc9060600160405180910390a25b505097509795505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612725576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610418565b565b6000611dee8373ffffffffffffffffffffffffffffffffffffffff841661395c565b6000611dee8373ffffffffffffffffffffffffffffffffffffffff8416613a56565b61277481613aa5565b6127aa576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015160038054604084015161ffff908116620100000263ffffffff199092169316929092179190911790555b6002541561298e5760028054600091906127f5906001906149d7565b8154811061280557612805614849565b60009182526020808320604080516080810182526002948502909201805473ffffffffffffffffffffffffffffffffffffffff90811680855260019092015480821685870190815260ff740100000000000000000000000000000000000000008304811687870152750100000000000000000000000000000000000000000090920490911660608601529187526005855282872080547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000016905590511685526009909252922080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690558054919250908061290457612904614a66565b60008281526020902060027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019182020180547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560010180547fffffffffffffffffffff000000000000000000000000000000000000000000001690559055506127d9565b60005b815151811015612ac1578151805160029190839081106129b3576129b3614849565b6020908102919091018101518254600181810185556000948552938390208251600290920201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116178155928201519284018054604084015160609094015160ff9081167501000000000000000000000000000000000000000000027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff9190951674010000000000000000000000000000000000000000027fffffffffffffffffffffff0000000000000000000000000000000000000000009092169590931694909417939093171617905501612991565b5060048054600090612ad89063ffffffff16614a95565b82546101009290920a63ffffffff8181021990931691831602179091556004541660005b82515160ff82161015612c5557600083600001518260ff1681518110612b2457612b24614849565b602090810291909101810151604080516060808201835263ffffffff80891683528385015160ff908116848801908152898216858701908152875173ffffffffffffffffffffffffffffffffffffffff908116600090815260058b528881209751885494519351861665010000000000027fffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffff948716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009096169190971617939093179190911693909317909455858701519091168352600990955291902080549190920151909216610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090921691909117600117905550612c4e816149ea565b9050612afc565b5073ffffffffffffffffffffffffffffffffffffffff60005260096020527f3bddde647ecb7992f4c710d4e1d59d07614508581f7c22c879a79d28544538a780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660011790556004805463ffffffff438116640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff90921691909117909155604051908216907f8c49fda8177c5c8c768eb39634bc6773695c7181711537b822451c12b2efd2a990612d2f908590614ab8565b60405180910390a26040805160c081018252600480825267ffffffffffffffff421660208301526000928201839052606082018390526080820183905260a08201839052600c80546001808201835591909452825160029094027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805493949093909284927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090921691908490811115612dec57612dec6146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c919091176001909101555050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611dee565b8151600003612f59576040517f55e9b08b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008316600090815260018201602052604090205460ff1615613007576040517f078f340000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201527fffffffffffffffffffffffffffffffff0000000000000000000000000000000084166024820152604401610418565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008316600090815260018281016020526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909117905560045463ffffffff16905b83518110156136ce57600181101580156130ed575083818151811061309657613096614849565b60200260200101516fffffffffffffffffffffffffffffffff1916846001836130bf91906149d7565b815181106130cf576130cf614849565b60200260200101516fffffffffffffffffffffffffffffffff191610155b15613124576040517f2432d8ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084828151811061313857613138614849565b60200260200101519050600061314e8483611df5565b73ffffffffffffffffffffffffffffffffffffffff8981166000818152600184016020908152604080832081518083019092525463ffffffff811682526401000000009004821b63ffffffff19169181019190915293945091148015906131be5750815163ffffffff8088169116105b806131d25750602082015163ffffffff1916155b15613225575085548254600091610100900460ff169084906006906132069084906601000000000000900461ffff1661493c565b92506101000a81548161ffff021916908361ffff16021790555061322c565b5060208101515b60408051808201825263ffffffff88168152815163ffffffff1984166020828101919091527fffffffffffffffffffffffffffffffff000000000000000000000000000000008d16828501528351808303850181526060909201909352805190830120909182019063ffffffff1916905273ffffffffffffffffffffffffffffffffffffffff8b166000818152600186016020908152604090912083518285015190921c6401000000000263ffffffff92831617905589549294509091908816907f8137bc8a8d712aaa27bfc6506d5566ac405618bd53f9831b8ca6b6fe5442ee7a9087908d9060ff610100909104166133234290565b6020898101518b54604080517fffffffffffffffffffffffffffffffff000000000000000000000000000000009889168152979096169287019290925260ff9093169385019390935267ffffffffffffffff16606084015263ffffffff191660808301526601000000000000900461ffff1660a082015260c00160405180910390a363ffffffff1981161580156133c85750825468010000000000000000900460ff16155b80156133d857506133d8836138fb565b156134c35782547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff1668010000000000000000178355600b80546000906134289067ffffffffffffffff16614acb565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508563ffffffff167fcfdbfd8ce9a56b5f7c202c0e102184d24f47ca87121dc165063fc4c290957bde8561347e4290565b604080517fffffffffffffffffffffffffffffffff00000000000000000000000000000000909316835267ffffffffffffffff90911660208301520160405180910390a25b6040805160c081018252600080825267ffffffffffffffff42166020830152855460ff680100000000000000009091041615159282019290925273ffffffffffffffffffffffffffffffffffffffff8c1660608201527fffffffffffffffffffffffffffffffff0000000000000000000000000000000086811660808301528b1660a0820152600c80546001808201835591909352815160029093027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805492939092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908360048111156135c0576135c06146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c9190911760019182015594909401935061306f92505050565b505050505050565b600060108260ff16106136eb576136eb614878565b50600160ff82161b821678ffffffffffffffffffffffffffffffffffffffffffffffffff16151592915050565b600060108260ff161061372d5761372d614878565b50600160ff919091161b1790565b3373ffffffffffffffffffffffffffffffffffffffff8216036137ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610418565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006201000078ffffffffffffffffffffffffffffffffffffffffffffffffff83161061385f5761385f614878565b78ffffffffffffffffffffffffffffffffffffffffffffffffff8216156105ac5761388b600183614ae8565b90911690613898816149ea565b905061385f565b6060816000018054806020026020016040519081016040528092919081815260200182805480156138ef57602002820191906000526020600020905b8154815260200190600101908083116138db575b50505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff600090815260018201602090815260408220546401000000009004901b63ffffffff19161515806105a65750505461ffff64010000000082048116660100000000000090920416101590565b60008181526001830160205260408120548015613a455760006139806001836149d7565b8554909150600090613994906001906149d7565b90508181146139f95760008660000182815481106139b4576139b4614849565b90600052602060002001549050808760000184815481106139d7576139d7614849565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613a0a57613a0a614a66565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105a6565b60009150506105a6565b5092915050565b6000818152600183016020526040812054613a9d575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105a6565b5060006105a6565b8051516000901580613ab957508151516010105b80613aca5750602082015161ffff16155b80613adb5750604082015161ffff16155b15613ae857506000919050565b60008060008460000151516002613aff9190614b1a565b67ffffffffffffffff811115613b1757613b17613e52565b604051908082528060200260200182016040528015613b40578160200160208202803683370190505b50905060005b855151811015613d1157600086600001518281518110613b6857613b68614849565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161480613bc95750602081015173ffffffffffffffffffffffffffffffffffffffff16155b80613bec5750602081015173ffffffffffffffffffffffffffffffffffffffff16155b80613c115750602081015173ffffffffffffffffffffffffffffffffffffffff908116145b80613c315750604081015160ff16158015613c315750606081015160ff16155b15613c43575060009695505050505050565b805183613c51846002614b1a565b613c5c9060006149c4565b81518110613c6c57613c6c614849565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910182015281015183613c9f846002614b1a565b613caa9060016149c4565b81518110613cba57613cba614849565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526040810151613cf19060ff16866149c4565b9450806060015160ff1684613d0691906149c4565b935050600101613b46565b5060005b8151811015613dc3576000828281518110613d3257613d32614849565b602002602001015190506000826001613d4b91906149c4565b90505b8351811015613db957838181518110613d6957613d69614849565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613db157506000979650505050505050565b600101613d4e565b5050600101613d15565b50846020015161ffff168310158015613de45750846040015161ffff168210155b95945050505050565b60008151808452602080850194506020840160005b83811015613e3457815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613e02565b509495945050505050565b602081526000611dee6020830184613ded565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613ea457613ea4613e52565b60405290565b6040516060810167ffffffffffffffff81118282101715613ea457613ea4613e52565b6040516080810167ffffffffffffffff81118282101715613ea457613ea4613e52565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613f3757613f37613e52565b604052919050565b600067ffffffffffffffff821115613f5957613f59613e52565b5060051b60200190565b80357fffffffffffffffffffffffffffffffff00000000000000000000000000000000811681146105ac57600080fd5b600060408284031215613fa557600080fd5b613fad613e81565b9050613fb882613f63565b8152602082013563ffffffff1981168114613fd257600080fd5b602082015292915050565b60006020808385031215613ff057600080fd5b823567ffffffffffffffff81111561400757600080fd5b8301601f8101851361401857600080fd5b803561402b61402682613f3f565b613ef0565b8082825260208201915060208360061b85010192508783111561404d57600080fd5b6020840193505b82841015614078576140668885613f93565b82528482019150604084019350614054565b979650505050505050565b60006020808352835180602085015260005b818110156140b157858101830151858201604001528201614095565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60006020828403121561410257600080fd5b611dee82613f63565b803573ffffffffffffffffffffffffffffffffffffffff811681146105ac57600080fd5b600082601f83011261414057600080fd5b8135602061415061402683613f3f565b8083825260208201915060208460051b87010193508684111561417257600080fd5b602086015b84811015614195576141888161410b565b8352918301918301614177565b509695505050505050565b600080604083850312156141b357600080fd5b823567ffffffffffffffff808211156141cb57600080fd5b6141d78683870161412f565b935060208501359150808211156141ed57600080fd5b506141fa8582860161412f565b9150509250929050565b8051606080845281518482018190526000926080916020918201918388019190865b82811015614280578451805173ffffffffffffffffffffffffffffffffffffffff908116865283820151168386015260408082015160ff908116918701919091529088015116878501529381019392850192600101614226565b508781015161ffff81168a83015295505050604086015193506142a9604088018561ffff169052565b9695505050505050565b600063ffffffff808616835280851660208401525060606040830152613de46060830184614204565b803560ff811681146105ac57600080fd5b803561ffff811681146105ac57600080fd5b6000602080838503121561431257600080fd5b823567ffffffffffffffff8082111561432a57600080fd5b8185019150606080838803121561434057600080fd5b614348613eaa565b83358381111561435757600080fd5b84019250601f8301881361436a57600080fd5b823561437861402682613f3f565b81815260079190911b8401860190868101908a83111561439757600080fd5b948701945b82861015614409576080868c0312156143b55760008081fd5b6143bd613ecd565b6143c68761410b565b81526143d389880161410b565b8982015260406143e48189016142dc565b908201526143f38787016142dc565b818701528252608095909501949087019061439c565b83525061441990508486016142ed565b85820152614429604085016142ed565b6040820152979650505050505050565b60006040828403121561444b57600080fd5b50919050565b6000806040838503121561446457600080fd5b61446d83613f63565b915060208084013567ffffffffffffffff81111561448a57600080fd5b8401601f8101861361449b57600080fd5b80356144a961402682613f3f565b81815260059190911b820183019083810190888311156144c857600080fd5b928401925b828410156144ed576144de84613f63565b825292840192908401906144cd565b80955050505050509250929050565b6000602080838503121561450f57600080fd5b823567ffffffffffffffff81111561452657600080fd5b8301601f8101851361453757600080fd5b803561454561402682613f3f565b81815260079190911b8201830190838101908783111561456457600080fd5b928401925b8284101561407857608084890312156145825760008081fd5b61458a613eaa565b6145938561410b565b81526145a189878701613f93565b86820152606085013580151581146145b95760008081fd5b604082015282526080939093019290840190614569565b600080602083850312156145e357600080fd5b823567ffffffffffffffff808211156145fb57600080fd5b818501915085601f83011261460f57600080fd5b81358181111561461e57600080fd5b8660208260061b850101111561463357600080fd5b60209290920196919550909350505050565b6080815260006146586080830187613ded565b82810360208481019190915286518083528782019282019060005b8181101561469657845163ffffffff191683529383019391830191600101614673565b505061ffff96909616604085015250505090151560609091015292915050565b600080604083850312156146c957600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208082528251828201819052600091906040908185019086840185805b838110156147f2578251805160058110614766577f4e487b710000000000000000000000000000000000000000000000000000000084526021600452602484fd5b86528088015167ffffffffffffffff16888701528681015115158787015260608082015173ffffffffffffffffffffffffffffffffffffffff16908701526080808201517fffffffffffffffffffffffffffffffff000000000000000000000000000000009081169188019190915260a091820151169086015260c09094019391860191600101614725565b509298975050505050505050565b60006020828403121561481257600080fd5b611dee8261410b565b60608152600061482e6060830186613ded565b61ffff94909416602083015250901515604090910152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6000604082840312156148b957600080fd5b6148c1613e81565b6148ca8361410b565b8152602083013560208201528091505092915050565b815173ffffffffffffffffffffffffffffffffffffffff16815260208083015190820152604081016105a6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61ffff818116838216019080821115613a4f57613a4f61490d565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036149885761498861490d565b5060010190565b60008161499e5761499e61490d565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b808201808211156105a6576105a661490d565b818103818111156105a6576105a661490d565b600060ff821660ff8103614a0057614a0061490d565b60010192915050565b61ffff828116828216039080821115613a4f57613a4f61490d565b600067ffffffffffffffff821680614a3e57614a3e61490d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600063ffffffff808316818103614aae57614aae61490d565b6001019392505050565b602081526000611dee6020830184614204565b600067ffffffffffffffff808316818103614aae57614aae61490d565b78ffffffffffffffffffffffffffffffffffffffffffffffffff828116828216039080821115613a4f57613a4f61490d565b80820281158282048414176105a6576105a661490d56fea164736f6c6343000818000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000bf469bd18b258f1eb3710a6b53778d650d193d410000000000000000000000007be2c5c3e4b48439314119486008e2e30b32319700000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000765293e01dc24d9aaad886c5bf78767930c4b34e000000000000000000000000fd3a26bdf612494b4c7dc0b14c1e8304bbec046500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000e9005e15eff73fb2c08a44b72003c01caa7a8fb0000000000000000000000000933c057f8e10dcd733c6c836ad3a36a956fcec7300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000dffd4d4556edbb629e2d15756da736582625d318000000000000000000000000857626295e895a2f44ae1c1f57d239bb515d9cb80000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000082dd2be746810245f978a20a28e86dff8b9cfe2f0000000000000000000000001f645d004dcaa833d439fed98c07bcf6c77d7d900000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000079f44a2acd6bb225b6ec113eb435fe463b4e201b00000000000000000000000073623ccfb74e22bf8d90cca342d736b8e8ff905900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : config (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
-----Encoded View---------------
29 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [5] : 000000000000000000000000bf469bd18b258f1eb3710a6b53778d650d193d41
Arg [6] : 0000000000000000000000007be2c5c3e4b48439314119486008e2e30b323197
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [9] : 000000000000000000000000765293e01dc24d9aaad886c5bf78767930c4b34e
Arg [10] : 000000000000000000000000fd3a26bdf612494b4c7dc0b14c1e8304bbec0465
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [13] : 000000000000000000000000e9005e15eff73fb2c08a44b72003c01caa7a8fb0
Arg [14] : 000000000000000000000000933c057f8e10dcd733c6c836ad3a36a956fcec73
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [16] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [17] : 000000000000000000000000dffd4d4556edbb629e2d15756da736582625d318
Arg [18] : 000000000000000000000000857626295e895a2f44ae1c1f57d239bb515d9cb8
Arg [19] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [20] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [21] : 00000000000000000000000082dd2be746810245f978a20a28e86dff8b9cfe2f
Arg [22] : 0000000000000000000000001f645d004dcaa833d439fed98c07bcf6c77d7d90
Arg [23] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [24] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [25] : 00000000000000000000000079f44a2acd6bb225b6ec113eb435fe463b4e201b
Arg [26] : 00000000000000000000000073623ccfb74e22bf8d90cca342d736b8e8ff9059
Arg [27] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [28] : 0000000000000000000000000000000000000000000000000000000000000001
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
[ Download: CSV Export ]
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.