Feature Tip: Add private address tag to any address under My Name Tag !
This nametag was submitted by Kleros Scout.
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 83,517 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Vote To Bless | 23721928 | 26 secs ago | IN | 0 ETH | 0.00010124 | ||||
| Vote To Bless | 23721928 | 26 secs ago | IN | 0 ETH | 0.0001369 | ||||
| Vote To Bless | 23721921 | 1 min ago | IN | 0 ETH | 0.00010209 | ||||
| Vote To Bless | 23721921 | 1 min ago | IN | 0 ETH | 0.00013804 | ||||
| Vote To Bless | 23721913 | 3 mins ago | IN | 0 ETH | 0.0001027 | ||||
| Vote To Bless | 23721913 | 3 mins ago | IN | 0 ETH | 0.00013886 | ||||
| Vote To Bless | 23721825 | 21 mins ago | IN | 0 ETH | 0.00010888 | ||||
| Vote To Bless | 23721825 | 21 mins ago | IN | 0 ETH | 0.00014722 | ||||
| Vote To Bless | 23721690 | 48 mins ago | IN | 0 ETH | 0.00010939 | ||||
| Vote To Bless | 23721690 | 48 mins ago | IN | 0 ETH | 0.00014792 | ||||
| Vote To Bless | 23721633 | 1 hr ago | IN | 0 ETH | 0.00010778 | ||||
| Vote To Bless | 23721631 | 1 hr ago | IN | 0 ETH | 0.00010744 | ||||
| Vote To Bless | 23721631 | 1 hr ago | IN | 0 ETH | 0.00014527 | ||||
| Vote To Bless | 23721623 | 1 hr ago | IN | 0 ETH | 0.00014695 | ||||
| Vote To Bless | 23721591 | 1 hr ago | IN | 0 ETH | 0.00010747 | ||||
| Vote To Bless | 23721591 | 1 hr ago | IN | 0 ETH | 0.00014531 | ||||
| Vote To Bless | 23721548 | 1 hr ago | IN | 0 ETH | 0.00011963 | ||||
| Vote To Bless | 23721548 | 1 hr ago | IN | 0 ETH | 0.00016175 | ||||
| Vote To Bless | 23721527 | 1 hr ago | IN | 0 ETH | 0.00011834 | ||||
| Vote To Bless | 23721527 | 1 hr ago | IN | 0 ETH | 0.00016001 | ||||
| Vote To Bless | 23721468 | 1 hr ago | IN | 0 ETH | 0.00012471 | ||||
| Vote To Bless | 23721468 | 1 hr ago | IN | 0 ETH | 0.00016862 | ||||
| Vote To Bless | 23721434 | 1 hr ago | IN | 0 ETH | 0.00013299 | ||||
| Vote To Bless | 23721434 | 1 hr ago | IN | 0 ETH | 0.00017983 | ||||
| Vote To Bless | 23721431 | 1 hr ago | IN | 0 ETH | 0.00012466 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
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/v5.0.2/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 v5.0.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.20;
/**
* @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.
*
* ```solidity
* 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 is the index of the value in the `values` array plus 1.
// Position 0 is used to mean a value is not in the set.
mapping(bytes32 value => uint256) _positions;
}
/**
* @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._positions[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 cache the value's position to prevent multiple reads from the same storage slot
uint256 position = set._positions[value];
if (position != 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 valueIndex = position - 1;
uint256 lastIndex = set._values.length - 1;
if (valueIndex != lastIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the lastValue to the index where the value to delete is
set._values[valueIndex] = lastValue;
// Update the tracked position of the lastValue (that was just moved)
set._positions[lastValue] = position;
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the tracked position for the deleted slot
delete set._positions[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._positions[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/",
"@chainlink/=node_modules/@chainlink/"
],
"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": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"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
60806040523480156200001157600080fd5b506040516200596238038062005962833981016040819052620000349162000aff565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be8162000138565b505060408051608081018252600080825260208201819052918101919091526001600160c81b03606082015290506001620000fb81601062000c7d565b82606001516001600160c81b0316901c6001600160c81b0316101562000125576200012562000c99565b506200013181620001e3565b5062000e14565b336001600160a01b03821603620001925760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b620001ee816200071d565b6200020c576040516306b7c75960e31b815260040160405180910390fd5b602081015160038054604084015161ffff908116620100000263ffffffff199092169316929092179190911790555b60025415620003465760028054600091906200025a9060019062000c7d565b815481106200026d576200026d62000caf565b6000918252602080832060408051608081018252600294850290920180546001600160a01b0390811680855260019092015480821685870190815260ff600160a01b8304811687870152600160a81b909204909116606086015291875260058552828720805465ffffffffffff19169055905116855260099092529220805461ffff191690558054919250908062000309576200030962000cc5565b60008281526020902060026000199092019182020180546001600160a01b031916815560010180546001600160b01b03191690559055506200023b565b60005b81515181101562000403578151805160029190839081106200036f576200036f62000caf565b602090810291909101810151825460018181018555600094855293839020825160029092020180546001600160a01b039283166001600160a01b0319909116178155928201519284018054604084015160609094015160ff908116600160a81b0260ff60a81b1991909516600160a01b026001600160a81b0319909216959093169490941793909317161790550162000349565b50600480546000906200041c9063ffffffff1662000cdb565b82546101009290920a63ffffffff8181021990931691831602179091556004541660005b82515160ff821610156200054157600083600001518260ff16815181106200046c576200046c62000caf565b602090810291909101810151604080516060808201835263ffffffff80891683528385015160ff90811684880190815289821685870190815287516001600160a01b03908116600090815260058b5288812097518854945193518616650100000000000260ff60281b199487166401000000000264ffffffffff1990961691909716179390931791909116939093179094558587015190911683526009909552919020805491909201519092166101000261ffff1990921691909117600117905550620005398162000d01565b905062000440565b506001600160a01b0360005260096020527f3bddde647ecb7992f4c710d4e1d59d07614508581f7c22c879a79d28544538a7805461ffff191660011790556004805463ffffffff4381166401000000000263ffffffff60201b1990921691909117909155604051908216907f8c49fda8177c5c8c768eb39634bc6773695c7181711537b822451c12b2efd2a990620005db90859062000d23565b60405180910390a26040805160c08101825260048082526001600160401b03421660208301526000928201839052606082018390526080820183905260a08201839052600c80546001808201835591909452825160029094027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7018054939490939092849260ff19909216919084908111156200067c576200067c62000dce565b021790555060208201518154604084015160608501516001600160a01b03166a010000000000000000000002600160501b600160f01b031991151569010000000000000000000260ff60481b196001600160401b039095166101000294909416610100600160501b031990931692909217929092179190911617815560808083015160a090930151811c600160801b0292901c919091176001909101555050565b80515160009015806200073257508151516010105b80620007445750602082015161ffff16155b80620007565750604082015161ffff16155b156200076457506000919050565b600080600084600001515160026200077d919062000de4565b6001600160401b0381111562000797576200079762000a24565b604051908082528060200260200182016040528015620007c1578160200160208202803683370190505b50905060005b8551518110156200095457600086600001518281518110620007ed57620007ed62000caf565b6020026020010151905060006001600160a01b031681600001516001600160a01b0316148062000828575060208101516001600160a01b0316155b806200083f575060208101516001600160a01b0316155b8062000858575060208101516001600160a01b03908116145b806200087a5750604081015160ff161580156200087a5750606081015160ff16155b156200088d575060009695505050505050565b8051836200089d84600262000de4565b620008aa90600062000dfe565b81518110620008bd57620008bd62000caf565b6001600160a01b0390921660209283029190910182015281015183620008e584600262000de4565b620008f290600162000dfe565b8151811062000905576200090562000caf565b6001600160a01b03909216602092830291909101909101526040810151620009319060ff168662000dfe565b9450806060015160ff168462000948919062000dfe565b935050600101620007c7565b5060005b8151811015620009f957600082828151811062000979576200097962000caf565b60200260200101519050600082600162000994919062000dfe565b90505b8351811015620009ee57838181518110620009b657620009b662000caf565b60200260200101516001600160a01b0316826001600160a01b031603620009e557506000979650505050505050565b60010162000997565b505060010162000958565b50846020015161ffff16831015801562000a1b5750846040015161ffff168210155b95945050505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171562000a5f5762000a5f62000a24565b60405290565b604051608081016001600160401b038111828210171562000a5f5762000a5f62000a24565b604051601f8201601f191681016001600160401b038111828210171562000ab55762000ab562000a24565b604052919050565b80516001600160a01b038116811462000ad557600080fd5b919050565b805160ff8116811462000ad557600080fd5b805161ffff8116811462000ad557600080fd5b6000602080838503121562000b1357600080fd5b82516001600160401b038082111562000b2b57600080fd5b8185019150606080838803121562000b4257600080fd5b62000b4c62000a3a565b83518381111562000b5c57600080fd5b8401601f8101891362000b6e57600080fd5b80518481111562000b835762000b8362000a24565b62000b93878260051b0162000a8a565b818152878101955060079190911b82018701908a82111562000bb457600080fd5b918701915b8183101562000c33576080838c03121562000bd45760008081fd5b62000bde62000a65565b62000be98462000abd565b815262000bf889850162000abd565b89820152604062000c0b81860162000ada565b9082015262000c1c84870162000ada565b818701528652948701946080929092019162000bb9565b83525062000c45905084860162000aec565b8582015262000c576040850162000aec565b6040820152979650505050505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111562000c935762000c9362000c67565b92915050565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b600063ffffffff80831681810362000cf75762000cf762000c67565b6001019392505050565b600060ff821660ff810362000d1a5762000d1a62000c67565b60010192915050565b60006020808352608080840185516060808588015282825180855260a0890191508684019450600093505b8084101562000da157845180516001600160a01b03908116845288820151168884015260408082015160ff9081169185019190915290840151168383015293860193600193909301929085019062000d4e565b509488015161ffff8116604089015294604089015161ffff811660608a0152955098975050505050505050565b634e487b7160e01b600052602160045260246000fd5b808202811582820484141762000c935762000c9362000c67565b8082018082111562000c935762000c9362000c67565b614b3e8062000e246000396000f3fe608060405234801561001057600080fd5b50600436106101825760003560e01c8063631ec73e116100d8578063979986111161008c578063d927f26711610066578063d927f26714610354578063f2fde38b14610374578063f33f28951461038757600080fd5b8063979986111461030b578063ba86a1f01461031e578063bd147ef41461033157600080fd5b806379ba5097116100bd57806379ba5097146102d35780638da5cb5b146102db578063970b8fc21461030357600080fd5b8063631ec73e146102ad5780636ba0526d146102c057600080fd5b8063397796f71161013a5780634102e4f4116101145780634102e4f4146102745780634d61677114610287578063586abe3c1461029a57600080fd5b8063397796f7146102425780633d0cf6101461024a5780633f42ab731461025d57600080fd5b8063181f5a771161016b578063181f5a77146101ba5780632cbc26bb14610203578063328d716c1461022657600080fd5b80630b009be21461018757806315c65588146101a5575b600080fd5b61018f6103a9565b60405161019c9190613e3f565b60405180910390f35b6101b86101b3366004613fdd565b6103ba565b005b6101f66040518060400160405280600981526020017f524d4e20312e352e30000000000000000000000000000000000000000000000081525081565b60405161019c9190614083565b6102166102113660046140f0565b6104e6565b604051901515815260200161019c565b600b5467ffffffffffffffff165b60405190815260200161019c565b6102166105b1565b6101b86102583660046141a0565b61068b565b6102656107ff565b60405161019c939291906142b3565b6101b86102823660046142ff565b610929565b610216610295366004614439565b61093d565b6101b86102a8366004614451565b6109cd565b6101b86102bb3660046144fc565b610a87565b6101b86102ce366004614451565b610ca0565b6101b8610d13565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019c565b600c54610234565b6101b86103193660046145d0565b610e10565b6101b861032c3660046145d0565b611368565b61034461033f3660046140f0565b61150d565b60405161019c9493929190614645565b6103676103623660046146b6565b611946565b60405161019c9190614707565b6101b8610382366004614800565b611b68565b61039a610395366004614439565b611b79565b60405161019c9392919061481b565b60606103b56007611de1565b905090565b336000818152600960205260409020805460ff16610421576040517f85412e7f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b60045463ffffffff166000805b85518110156104a757600086828151811061044b5761044b614849565b602002602001015190506000610465858360000151611df5565b905060008061047b6001888b8760008d89611fd6565b91509150801561048d5761048d614878565b85806104965750815b95505050505080600101905061042e565b50806104df576040517ffb106b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b600b5460009067ffffffffffffffff16810361050457506000919050565b7f0100000000000000000000000000000100000000000000000000000000000000600052600a6020527fcf943f0e419056430919a3fdfd72276bc0b123ebdd670f4152b82bffbfb8bb385468010000000000000000900460ff16806105a657507fffffffffffffffffffffffffffffffff0000000000000000000000000000000082166000908152600a602052604090205468010000000000000000900460ff165b92915050565b919050565b600b5460009067ffffffffffffffff1681036105cd5750600090565b7f0100000000000000000000000000000100000000000000000000000000000000600052600a6020527fcf943f0e419056430919a3fdfd72276bc0b123ebdd670f4152b82bffbfb8bb385468010000000000000000900460ff16806103b55750507f0100000000000000000000000000000000000000000000000000000000000000600052600a6020527f1d4cd6d2639449a552dbfb463b59316946d78c518b3170daa4a4c217bef019ba5468010000000000000000900460ff1690565b6106936126a4565b60005b8251811015610746576106cc8382815181106106b4576106b4614849565b6020026020010151600761272790919063ffffffff16565b1561073e577fdca892154bbc36d0c05ccd01b3d0411875cb1b841fcdeebb384e5d0d6eb06b4483828151811061070457610704614849565b6020026020010151604051610735919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180910390a15b600101610696565b5060005b81518110156107fa5761078082828151811061076857610768614849565b6020026020010151600761274990919063ffffffff16565b156107f2577f66b4b4752c65ae8cd2f3a0a48c7dc8b2118c60d5ea15514992eb2ddf56c9cb158282815181106107b8576107b8614849565b60200260200101516040516107e9919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180910390a15b60010161074a565b505050565b6040805160608082018352808252600060208084018290528385018290526004548551600280549384028201608090810190985294810183815263ffffffff808416986401000000009094041696959194919385939192859285015b828210156108f95760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff740100000000000000000000000000000000000000008204811693850193909352750100000000000000000000000000000000000000000090049091166060830152908352909201910161085b565b505050908252506001919091015461ffff8082166020840152620100009091041660409091015292939192919050565b6109316126a4565b61093a8161276b565b50565b600060068161099b610954368690038601866148a7565b80516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b815260208101919091526040016000205460ff16806105a657506105a66109c56020840184614800565b600790612eef565b337fffffffffffffffffffffffff000000000000000000000000000000000000000181016109fd576109fd614878565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600960205260409020805460ff16610a75576040517f85412e7f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610418565b610a8182858584612f1e565b50505050565b610a8f6126a4565b600454600090819063ffffffff16815b8451811015610b66576000858281518110610abc57610abc614849565b602002602001015190506000610ada84836020015160000151611df5565b9050600080610b3d600087866000015187602001518860400151600960008b6000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002089611fd6565b915091508680610b4a5750815b96508780610b555750805b975050505050806001019050610a9f565b508215610c615760408051600280546080602082028401810190945260608301818152610c61948492849160009085015b82821015610c355760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff7401000000000000000000000000000000000000000082048116938501939093527501000000000000000000000000000000000000000000900490911660608301529083529092019101610b97565b505050908252506001919091015461ffff8082166020840152620100009091041660409091015261276b565b8180610c6a5750825b610a81576040517ffb106b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca86126a4565b73ffffffffffffffffffffffffffffffffffffffff60005260096020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f3bddde647ecb7992f4c710d4e1d59d07614508581f7c22c879a79d28544538a7610a8182858584612f1e565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d94576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610418565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e397f01000000000000000000000000000001000000000000000000000000000000006104e6565b15610e70576040517fcde2d97c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454336000908152600560209081526040918290208251606081018452905463ffffffff81811680845260ff64010000000084048116958501959095526501000000000090920490931693820193909352921691908214610f00576040517f85412e7f000000000000000000000000000000000000000000000000000000008152336004820152602401610418565b600160005b8481101561132f576000868683818110610f2157610f21614849565b905060400201803603810190610f3791906148a7565b90506000610f868280516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b6000818152600660209081526040918290208251608081018452905460ff81161580158352610100820463ffffffff169383019390935265010000000000810461ffff169382019390935267010000000000000090920478ffffffffffffffffffffffffffffffffffffffffffffffffff16606083015291925090611062573373ffffffffffffffffffffffffffffffffffffffff168763ffffffff167f274d6d5b916b0a53974b7ab86c844b97a2e03a60f658cd9a4b1c028b604d7bf18560405161105291906148e0565b60405180910390a3505050611327565b8663ffffffff16816020015163ffffffff16146110a8575060408051608081018252600080825263ffffffff89166020830152918101829052606081019190915261110c565b6110ba816060015187604001516136d6565b1561110c573373ffffffffffffffffffffffffffffffffffffffff168763ffffffff167f6dfbb745226fa630aeb1b9557d17d508ddb789a04f0cb873ec16e58beb8beead8560405161105291906148e0565b6000945061112281606001518760400151613718565b78ffffffffffffffffffffffffffffffffffffffffffffffffff166060820152602086015160408201805160ff9092169161115e90839061493c565b61ffff1690525060208681015160408051865173ffffffffffffffffffffffffffffffffffffffff168152868401519381019390935260ff9091168282015251339163ffffffff8a16917f2a08a2bd2798f0aae9a843f0f4ad4de488c1b3d5f04049940cfed736ad69fb979181900360600190a3600354604082015161ffff91821691161061125757600181526040808201518151855173ffffffffffffffffffffffffffffffffffffffff1681526020808701519082015261ffff90911681830152905163ffffffff8916917f8257378aa73bf8e4ada848713526584a3dcee0fd3db3beed7397f7a7f5067cc9919081900360600190a25b60009182526006602090815260409283902082518154928401519484015160609094015178ffffffffffffffffffffffffffffffffffffffffffffffffff166701000000000000000266ffffffffffffff61ffff90951665010000000000029490941664ffffffffff63ffffffff909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000090941693909317179390931617179055505b600101610f05565b5080156104df576040517f604c767700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113706126a4565b60045463ffffffff1660005b82811015610a8157600084848381811061139857611398614849565b9050604002018036038101906113ae91906148a7565b905060006113fd8280516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b60008181526006602081815260408084208151608081018352815460ff811615158252610100810463ffffffff90811683870190815265010000000000830461ffff169584019590955267010000000000000090910478ffffffffffffffffffffffffffffffffffffffffffffffffff16606083015287875294909352939093558051925193945092878216911614806114945750805b156114fe5760408051855173ffffffffffffffffffffffffffffffffffffffff1681526020808701519082015282151581830152905163ffffffff8816917f7d15a6eebaa019ea7d5b7d38937c51ebd3befbfdf51bb630a694fd28635bbcba919081900360600190a25b5050505080600101905061137c565b600454604080516002805460806020820284018101909452606083810182815290958695600095869563ffffffff9093169486949193928492918491879085015b828210156115ec5760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff740100000000000000000000000000000000000000008204811693850193909352750100000000000000000000000000000000000000000090049091166060830152908352909201910161154e565b505050908252506001919091015461ffff80821660208085019190915262010000909204166040928301527fffffffffffffffffffffffffffffffff000000000000000000000000000000008a166000908152600a909152908120805460ff6801000000000000000082041696509293509163ffffffff80861691161080156116725750845b6000965090508560015b60028111611939578451515b6000808760000151518310156116e35787518051849081106116ac576116ac614849565b6020026020010151602001519150876000015183815181106116d0576116d0614849565b602002602001015160600151905061170a565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905060005b73ffffffffffffffffffffffffffffffffffffffff82166000908152600188016020908152604080832081518083019092525463ffffffff811682526401000000009004821b63ffffffff19169181019190915290878061177a57508a63ffffffff16826000015163ffffffff16145b8061179a575073ffffffffffffffffffffffffffffffffffffffff848116145b80156117b05750602082015163ffffffff191615155b9050801561186d57856001036117d0576117c987614957565b965061186d565b85600203610182576117e560ff84168e61493c565b9c506117f08761498f565b9650838f888151811061180557611805614849565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505081602001518e888151811061185657611856614849565b63ffffffff19909216602092830291909101909101525b84156118835761187c8561498f565b945061188c565b50505050611895565b50505050611688565b81600103611928578267ffffffffffffffff8111156118b6576118b6613e52565b6040519080825280602002602001820160405280156118df578160200160208202803683370190505b509a508267ffffffffffffffff8111156118fb576118fb613e52565b604051908082528060200260200182016040528015611924578160200160208202803683370190505b5099505b5061193281614957565b905061167c565b5050505050509193509193565b600c5460609060009061195984866149c4565b11611965575081611988565b600c5484101561198457600c5461197d9085906149d7565b9050611988565b5060005b60008167ffffffffffffffff8111156119a3576119a3613e52565b604051908082528060200260200182016040528015611a2157816020015b6040805160c08101825260008082526020808301829052928201819052606082018190526080820181905260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816119c15790505b50905060005b82811015611b5f57600c611a3b82886149c4565b81548110611a4b57611a4b614849565b600091825260209091206040805160c081019091526002909202018054829060ff166004811115611a7e57611a7e6146d8565b6004811115611a8f57611a8f6146d8565b81528154610100810467ffffffffffffffff1660208301526901000000000000000000810460ff16151560408301526a0100000000000000000000900473ffffffffffffffffffffffffffffffffffffffff166060820152600190910154608081811b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000090811682850152700100000000000000000000000000000000909204901b1660a0909101528251839083908110611b4c57611b4c614849565b6020908102919091010152600101611a27565b50949350505050565b611b706126a4565b61093a8161373b565b606060008080611b91610954368790038701876148a7565b6000818152600660209081526040918290208251608081018452905460ff81161515808352610100820463ffffffff90811694840185905265010000000000830461ffff169584019590955267010000000000000090910478ffffffffffffffffffffffffffffffffffffffffffffffffff166060830152600454909650939450929091169003611dd85760408101516060820151909450611c3281613830565b60ff1667ffffffffffffffff811115611c4d57611c4d613e52565b604051908082528060200260200182016040528015611c76578160200160208202803683370190505b506002805460408051602080840282018101909252828152939950600093929190849084015b82821015611d3a5760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff7401000000000000000000000000000000000000000082048116938501939093527501000000000000000000000000000000000000000000900490911660608301529083529092019101611c9c565b5050505090506000805b82518160ff161015611dd357611d5a84826136d6565b15611dc357828160ff1681518110611d7457611d74614849565b602002602001015160000151898381518110611d9257611d92614849565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152611dc082614957565b91505b611dcc816149ea565b9050611d44565b505050505b50509193909250565b60606000611dee8361389f565b9392505050565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000081166000908152600a60205260408120805463ffffffff858116911614611dee57805463ffffffff19811663ffffffff861690811783556003547fffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000909216176201000090910461ffff1664010000000002177fffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffff1680825568010000000000000000900460ff1615611dee57600260005b8154811015611fcd576000826000018281548110611ee657611ee6614849565b6000918252602080832060016002909302018281015473ffffffffffffffffffffffffffffffffffffffff1684529187019052604090912080549192509063ffffffff808a169116108015611f4d57508054640100000000900460201b63ffffffff191615155b15611fc357805463ffffffff191663ffffffff891617815560018201548554750100000000000000000000000000000000000000000090910460ff16908690600690611fa89084906601000000000000900461ffff1661493c565b92506101000a81548161ffff021916908361ffff1602179055505b5050600101611ec6565b50509392505050565b6000806001896001811115611fed57611fed6146d8565b148061200a57506000896001811115612008576120086146d8565b145b61201657612016614878565b8480612037575073ffffffffffffffffffffffffffffffffffffffff878116145b80612056575073ffffffffffffffffffffffffffffffffffffffff8716155b1561207c57600089600181111561206f5761206f6146d8565b1461207c5761207c614878565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260018401602090815260409182902082518084019093525463ffffffff811683526401000000009004811b63ffffffff191690820152845460ff16801561210d575073ffffffffffffffffffffffffffffffffffffffff888116148061210d57508863ffffffff16816000015163ffffffff16145b80156121235750602081015163ffffffff191615155b801561214b5750866020015163ffffffff1916816020015163ffffffff1916148061214b5750855b156122765773ffffffffffffffffffffffffffffffffffffffff881660009081526001858101602052604082209190915585548554919450610100900460ff169085906006906121aa9084906601000000000000900461ffff16614a09565b825461010092830a61ffff818102199092169282160291909117909255895188546020808d01518a54604080517fffffffffffffffffffffffffffffffff0000000000000000000000000000000090961686529590930460ff169184019190915263ffffffff1916828401526601000000000000900490921660608301525173ffffffffffffffffffffffffffffffffffffffff8b16925063ffffffff8c16917fa96a155bd67c927a6c056befbd979b78465e2b2f1276bf7d4e90a31d4f430aa8919081900360800190a35b6000808b600181111561228b5761228b6146d8565b1480156122b3575083806122b3575073ffffffffffffffffffffffffffffffffffffffff8916155b90508080156122cf5750845468010000000000000000900460ff165b80156122e157506122df856138fb565b155b156123b45784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555600b80546001945060009061232a9067ffffffffffffffff16614a24565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f65d0e78c3625f0956f58610cf0fb157eaf627683258875ef29af2f71d25ac8fd88600001516040516123ab91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b60405180910390a15b83806123bd5750825b15612605576000808c60018111156123d7576123d76146d8565b036123f25787156123ea5750600361240f565b50600261240f565b60018c6001811115612406576124066146d8565b03610182575060015b600c6040518060c0016040528083600481111561242e5761242e6146d8565b81526020014267ffffffffffffffff168152885468010000000000000000900460ff16151560208083019190915273ffffffffffffffffffffffffffffffffffffffff8e1660408301528c517fffffffffffffffffffffffffffffffff00000000000000000000000000000000166060830152600060809092018290528354600180820186559483529120825160029092020180549293909283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836004811115612500576125006146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c9190911760019091015550612696565b8751602080840151818b0151604080517fffffffffffffffffffffffffffffffff00000000000000000000000000000000909516855263ffffffff1992831693850193909352169082015273ffffffffffffffffffffffffffffffffffffffff8a16907fbabb0d7099e6ca14a29fad2a2cfb4fda2bd30f97cb3c27e546174bfb4277c1cc9060600160405180910390a25b505097509795505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612725576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610418565b565b6000611dee8373ffffffffffffffffffffffffffffffffffffffff841661395c565b6000611dee8373ffffffffffffffffffffffffffffffffffffffff8416613a56565b61277481613aa5565b6127aa576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015160038054604084015161ffff908116620100000263ffffffff199092169316929092179190911790555b6002541561298e5760028054600091906127f5906001906149d7565b8154811061280557612805614849565b60009182526020808320604080516080810182526002948502909201805473ffffffffffffffffffffffffffffffffffffffff90811680855260019092015480821685870190815260ff740100000000000000000000000000000000000000008304811687870152750100000000000000000000000000000000000000000090920490911660608601529187526005855282872080547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000016905590511685526009909252922080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690558054919250908061290457612904614a66565b60008281526020902060027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019182020180547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560010180547fffffffffffffffffffff000000000000000000000000000000000000000000001690559055506127d9565b60005b815151811015612ac1578151805160029190839081106129b3576129b3614849565b6020908102919091018101518254600181810185556000948552938390208251600290920201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116178155928201519284018054604084015160609094015160ff9081167501000000000000000000000000000000000000000000027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff9190951674010000000000000000000000000000000000000000027fffffffffffffffffffffff0000000000000000000000000000000000000000009092169590931694909417939093171617905501612991565b5060048054600090612ad89063ffffffff16614a95565b82546101009290920a63ffffffff8181021990931691831602179091556004541660005b82515160ff82161015612c5557600083600001518260ff1681518110612b2457612b24614849565b602090810291909101810151604080516060808201835263ffffffff80891683528385015160ff908116848801908152898216858701908152875173ffffffffffffffffffffffffffffffffffffffff908116600090815260058b528881209751885494519351861665010000000000027fffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffff948716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009096169190971617939093179190911693909317909455858701519091168352600990955291902080549190920151909216610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090921691909117600117905550612c4e816149ea565b9050612afc565b5073ffffffffffffffffffffffffffffffffffffffff60005260096020527f3bddde647ecb7992f4c710d4e1d59d07614508581f7c22c879a79d28544538a780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660011790556004805463ffffffff438116640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff90921691909117909155604051908216907f8c49fda8177c5c8c768eb39634bc6773695c7181711537b822451c12b2efd2a990612d2f908590614ab8565b60405180910390a26040805160c081018252600480825267ffffffffffffffff421660208301526000928201839052606082018390526080820183905260a08201839052600c80546001808201835591909452825160029094027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805493949093909284927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090921691908490811115612dec57612dec6146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c919091176001909101555050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611dee565b8151600003612f59576040517f55e9b08b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008316600090815260018201602052604090205460ff1615613007576040517f078f340000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201527fffffffffffffffffffffffffffffffff0000000000000000000000000000000084166024820152604401610418565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008316600090815260018281016020526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909117905560045463ffffffff16905b83518110156136ce57600181101580156130ed575083818151811061309657613096614849565b60200260200101516fffffffffffffffffffffffffffffffff1916846001836130bf91906149d7565b815181106130cf576130cf614849565b60200260200101516fffffffffffffffffffffffffffffffff191610155b15613124576040517f2432d8ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084828151811061313857613138614849565b60200260200101519050600061314e8483611df5565b73ffffffffffffffffffffffffffffffffffffffff8981166000818152600184016020908152604080832081518083019092525463ffffffff811682526401000000009004821b63ffffffff19169181019190915293945091148015906131be5750815163ffffffff8088169116105b806131d25750602082015163ffffffff1916155b15613225575085548254600091610100900460ff169084906006906132069084906601000000000000900461ffff1661493c565b92506101000a81548161ffff021916908361ffff16021790555061322c565b5060208101515b60408051808201825263ffffffff88168152815163ffffffff1984166020828101919091527fffffffffffffffffffffffffffffffff000000000000000000000000000000008d16828501528351808303850181526060909201909352805190830120909182019063ffffffff1916905273ffffffffffffffffffffffffffffffffffffffff8b166000818152600186016020908152604090912083518285015190921c6401000000000263ffffffff92831617905589549294509091908816907f8137bc8a8d712aaa27bfc6506d5566ac405618bd53f9831b8ca6b6fe5442ee7a9087908d9060ff610100909104166133234290565b6020898101518b54604080517fffffffffffffffffffffffffffffffff000000000000000000000000000000009889168152979096169287019290925260ff9093169385019390935267ffffffffffffffff16606084015263ffffffff191660808301526601000000000000900461ffff1660a082015260c00160405180910390a363ffffffff1981161580156133c85750825468010000000000000000900460ff16155b80156133d857506133d8836138fb565b156134c35782547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff1668010000000000000000178355600b80546000906134289067ffffffffffffffff16614acb565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508563ffffffff167fcfdbfd8ce9a56b5f7c202c0e102184d24f47ca87121dc165063fc4c290957bde8561347e4290565b604080517fffffffffffffffffffffffffffffffff00000000000000000000000000000000909316835267ffffffffffffffff90911660208301520160405180910390a25b6040805160c081018252600080825267ffffffffffffffff42166020830152855460ff680100000000000000009091041615159282019290925273ffffffffffffffffffffffffffffffffffffffff8c1660608201527fffffffffffffffffffffffffffffffff0000000000000000000000000000000086811660808301528b1660a0820152600c80546001808201835591909352815160029093027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805492939092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908360048111156135c0576135c06146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c9190911760019182015594909401935061306f92505050565b505050505050565b600060108260ff16106136eb576136eb614878565b50600160ff82161b821678ffffffffffffffffffffffffffffffffffffffffffffffffff16151592915050565b600060108260ff161061372d5761372d614878565b50600160ff919091161b1790565b3373ffffffffffffffffffffffffffffffffffffffff8216036137ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610418565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006201000078ffffffffffffffffffffffffffffffffffffffffffffffffff83161061385f5761385f614878565b78ffffffffffffffffffffffffffffffffffffffffffffffffff8216156105ac5761388b600183614ae8565b90911690613898816149ea565b905061385f565b6060816000018054806020026020016040519081016040528092919081815260200182805480156138ef57602002820191906000526020600020905b8154815260200190600101908083116138db575b50505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff600090815260018201602090815260408220546401000000009004901b63ffffffff19161515806105a65750505461ffff64010000000082048116660100000000000090920416101590565b60008181526001830160205260408120548015613a455760006139806001836149d7565b8554909150600090613994906001906149d7565b90508082146139f95760008660000182815481106139b4576139b4614849565b90600052602060002001549050808760000184815481106139d7576139d7614849565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613a0a57613a0a614a66565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105a6565b60009150506105a6565b5092915050565b6000818152600183016020526040812054613a9d575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105a6565b5060006105a6565b8051516000901580613ab957508151516010105b80613aca5750602082015161ffff16155b80613adb5750604082015161ffff16155b15613ae857506000919050565b60008060008460000151516002613aff9190614b1a565b67ffffffffffffffff811115613b1757613b17613e52565b604051908082528060200260200182016040528015613b40578160200160208202803683370190505b50905060005b855151811015613d1157600086600001518281518110613b6857613b68614849565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161480613bc95750602081015173ffffffffffffffffffffffffffffffffffffffff16155b80613bec5750602081015173ffffffffffffffffffffffffffffffffffffffff16155b80613c115750602081015173ffffffffffffffffffffffffffffffffffffffff908116145b80613c315750604081015160ff16158015613c315750606081015160ff16155b15613c43575060009695505050505050565b805183613c51846002614b1a565b613c5c9060006149c4565b81518110613c6c57613c6c614849565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910182015281015183613c9f846002614b1a565b613caa9060016149c4565b81518110613cba57613cba614849565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526040810151613cf19060ff16866149c4565b9450806060015160ff1684613d0691906149c4565b935050600101613b46565b5060005b8151811015613dc3576000828281518110613d3257613d32614849565b602002602001015190506000826001613d4b91906149c4565b90505b8351811015613db957838181518110613d6957613d69614849565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613db157506000979650505050505050565b600101613d4e565b5050600101613d15565b50846020015161ffff168310158015613de45750846040015161ffff168210155b95945050505050565b60008151808452602080850194506020840160005b83811015613e3457815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613e02565b509495945050505050565b602081526000611dee6020830184613ded565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613ea457613ea4613e52565b60405290565b6040516060810167ffffffffffffffff81118282101715613ea457613ea4613e52565b6040516080810167ffffffffffffffff81118282101715613ea457613ea4613e52565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613f3757613f37613e52565b604052919050565b600067ffffffffffffffff821115613f5957613f59613e52565b5060051b60200190565b80357fffffffffffffffffffffffffffffffff00000000000000000000000000000000811681146105ac57600080fd5b600060408284031215613fa557600080fd5b613fad613e81565b9050613fb882613f63565b8152602082013563ffffffff1981168114613fd257600080fd5b602082015292915050565b60006020808385031215613ff057600080fd5b823567ffffffffffffffff81111561400757600080fd5b8301601f8101851361401857600080fd5b803561402b61402682613f3f565b613ef0565b8082825260208201915060208360061b85010192508783111561404d57600080fd5b6020840193505b82841015614078576140668885613f93565b82528482019150604084019350614054565b979650505050505050565b60006020808352835180602085015260005b818110156140b157858101830151858201604001528201614095565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60006020828403121561410257600080fd5b611dee82613f63565b803573ffffffffffffffffffffffffffffffffffffffff811681146105ac57600080fd5b600082601f83011261414057600080fd5b8135602061415061402683613f3f565b8083825260208201915060208460051b87010193508684111561417257600080fd5b602086015b84811015614195576141888161410b565b8352918301918301614177565b509695505050505050565b600080604083850312156141b357600080fd5b823567ffffffffffffffff808211156141cb57600080fd5b6141d78683870161412f565b935060208501359150808211156141ed57600080fd5b506141fa8582860161412f565b9150509250929050565b8051606080845281518482018190526000926080916020918201918388019190865b82811015614280578451805173ffffffffffffffffffffffffffffffffffffffff908116865283820151168386015260408082015160ff908116918701919091529088015116878501529381019392850192600101614226565b508781015161ffff81168a83015295505050604086015193506142a9604088018561ffff169052565b9695505050505050565b600063ffffffff808616835280851660208401525060606040830152613de46060830184614204565b803560ff811681146105ac57600080fd5b803561ffff811681146105ac57600080fd5b6000602080838503121561431257600080fd5b823567ffffffffffffffff8082111561432a57600080fd5b8185019150606080838803121561434057600080fd5b614348613eaa565b83358381111561435757600080fd5b84019250601f8301881361436a57600080fd5b823561437861402682613f3f565b81815260079190911b8401860190868101908a83111561439757600080fd5b948701945b82861015614409576080868c0312156143b55760008081fd5b6143bd613ecd565b6143c68761410b565b81526143d389880161410b565b8982015260406143e48189016142dc565b908201526143f38787016142dc565b818701528252608095909501949087019061439c565b83525061441990508486016142ed565b85820152614429604085016142ed565b6040820152979650505050505050565b60006040828403121561444b57600080fd5b50919050565b6000806040838503121561446457600080fd5b61446d83613f63565b915060208084013567ffffffffffffffff81111561448a57600080fd5b8401601f8101861361449b57600080fd5b80356144a961402682613f3f565b81815260059190911b820183019083810190888311156144c857600080fd5b928401925b828410156144ed576144de84613f63565b825292840192908401906144cd565b80955050505050509250929050565b6000602080838503121561450f57600080fd5b823567ffffffffffffffff81111561452657600080fd5b8301601f8101851361453757600080fd5b803561454561402682613f3f565b81815260079190911b8201830190838101908783111561456457600080fd5b928401925b8284101561407857608084890312156145825760008081fd5b61458a613eaa565b6145938561410b565b81526145a189878701613f93565b86820152606085013580151581146145b95760008081fd5b604082015282526080939093019290840190614569565b600080602083850312156145e357600080fd5b823567ffffffffffffffff808211156145fb57600080fd5b818501915085601f83011261460f57600080fd5b81358181111561461e57600080fd5b8660208260061b850101111561463357600080fd5b60209290920196919550909350505050565b6080815260006146586080830187613ded565b82810360208481019190915286518083528782019282019060005b8181101561469657845163ffffffff191683529383019391830191600101614673565b505061ffff96909616604085015250505090151560609091015292915050565b600080604083850312156146c957600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208082528251828201819052600091906040908185019086840185805b838110156147f2578251805160058110614766577f4e487b710000000000000000000000000000000000000000000000000000000084526021600452602484fd5b86528088015167ffffffffffffffff16888701528681015115158787015260608082015173ffffffffffffffffffffffffffffffffffffffff16908701526080808201517fffffffffffffffffffffffffffffffff000000000000000000000000000000009081169188019190915260a091820151169086015260c09094019391860191600101614725565b509298975050505050505050565b60006020828403121561481257600080fd5b611dee8261410b565b60608152600061482e6060830186613ded565b61ffff94909416602083015250901515604090910152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6000604082840312156148b957600080fd5b6148c1613e81565b6148ca8361410b565b8152602083013560208201528091505092915050565b815173ffffffffffffffffffffffffffffffffffffffff16815260208083015190820152604081016105a6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61ffff818116838216019080821115613a4f57613a4f61490d565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036149885761498861490d565b5060010190565b60008161499e5761499e61490d565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b808201808211156105a6576105a661490d565b818103818111156105a6576105a661490d565b600060ff821660ff8103614a0057614a0061490d565b60010192915050565b61ffff828116828216039080821115613a4f57613a4f61490d565b600067ffffffffffffffff821680614a3e57614a3e61490d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600063ffffffff808316818103614aae57614aae61490d565b6001019392505050565b602081526000611dee6020830184614204565b600067ffffffffffffffff808316818103614aae57614aae61490d565b78ffffffffffffffffffffffffffffffffffffffffffffffffff828116828216039080821115613a4f57613a4f61490d565b80820281158282048414176105a6576105a661490d56fea164736f6c6343000818000a0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000700000000000000000000000023ccf5a7309a9ba850f877313cff35b6903609440000000000000000000000000b59fa90337b8c1dfcf83a60be93df36d3022bf200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000eaa2691fe9c8cef93ccbc1b4b1e4f3ce026789420000000000000000000000000cb702a32e380e6bbe578d73928db35f27dfd0d100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f5d5840ce35ed1e408b26df1f5eb74d6641dfae600000000000000000000000038ea6cea45d30f9a4ba1b7fa28ce840135fe3118000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000009f199d8a106a220d483bd548ef862b15ecd3bfac0000000000000000000000001dca94f408bc850524a320988721642d64870b62000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000008749f722d74b2a8d9af5e4f8011287da3dc058a1000000000000000000000000699e53aba4543726e487771def1781c89dbd30cf000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000bc0fb2faa891d3c48e494bffd3b0bcd53b99ce500000000000000000000000012119a85235939c6d28182f198add16e9c1d7b1100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000d6c690713dc1b3995c200e600d3a00b30299ae08000000000000000000000000c5f450a270dcefdcb990851a280a8a2a3d9403df00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101825760003560e01c8063631ec73e116100d8578063979986111161008c578063d927f26711610066578063d927f26714610354578063f2fde38b14610374578063f33f28951461038757600080fd5b8063979986111461030b578063ba86a1f01461031e578063bd147ef41461033157600080fd5b806379ba5097116100bd57806379ba5097146102d35780638da5cb5b146102db578063970b8fc21461030357600080fd5b8063631ec73e146102ad5780636ba0526d146102c057600080fd5b8063397796f71161013a5780634102e4f4116101145780634102e4f4146102745780634d61677114610287578063586abe3c1461029a57600080fd5b8063397796f7146102425780633d0cf6101461024a5780633f42ab731461025d57600080fd5b8063181f5a771161016b578063181f5a77146101ba5780632cbc26bb14610203578063328d716c1461022657600080fd5b80630b009be21461018757806315c65588146101a5575b600080fd5b61018f6103a9565b60405161019c9190613e3f565b60405180910390f35b6101b86101b3366004613fdd565b6103ba565b005b6101f66040518060400160405280600981526020017f524d4e20312e352e30000000000000000000000000000000000000000000000081525081565b60405161019c9190614083565b6102166102113660046140f0565b6104e6565b604051901515815260200161019c565b600b5467ffffffffffffffff165b60405190815260200161019c565b6102166105b1565b6101b86102583660046141a0565b61068b565b6102656107ff565b60405161019c939291906142b3565b6101b86102823660046142ff565b610929565b610216610295366004614439565b61093d565b6101b86102a8366004614451565b6109cd565b6101b86102bb3660046144fc565b610a87565b6101b86102ce366004614451565b610ca0565b6101b8610d13565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019c565b600c54610234565b6101b86103193660046145d0565b610e10565b6101b861032c3660046145d0565b611368565b61034461033f3660046140f0565b61150d565b60405161019c9493929190614645565b6103676103623660046146b6565b611946565b60405161019c9190614707565b6101b8610382366004614800565b611b68565b61039a610395366004614439565b611b79565b60405161019c9392919061481b565b60606103b56007611de1565b905090565b336000818152600960205260409020805460ff16610421576040517f85412e7f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b60045463ffffffff166000805b85518110156104a757600086828151811061044b5761044b614849565b602002602001015190506000610465858360000151611df5565b905060008061047b6001888b8760008d89611fd6565b91509150801561048d5761048d614878565b85806104965750815b95505050505080600101905061042e565b50806104df576040517ffb106b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b600b5460009067ffffffffffffffff16810361050457506000919050565b7f0100000000000000000000000000000100000000000000000000000000000000600052600a6020527fcf943f0e419056430919a3fdfd72276bc0b123ebdd670f4152b82bffbfb8bb385468010000000000000000900460ff16806105a657507fffffffffffffffffffffffffffffffff0000000000000000000000000000000082166000908152600a602052604090205468010000000000000000900460ff165b92915050565b919050565b600b5460009067ffffffffffffffff1681036105cd5750600090565b7f0100000000000000000000000000000100000000000000000000000000000000600052600a6020527fcf943f0e419056430919a3fdfd72276bc0b123ebdd670f4152b82bffbfb8bb385468010000000000000000900460ff16806103b55750507f0100000000000000000000000000000000000000000000000000000000000000600052600a6020527f1d4cd6d2639449a552dbfb463b59316946d78c518b3170daa4a4c217bef019ba5468010000000000000000900460ff1690565b6106936126a4565b60005b8251811015610746576106cc8382815181106106b4576106b4614849565b6020026020010151600761272790919063ffffffff16565b1561073e577fdca892154bbc36d0c05ccd01b3d0411875cb1b841fcdeebb384e5d0d6eb06b4483828151811061070457610704614849565b6020026020010151604051610735919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180910390a15b600101610696565b5060005b81518110156107fa5761078082828151811061076857610768614849565b6020026020010151600761274990919063ffffffff16565b156107f2577f66b4b4752c65ae8cd2f3a0a48c7dc8b2118c60d5ea15514992eb2ddf56c9cb158282815181106107b8576107b8614849565b60200260200101516040516107e9919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180910390a15b60010161074a565b505050565b6040805160608082018352808252600060208084018290528385018290526004548551600280549384028201608090810190985294810183815263ffffffff808416986401000000009094041696959194919385939192859285015b828210156108f95760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff740100000000000000000000000000000000000000008204811693850193909352750100000000000000000000000000000000000000000090049091166060830152908352909201910161085b565b505050908252506001919091015461ffff8082166020840152620100009091041660409091015292939192919050565b6109316126a4565b61093a8161276b565b50565b600060068161099b610954368690038601866148a7565b80516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b815260208101919091526040016000205460ff16806105a657506105a66109c56020840184614800565b600790612eef565b337fffffffffffffffffffffffff000000000000000000000000000000000000000181016109fd576109fd614878565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600960205260409020805460ff16610a75576040517f85412e7f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610418565b610a8182858584612f1e565b50505050565b610a8f6126a4565b600454600090819063ffffffff16815b8451811015610b66576000858281518110610abc57610abc614849565b602002602001015190506000610ada84836020015160000151611df5565b9050600080610b3d600087866000015187602001518860400151600960008b6000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002089611fd6565b915091508680610b4a5750815b96508780610b555750805b975050505050806001019050610a9f565b508215610c615760408051600280546080602082028401810190945260608301818152610c61948492849160009085015b82821015610c355760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff7401000000000000000000000000000000000000000082048116938501939093527501000000000000000000000000000000000000000000900490911660608301529083529092019101610b97565b505050908252506001919091015461ffff8082166020840152620100009091041660409091015261276b565b8180610c6a5750825b610a81576040517ffb106b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca86126a4565b73ffffffffffffffffffffffffffffffffffffffff60005260096020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f3bddde647ecb7992f4c710d4e1d59d07614508581f7c22c879a79d28544538a7610a8182858584612f1e565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d94576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610418565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e397f01000000000000000000000000000001000000000000000000000000000000006104e6565b15610e70576040517fcde2d97c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454336000908152600560209081526040918290208251606081018452905463ffffffff81811680845260ff64010000000084048116958501959095526501000000000090920490931693820193909352921691908214610f00576040517f85412e7f000000000000000000000000000000000000000000000000000000008152336004820152602401610418565b600160005b8481101561132f576000868683818110610f2157610f21614849565b905060400201803603810190610f3791906148a7565b90506000610f868280516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b6000818152600660209081526040918290208251608081018452905460ff81161580158352610100820463ffffffff169383019390935265010000000000810461ffff169382019390935267010000000000000090920478ffffffffffffffffffffffffffffffffffffffffffffffffff16606083015291925090611062573373ffffffffffffffffffffffffffffffffffffffff168763ffffffff167f274d6d5b916b0a53974b7ab86c844b97a2e03a60f658cd9a4b1c028b604d7bf18560405161105291906148e0565b60405180910390a3505050611327565b8663ffffffff16816020015163ffffffff16146110a8575060408051608081018252600080825263ffffffff89166020830152918101829052606081019190915261110c565b6110ba816060015187604001516136d6565b1561110c573373ffffffffffffffffffffffffffffffffffffffff168763ffffffff167f6dfbb745226fa630aeb1b9557d17d508ddb789a04f0cb873ec16e58beb8beead8560405161105291906148e0565b6000945061112281606001518760400151613718565b78ffffffffffffffffffffffffffffffffffffffffffffffffff166060820152602086015160408201805160ff9092169161115e90839061493c565b61ffff1690525060208681015160408051865173ffffffffffffffffffffffffffffffffffffffff168152868401519381019390935260ff9091168282015251339163ffffffff8a16917f2a08a2bd2798f0aae9a843f0f4ad4de488c1b3d5f04049940cfed736ad69fb979181900360600190a3600354604082015161ffff91821691161061125757600181526040808201518151855173ffffffffffffffffffffffffffffffffffffffff1681526020808701519082015261ffff90911681830152905163ffffffff8916917f8257378aa73bf8e4ada848713526584a3dcee0fd3db3beed7397f7a7f5067cc9919081900360600190a25b60009182526006602090815260409283902082518154928401519484015160609094015178ffffffffffffffffffffffffffffffffffffffffffffffffff166701000000000000000266ffffffffffffff61ffff90951665010000000000029490941664ffffffffff63ffffffff909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000090941693909317179390931617179055505b600101610f05565b5080156104df576040517f604c767700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113706126a4565b60045463ffffffff1660005b82811015610a8157600084848381811061139857611398614849565b9050604002018036038101906113ae91906148a7565b905060006113fd8280516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b60008181526006602081815260408084208151608081018352815460ff811615158252610100810463ffffffff90811683870190815265010000000000830461ffff169584019590955267010000000000000090910478ffffffffffffffffffffffffffffffffffffffffffffffffff16606083015287875294909352939093558051925193945092878216911614806114945750805b156114fe5760408051855173ffffffffffffffffffffffffffffffffffffffff1681526020808701519082015282151581830152905163ffffffff8816917f7d15a6eebaa019ea7d5b7d38937c51ebd3befbfdf51bb630a694fd28635bbcba919081900360600190a25b5050505080600101905061137c565b600454604080516002805460806020820284018101909452606083810182815290958695600095869563ffffffff9093169486949193928492918491879085015b828210156115ec5760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff740100000000000000000000000000000000000000008204811693850193909352750100000000000000000000000000000000000000000090049091166060830152908352909201910161154e565b505050908252506001919091015461ffff80821660208085019190915262010000909204166040928301527fffffffffffffffffffffffffffffffff000000000000000000000000000000008a166000908152600a909152908120805460ff6801000000000000000082041696509293509163ffffffff80861691161080156116725750845b6000965090508560015b60028111611939578451515b6000808760000151518310156116e35787518051849081106116ac576116ac614849565b6020026020010151602001519150876000015183815181106116d0576116d0614849565b602002602001015160600151905061170a565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905060005b73ffffffffffffffffffffffffffffffffffffffff82166000908152600188016020908152604080832081518083019092525463ffffffff811682526401000000009004821b63ffffffff19169181019190915290878061177a57508a63ffffffff16826000015163ffffffff16145b8061179a575073ffffffffffffffffffffffffffffffffffffffff848116145b80156117b05750602082015163ffffffff191615155b9050801561186d57856001036117d0576117c987614957565b965061186d565b85600203610182576117e560ff84168e61493c565b9c506117f08761498f565b9650838f888151811061180557611805614849565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505081602001518e888151811061185657611856614849565b63ffffffff19909216602092830291909101909101525b84156118835761187c8561498f565b945061188c565b50505050611895565b50505050611688565b81600103611928578267ffffffffffffffff8111156118b6576118b6613e52565b6040519080825280602002602001820160405280156118df578160200160208202803683370190505b509a508267ffffffffffffffff8111156118fb576118fb613e52565b604051908082528060200260200182016040528015611924578160200160208202803683370190505b5099505b5061193281614957565b905061167c565b5050505050509193509193565b600c5460609060009061195984866149c4565b11611965575081611988565b600c5484101561198457600c5461197d9085906149d7565b9050611988565b5060005b60008167ffffffffffffffff8111156119a3576119a3613e52565b604051908082528060200260200182016040528015611a2157816020015b6040805160c08101825260008082526020808301829052928201819052606082018190526080820181905260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816119c15790505b50905060005b82811015611b5f57600c611a3b82886149c4565b81548110611a4b57611a4b614849565b600091825260209091206040805160c081019091526002909202018054829060ff166004811115611a7e57611a7e6146d8565b6004811115611a8f57611a8f6146d8565b81528154610100810467ffffffffffffffff1660208301526901000000000000000000810460ff16151560408301526a0100000000000000000000900473ffffffffffffffffffffffffffffffffffffffff166060820152600190910154608081811b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000090811682850152700100000000000000000000000000000000909204901b1660a0909101528251839083908110611b4c57611b4c614849565b6020908102919091010152600101611a27565b50949350505050565b611b706126a4565b61093a8161373b565b606060008080611b91610954368790038701876148a7565b6000818152600660209081526040918290208251608081018452905460ff81161515808352610100820463ffffffff90811694840185905265010000000000830461ffff169584019590955267010000000000000090910478ffffffffffffffffffffffffffffffffffffffffffffffffff166060830152600454909650939450929091169003611dd85760408101516060820151909450611c3281613830565b60ff1667ffffffffffffffff811115611c4d57611c4d613e52565b604051908082528060200260200182016040528015611c76578160200160208202803683370190505b506002805460408051602080840282018101909252828152939950600093929190849084015b82821015611d3a5760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff7401000000000000000000000000000000000000000082048116938501939093527501000000000000000000000000000000000000000000900490911660608301529083529092019101611c9c565b5050505090506000805b82518160ff161015611dd357611d5a84826136d6565b15611dc357828160ff1681518110611d7457611d74614849565b602002602001015160000151898381518110611d9257611d92614849565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152611dc082614957565b91505b611dcc816149ea565b9050611d44565b505050505b50509193909250565b60606000611dee8361389f565b9392505050565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000081166000908152600a60205260408120805463ffffffff858116911614611dee57805463ffffffff19811663ffffffff861690811783556003547fffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000909216176201000090910461ffff1664010000000002177fffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffff1680825568010000000000000000900460ff1615611dee57600260005b8154811015611fcd576000826000018281548110611ee657611ee6614849565b6000918252602080832060016002909302018281015473ffffffffffffffffffffffffffffffffffffffff1684529187019052604090912080549192509063ffffffff808a169116108015611f4d57508054640100000000900460201b63ffffffff191615155b15611fc357805463ffffffff191663ffffffff891617815560018201548554750100000000000000000000000000000000000000000090910460ff16908690600690611fa89084906601000000000000900461ffff1661493c565b92506101000a81548161ffff021916908361ffff1602179055505b5050600101611ec6565b50509392505050565b6000806001896001811115611fed57611fed6146d8565b148061200a57506000896001811115612008576120086146d8565b145b61201657612016614878565b8480612037575073ffffffffffffffffffffffffffffffffffffffff878116145b80612056575073ffffffffffffffffffffffffffffffffffffffff8716155b1561207c57600089600181111561206f5761206f6146d8565b1461207c5761207c614878565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260018401602090815260409182902082518084019093525463ffffffff811683526401000000009004811b63ffffffff191690820152845460ff16801561210d575073ffffffffffffffffffffffffffffffffffffffff888116148061210d57508863ffffffff16816000015163ffffffff16145b80156121235750602081015163ffffffff191615155b801561214b5750866020015163ffffffff1916816020015163ffffffff1916148061214b5750855b156122765773ffffffffffffffffffffffffffffffffffffffff881660009081526001858101602052604082209190915585548554919450610100900460ff169085906006906121aa9084906601000000000000900461ffff16614a09565b825461010092830a61ffff818102199092169282160291909117909255895188546020808d01518a54604080517fffffffffffffffffffffffffffffffff0000000000000000000000000000000090961686529590930460ff169184019190915263ffffffff1916828401526601000000000000900490921660608301525173ffffffffffffffffffffffffffffffffffffffff8b16925063ffffffff8c16917fa96a155bd67c927a6c056befbd979b78465e2b2f1276bf7d4e90a31d4f430aa8919081900360800190a35b6000808b600181111561228b5761228b6146d8565b1480156122b3575083806122b3575073ffffffffffffffffffffffffffffffffffffffff8916155b90508080156122cf5750845468010000000000000000900460ff165b80156122e157506122df856138fb565b155b156123b45784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555600b80546001945060009061232a9067ffffffffffffffff16614a24565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f65d0e78c3625f0956f58610cf0fb157eaf627683258875ef29af2f71d25ac8fd88600001516040516123ab91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b60405180910390a15b83806123bd5750825b15612605576000808c60018111156123d7576123d76146d8565b036123f25787156123ea5750600361240f565b50600261240f565b60018c6001811115612406576124066146d8565b03610182575060015b600c6040518060c0016040528083600481111561242e5761242e6146d8565b81526020014267ffffffffffffffff168152885468010000000000000000900460ff16151560208083019190915273ffffffffffffffffffffffffffffffffffffffff8e1660408301528c517fffffffffffffffffffffffffffffffff00000000000000000000000000000000166060830152600060809092018290528354600180820186559483529120825160029092020180549293909283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836004811115612500576125006146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c9190911760019091015550612696565b8751602080840151818b0151604080517fffffffffffffffffffffffffffffffff00000000000000000000000000000000909516855263ffffffff1992831693850193909352169082015273ffffffffffffffffffffffffffffffffffffffff8a16907fbabb0d7099e6ca14a29fad2a2cfb4fda2bd30f97cb3c27e546174bfb4277c1cc9060600160405180910390a25b505097509795505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612725576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610418565b565b6000611dee8373ffffffffffffffffffffffffffffffffffffffff841661395c565b6000611dee8373ffffffffffffffffffffffffffffffffffffffff8416613a56565b61277481613aa5565b6127aa576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015160038054604084015161ffff908116620100000263ffffffff199092169316929092179190911790555b6002541561298e5760028054600091906127f5906001906149d7565b8154811061280557612805614849565b60009182526020808320604080516080810182526002948502909201805473ffffffffffffffffffffffffffffffffffffffff90811680855260019092015480821685870190815260ff740100000000000000000000000000000000000000008304811687870152750100000000000000000000000000000000000000000090920490911660608601529187526005855282872080547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000016905590511685526009909252922080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690558054919250908061290457612904614a66565b60008281526020902060027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019182020180547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560010180547fffffffffffffffffffff000000000000000000000000000000000000000000001690559055506127d9565b60005b815151811015612ac1578151805160029190839081106129b3576129b3614849565b6020908102919091018101518254600181810185556000948552938390208251600290920201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116178155928201519284018054604084015160609094015160ff9081167501000000000000000000000000000000000000000000027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff9190951674010000000000000000000000000000000000000000027fffffffffffffffffffffff0000000000000000000000000000000000000000009092169590931694909417939093171617905501612991565b5060048054600090612ad89063ffffffff16614a95565b82546101009290920a63ffffffff8181021990931691831602179091556004541660005b82515160ff82161015612c5557600083600001518260ff1681518110612b2457612b24614849565b602090810291909101810151604080516060808201835263ffffffff80891683528385015160ff908116848801908152898216858701908152875173ffffffffffffffffffffffffffffffffffffffff908116600090815260058b528881209751885494519351861665010000000000027fffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffff948716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009096169190971617939093179190911693909317909455858701519091168352600990955291902080549190920151909216610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090921691909117600117905550612c4e816149ea565b9050612afc565b5073ffffffffffffffffffffffffffffffffffffffff60005260096020527f3bddde647ecb7992f4c710d4e1d59d07614508581f7c22c879a79d28544538a780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660011790556004805463ffffffff438116640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff90921691909117909155604051908216907f8c49fda8177c5c8c768eb39634bc6773695c7181711537b822451c12b2efd2a990612d2f908590614ab8565b60405180910390a26040805160c081018252600480825267ffffffffffffffff421660208301526000928201839052606082018390526080820183905260a08201839052600c80546001808201835591909452825160029094027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805493949093909284927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090921691908490811115612dec57612dec6146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c919091176001909101555050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611dee565b8151600003612f59576040517f55e9b08b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008316600090815260018201602052604090205460ff1615613007576040517f078f340000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201527fffffffffffffffffffffffffffffffff0000000000000000000000000000000084166024820152604401610418565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008316600090815260018281016020526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909117905560045463ffffffff16905b83518110156136ce57600181101580156130ed575083818151811061309657613096614849565b60200260200101516fffffffffffffffffffffffffffffffff1916846001836130bf91906149d7565b815181106130cf576130cf614849565b60200260200101516fffffffffffffffffffffffffffffffff191610155b15613124576040517f2432d8ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084828151811061313857613138614849565b60200260200101519050600061314e8483611df5565b73ffffffffffffffffffffffffffffffffffffffff8981166000818152600184016020908152604080832081518083019092525463ffffffff811682526401000000009004821b63ffffffff19169181019190915293945091148015906131be5750815163ffffffff8088169116105b806131d25750602082015163ffffffff1916155b15613225575085548254600091610100900460ff169084906006906132069084906601000000000000900461ffff1661493c565b92506101000a81548161ffff021916908361ffff16021790555061322c565b5060208101515b60408051808201825263ffffffff88168152815163ffffffff1984166020828101919091527fffffffffffffffffffffffffffffffff000000000000000000000000000000008d16828501528351808303850181526060909201909352805190830120909182019063ffffffff1916905273ffffffffffffffffffffffffffffffffffffffff8b166000818152600186016020908152604090912083518285015190921c6401000000000263ffffffff92831617905589549294509091908816907f8137bc8a8d712aaa27bfc6506d5566ac405618bd53f9831b8ca6b6fe5442ee7a9087908d9060ff610100909104166133234290565b6020898101518b54604080517fffffffffffffffffffffffffffffffff000000000000000000000000000000009889168152979096169287019290925260ff9093169385019390935267ffffffffffffffff16606084015263ffffffff191660808301526601000000000000900461ffff1660a082015260c00160405180910390a363ffffffff1981161580156133c85750825468010000000000000000900460ff16155b80156133d857506133d8836138fb565b156134c35782547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff1668010000000000000000178355600b80546000906134289067ffffffffffffffff16614acb565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508563ffffffff167fcfdbfd8ce9a56b5f7c202c0e102184d24f47ca87121dc165063fc4c290957bde8561347e4290565b604080517fffffffffffffffffffffffffffffffff00000000000000000000000000000000909316835267ffffffffffffffff90911660208301520160405180910390a25b6040805160c081018252600080825267ffffffffffffffff42166020830152855460ff680100000000000000009091041615159282019290925273ffffffffffffffffffffffffffffffffffffffff8c1660608201527fffffffffffffffffffffffffffffffff0000000000000000000000000000000086811660808301528b1660a0820152600c80546001808201835591909352815160029093027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805492939092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908360048111156135c0576135c06146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c9190911760019182015594909401935061306f92505050565b505050505050565b600060108260ff16106136eb576136eb614878565b50600160ff82161b821678ffffffffffffffffffffffffffffffffffffffffffffffffff16151592915050565b600060108260ff161061372d5761372d614878565b50600160ff919091161b1790565b3373ffffffffffffffffffffffffffffffffffffffff8216036137ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610418565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006201000078ffffffffffffffffffffffffffffffffffffffffffffffffff83161061385f5761385f614878565b78ffffffffffffffffffffffffffffffffffffffffffffffffff8216156105ac5761388b600183614ae8565b90911690613898816149ea565b905061385f565b6060816000018054806020026020016040519081016040528092919081815260200182805480156138ef57602002820191906000526020600020905b8154815260200190600101908083116138db575b50505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff600090815260018201602090815260408220546401000000009004901b63ffffffff19161515806105a65750505461ffff64010000000082048116660100000000000090920416101590565b60008181526001830160205260408120548015613a455760006139806001836149d7565b8554909150600090613994906001906149d7565b90508082146139f95760008660000182815481106139b4576139b4614849565b90600052602060002001549050808760000184815481106139d7576139d7614849565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613a0a57613a0a614a66565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105a6565b60009150506105a6565b5092915050565b6000818152600183016020526040812054613a9d575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105a6565b5060006105a6565b8051516000901580613ab957508151516010105b80613aca5750602082015161ffff16155b80613adb5750604082015161ffff16155b15613ae857506000919050565b60008060008460000151516002613aff9190614b1a565b67ffffffffffffffff811115613b1757613b17613e52565b604051908082528060200260200182016040528015613b40578160200160208202803683370190505b50905060005b855151811015613d1157600086600001518281518110613b6857613b68614849565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161480613bc95750602081015173ffffffffffffffffffffffffffffffffffffffff16155b80613bec5750602081015173ffffffffffffffffffffffffffffffffffffffff16155b80613c115750602081015173ffffffffffffffffffffffffffffffffffffffff908116145b80613c315750604081015160ff16158015613c315750606081015160ff16155b15613c43575060009695505050505050565b805183613c51846002614b1a565b613c5c9060006149c4565b81518110613c6c57613c6c614849565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910182015281015183613c9f846002614b1a565b613caa9060016149c4565b81518110613cba57613cba614849565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526040810151613cf19060ff16866149c4565b9450806060015160ff1684613d0691906149c4565b935050600101613b46565b5060005b8151811015613dc3576000828281518110613d3257613d32614849565b602002602001015190506000826001613d4b91906149c4565b90505b8351811015613db957838181518110613d6957613d69614849565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613db157506000979650505050505050565b600101613d4e565b5050600101613d15565b50846020015161ffff168310158015613de45750846040015161ffff168210155b95945050505050565b60008151808452602080850194506020840160005b83811015613e3457815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613e02565b509495945050505050565b602081526000611dee6020830184613ded565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613ea457613ea4613e52565b60405290565b6040516060810167ffffffffffffffff81118282101715613ea457613ea4613e52565b6040516080810167ffffffffffffffff81118282101715613ea457613ea4613e52565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613f3757613f37613e52565b604052919050565b600067ffffffffffffffff821115613f5957613f59613e52565b5060051b60200190565b80357fffffffffffffffffffffffffffffffff00000000000000000000000000000000811681146105ac57600080fd5b600060408284031215613fa557600080fd5b613fad613e81565b9050613fb882613f63565b8152602082013563ffffffff1981168114613fd257600080fd5b602082015292915050565b60006020808385031215613ff057600080fd5b823567ffffffffffffffff81111561400757600080fd5b8301601f8101851361401857600080fd5b803561402b61402682613f3f565b613ef0565b8082825260208201915060208360061b85010192508783111561404d57600080fd5b6020840193505b82841015614078576140668885613f93565b82528482019150604084019350614054565b979650505050505050565b60006020808352835180602085015260005b818110156140b157858101830151858201604001528201614095565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60006020828403121561410257600080fd5b611dee82613f63565b803573ffffffffffffffffffffffffffffffffffffffff811681146105ac57600080fd5b600082601f83011261414057600080fd5b8135602061415061402683613f3f565b8083825260208201915060208460051b87010193508684111561417257600080fd5b602086015b84811015614195576141888161410b565b8352918301918301614177565b509695505050505050565b600080604083850312156141b357600080fd5b823567ffffffffffffffff808211156141cb57600080fd5b6141d78683870161412f565b935060208501359150808211156141ed57600080fd5b506141fa8582860161412f565b9150509250929050565b8051606080845281518482018190526000926080916020918201918388019190865b82811015614280578451805173ffffffffffffffffffffffffffffffffffffffff908116865283820151168386015260408082015160ff908116918701919091529088015116878501529381019392850192600101614226565b508781015161ffff81168a83015295505050604086015193506142a9604088018561ffff169052565b9695505050505050565b600063ffffffff808616835280851660208401525060606040830152613de46060830184614204565b803560ff811681146105ac57600080fd5b803561ffff811681146105ac57600080fd5b6000602080838503121561431257600080fd5b823567ffffffffffffffff8082111561432a57600080fd5b8185019150606080838803121561434057600080fd5b614348613eaa565b83358381111561435757600080fd5b84019250601f8301881361436a57600080fd5b823561437861402682613f3f565b81815260079190911b8401860190868101908a83111561439757600080fd5b948701945b82861015614409576080868c0312156143b55760008081fd5b6143bd613ecd565b6143c68761410b565b81526143d389880161410b565b8982015260406143e48189016142dc565b908201526143f38787016142dc565b818701528252608095909501949087019061439c565b83525061441990508486016142ed565b85820152614429604085016142ed565b6040820152979650505050505050565b60006040828403121561444b57600080fd5b50919050565b6000806040838503121561446457600080fd5b61446d83613f63565b915060208084013567ffffffffffffffff81111561448a57600080fd5b8401601f8101861361449b57600080fd5b80356144a961402682613f3f565b81815260059190911b820183019083810190888311156144c857600080fd5b928401925b828410156144ed576144de84613f63565b825292840192908401906144cd565b80955050505050509250929050565b6000602080838503121561450f57600080fd5b823567ffffffffffffffff81111561452657600080fd5b8301601f8101851361453757600080fd5b803561454561402682613f3f565b81815260079190911b8201830190838101908783111561456457600080fd5b928401925b8284101561407857608084890312156145825760008081fd5b61458a613eaa565b6145938561410b565b81526145a189878701613f93565b86820152606085013580151581146145b95760008081fd5b604082015282526080939093019290840190614569565b600080602083850312156145e357600080fd5b823567ffffffffffffffff808211156145fb57600080fd5b818501915085601f83011261460f57600080fd5b81358181111561461e57600080fd5b8660208260061b850101111561463357600080fd5b60209290920196919550909350505050565b6080815260006146586080830187613ded565b82810360208481019190915286518083528782019282019060005b8181101561469657845163ffffffff191683529383019391830191600101614673565b505061ffff96909616604085015250505090151560609091015292915050565b600080604083850312156146c957600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208082528251828201819052600091906040908185019086840185805b838110156147f2578251805160058110614766577f4e487b710000000000000000000000000000000000000000000000000000000084526021600452602484fd5b86528088015167ffffffffffffffff16888701528681015115158787015260608082015173ffffffffffffffffffffffffffffffffffffffff16908701526080808201517fffffffffffffffffffffffffffffffff000000000000000000000000000000009081169188019190915260a091820151169086015260c09094019391860191600101614725565b509298975050505050505050565b60006020828403121561481257600080fd5b611dee8261410b565b60608152600061482e6060830186613ded565b61ffff94909416602083015250901515604090910152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6000604082840312156148b957600080fd5b6148c1613e81565b6148ca8361410b565b8152602083013560208201528091505092915050565b815173ffffffffffffffffffffffffffffffffffffffff16815260208083015190820152604081016105a6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61ffff818116838216019080821115613a4f57613a4f61490d565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036149885761498861490d565b5060010190565b60008161499e5761499e61490d565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b808201808211156105a6576105a661490d565b818103818111156105a6576105a661490d565b600060ff821660ff8103614a0057614a0061490d565b60010192915050565b61ffff828116828216039080821115613a4f57613a4f61490d565b600067ffffffffffffffff821680614a3e57614a3e61490d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600063ffffffff808316818103614aae57614aae61490d565b6001019392505050565b602081526000611dee6020830184614204565b600067ffffffffffffffff808316818103614aae57614aae61490d565b78ffffffffffffffffffffffffffffffffffffffffffffffffff828116828216039080821115613a4f57613a4f61490d565b80820281158282048414176105a6576105a661490d56fea164736f6c6343000818000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000700000000000000000000000023ccf5a7309a9ba850f877313cff35b6903609440000000000000000000000000b59fa90337b8c1dfcf83a60be93df36d3022bf200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000eaa2691fe9c8cef93ccbc1b4b1e4f3ce026789420000000000000000000000000cb702a32e380e6bbe578d73928db35f27dfd0d100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f5d5840ce35ed1e408b26df1f5eb74d6641dfae600000000000000000000000038ea6cea45d30f9a4ba1b7fa28ce840135fe3118000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000009f199d8a106a220d483bd548ef862b15ecd3bfac0000000000000000000000001dca94f408bc850524a320988721642d64870b62000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000008749f722d74b2a8d9af5e4f8011287da3dc058a1000000000000000000000000699e53aba4543726e487771def1781c89dbd30cf000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000bc0fb2faa891d3c48e494bffd3b0bcd53b99ce500000000000000000000000012119a85235939c6d28182f198add16e9c1d7b1100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000d6c690713dc1b3995c200e600d3a00b30299ae08000000000000000000000000c5f450a270dcefdcb990851a280a8a2a3d9403df00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : config (tuple):
Arg [1] : voters (tuple[]):
Arg [1] : blessVoteAddr (address): 0x23ccf5a7309A9bA850F877313CFF35B690360944
Arg [2] : curseVoteAddr (address): 0x0B59Fa90337B8c1DfcF83A60be93Df36d3022bf2
Arg [3] : blessWeight (uint8): 1
Arg [4] : curseWeight (uint8): 1
,
Arg [1] : blessVoteAddr (address): 0xeAA2691fE9C8CEF93CcBc1b4B1E4F3ce02678942
Arg [2] : curseVoteAddr (address): 0x0cb702A32e380e6bBE578d73928db35F27Dfd0d1
Arg [3] : blessWeight (uint8): 1
Arg [4] : curseWeight (uint8): 1
,
Arg [1] : blessVoteAddr (address): 0xF5d5840ce35ED1E408B26df1f5Eb74D6641DfAe6
Arg [2] : curseVoteAddr (address): 0x38eA6cEa45D30F9a4Ba1B7fa28CE840135Fe3118
Arg [3] : blessWeight (uint8): 1
Arg [4] : curseWeight (uint8): 1
,
Arg [1] : blessVoteAddr (address): 0x9F199d8A106a220D483BD548Ef862b15eCd3BFAc
Arg [2] : curseVoteAddr (address): 0x1DCA94f408BC850524a320988721642D64870B62
Arg [3] : blessWeight (uint8): 1
Arg [4] : curseWeight (uint8): 1
,
Arg [1] : blessVoteAddr (address): 0x8749F722d74b2a8d9AF5e4F8011287DA3DC058a1
Arg [2] : curseVoteAddr (address): 0x699E53aba4543726E487771def1781C89Dbd30Cf
Arg [3] : blessWeight (uint8): 1
Arg [4] : curseWeight (uint8): 1
,
Arg [1] : blessVoteAddr (address): 0x0bc0fb2faa891D3C48e494BfFd3B0BCD53B99cE5
Arg [2] : curseVoteAddr (address): 0x12119A85235939C6d28182f198AdD16e9C1d7B11
Arg [3] : blessWeight (uint8): 1
Arg [4] : curseWeight (uint8): 1
,
Arg [1] : blessVoteAddr (address): 0xd6c690713DC1B3995C200E600D3A00b30299Ae08
Arg [2] : curseVoteAddr (address): 0xC5f450a270DceFdcb990851A280a8A2A3d9403Df
Arg [3] : blessWeight (uint8): 1
Arg [4] : curseWeight (uint8): 1
Arg [2] : blessWeightThreshold (uint16): 2
Arg [3] : curseWeightThreshold (uint16): 2
-----Encoded View---------------
33 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [5] : 00000000000000000000000023ccf5a7309a9ba850f877313cff35b690360944
Arg [6] : 0000000000000000000000000b59fa90337b8c1dfcf83a60be93df36d3022bf2
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [9] : 000000000000000000000000eaa2691fe9c8cef93ccbc1b4b1e4f3ce02678942
Arg [10] : 0000000000000000000000000cb702a32e380e6bbe578d73928db35f27dfd0d1
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [13] : 000000000000000000000000f5d5840ce35ed1e408b26df1f5eb74d6641dfae6
Arg [14] : 00000000000000000000000038ea6cea45d30f9a4ba1b7fa28ce840135fe3118
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [16] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [17] : 0000000000000000000000009f199d8a106a220d483bd548ef862b15ecd3bfac
Arg [18] : 0000000000000000000000001dca94f408bc850524a320988721642d64870b62
Arg [19] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [20] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [21] : 0000000000000000000000008749f722d74b2a8d9af5e4f8011287da3dc058a1
Arg [22] : 000000000000000000000000699e53aba4543726e487771def1781c89dbd30cf
Arg [23] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [24] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [25] : 0000000000000000000000000bc0fb2faa891d3c48e494bffd3b0bcd53b99ce5
Arg [26] : 00000000000000000000000012119a85235939c6d28182f198add16e9c1d7b11
Arg [27] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [28] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [29] : 000000000000000000000000d6c690713dc1b3995c200e600d3a00b30299ae08
Arg [30] : 000000000000000000000000c5f450a270dcefdcb990851a280a8a2a3d9403df
Arg [31] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [32] : 0000000000000000000000000000000000000000000000000000000000000001
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.