Source Code
Overview
S Balance
More Info
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Loading...
Loading
Contract Name:
Assessment
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.18; import "@openzeppelin/contracts-v4/utils/cryptography/MerkleProof.sol"; import "../../abstract/MasterAwareV2.sol"; import "../../interfaces/IAssessment.sol"; import "../../interfaces/IMemberRoles.sol"; import "../../interfaces/ISAFURAToken.sol"; import "../../interfaces/ITokenController.sol"; import "../../interfaces/IRamm.sol"; import "../../libraries/Math.sol"; import "../../libraries/SafeUintCast.sol"; /// Provides the assessment mechanism for members to decide the outcome of the events that can lead /// to payouts. Mints rewards for stakers that act benevolently and allows burning fraudulent ones. contract Assessment is IAssessment, MasterAwareV2 { ISAFURAToken public immutable nxm; /* ========== STATE VARIABLES ========== */ // Parameters configurable through governance. Configuration public override config; // Stake states of users. (See Stake struct) mapping(address => Stake) public override stakeOf; // Votes of users. (See Vote struct) mapping(address => Vote[]) public override votesOf; // Mapping used to determine if a user has already voted mapping(address => mapping(uint => bool)) public override hasAlreadyVotedOn; // An array of merkle tree roots used to indicate fraudulent assessors. Each root represents a // fraud attempt by one or multiple addresses. Once the root is submitted by adivsory board // members through governance, burnFraud uses this root to burn the fraudulent assessors' stakes // and correct the outcome of the poll. bytes32[] public fraudResolution; Assessment[] public override assessments; /* ========== CONSTRUCTOR ========== */ constructor(address nxmAddress) { nxm = ISAFURAToken(nxmAddress); } /* ========== VIEWS ========== */ /// @dev Returns the vote count of an assessor. /// /// @param assessor The address of the assessor. function getVoteCountOfAssessor(address assessor) external override view returns (uint) { return votesOf[assessor].length; } /// @dev Returns the number of assessments. function getAssessmentsCount() external override view returns (uint) { return assessments.length; } /// @dev Returns only the poll from the assessment struct to make only one SLOAD. Is used by /// other contracts. /// /// @param assessmentId The index of the assessment function getPoll(uint assessmentId) external override view returns (Poll memory) { return assessments[assessmentId].poll; } /// Returns all pending rewards, the withdrawable amount and the index until which they can be /// withdrawn. /// /// @param staker The address of the staker function getRewards(address staker) external override view returns ( uint totalPendingAmountInNXM, uint withdrawableAmountInNXM, uint withdrawableUntilIndex ) { uint104 rewardsWithdrawableFromIndex = stakeOf[staker].rewardsWithdrawableFromIndex; Vote memory vote; Assessment memory assessment; uint voteCount = votesOf[staker].length; bool hasReachedUnwithdrawableReward = false; for (uint i = rewardsWithdrawableFromIndex; i < voteCount; i++) { vote = votesOf[staker][i]; assessment = assessments[vote.assessmentId]; // If hasReachedUnwithdrawableReward is true, skip and continue calculating the pending total // rewards. if ( !hasReachedUnwithdrawableReward && uint(assessment.poll.end) + uint(config.payoutCooldownInDays) * 1 days >= block.timestamp ) { hasReachedUnwithdrawableReward = true; // Store the index of the vote until which rewards can be withdrawn. withdrawableUntilIndex = i; // Then, also store the pending total value that can be withdrawn until this index. withdrawableAmountInNXM = totalPendingAmountInNXM; } totalPendingAmountInNXM += uint(assessment.totalRewardInNXM) * uint(vote.stakedAmount) / (uint(assessment.poll.accepted) + uint(assessment.poll.denied)); } if (!hasReachedUnwithdrawableReward) { withdrawableUntilIndex = voteCount; withdrawableAmountInNXM = totalPendingAmountInNXM; } } /* === MUTATIVE FUNCTIONS ==== */ /// Increases the sender's stake by the specified amount and transfers NXM to this contract /// /// @param amount The amount of nxm to stake function stake(uint96 amount) public whenNotPaused { // only owner, advisory board, auditor can stake require( IMemberRoles(internalContracts[uint(ID.MR)]).checkRole(msg.sender, uint(IMemberRoles.Role.Owner)) || IMemberRoles(internalContracts[uint(ID.MR)]).checkRole(msg.sender, uint(IMemberRoles.Role.AdvisoryBoard)) || IMemberRoles(internalContracts[uint(ID.MR)]).checkRole(msg.sender, uint(IMemberRoles.Role.Auditor)), "Only owner, advisory board, auditor can stake"); stakeOf[msg.sender].amount += amount; ITokenController(getInternalContractAddress(ID.TC)) .operatorTransfer(msg.sender, address(this), amount); emit StakeDeposited(msg.sender, amount); } /// Withdraws a portion or all of the user's stake /// /// @dev At least stakeLockupPeriodInDays must have passed since the last vote. /// /// @param amount The amount of nxm to unstake /// @param to The member address where the NXM is transfered to. Useful for switching /// membership during stake lockup period and thus allowing the user to withdraw /// their staked amount to the new address when possible. function unstake(uint96 amount, address to) external whenNotPaused override { // Restrict unstaking to a different account if still locked for member vote if (block.timestamp < nxm.isLockedForMV(msg.sender)) { require(to == msg.sender, "Assessment: NXM is locked for voting in governance"); } uint voteCount = votesOf[msg.sender].length; if (voteCount > 0) { Vote memory vote = votesOf[msg.sender][voteCount - 1]; require( block.timestamp > vote.timestamp + uint(config.stakeLockupPeriodInDays) * 1 days, "Stake is in lockup period" ); } stakeOf[msg.sender].amount -= amount; nxm.transfer(to, amount); emit StakeWithdrawn(msg.sender, to, amount); } /// Withdraws a staker's accumulated rewards to a destination address but only the staker can /// call this. /// /// @dev Only withdraws until the last finalized poll. /// /// @param staker The address of the staker for which the rewards are withdrawn /// @param batchSize The index until which (but not including) the rewards should be withdrawn. /// Used if a large number of assessments accumulates and the function doesn't /// fit in one block, thus requiring multiple batched transactions. function withdrawRewards( address staker, uint104 batchSize ) external override whenNotPaused returns (uint withdrawn, uint withdrawnUntilIndex) { return _withdrawRewards(staker, staker, batchSize); } /// Withdraws a staker's accumulated rewards. /// /// @dev Only withdraws until the last finalized poll. /// /// @param destination The destination address where the rewards will be withdrawn. /// @param batchSize The index until which (but not including) the rewards should be withdrawn. /// Used if a large number of assessments accumulates and the function doesn't /// fit in one block, thus requiring multiple batched transactions. function withdrawRewardsTo( address destination, uint104 batchSize ) external override whenNotPaused returns (uint withdrawn, uint withdrawnUntilIndex) { return _withdrawRewards(msg.sender, destination, batchSize); } function _withdrawRewards( address staker, address destination, uint104 batchSize ) internal returns (uint withdrawn, uint withdrawnUntilIndex) { require( IMemberRoles(internalContracts[uint(ID.MR)]).checkRole( destination, uint(IMemberRoles.Role.Member) ), "Destination address is not a member" ); // This is the index until which (but not including) the previous withdrawal was processed. // The current withdrawal starts from this index. uint104 rewardsWithdrawableFromIndex = stakeOf[staker].rewardsWithdrawableFromIndex; { uint voteCount = votesOf[staker].length; require(rewardsWithdrawableFromIndex < voteCount, "No withdrawable rewards"); // If batchSize is a non-zero value, it means the withdrawal is going to be batched in // multiple transactions. withdrawnUntilIndex = batchSize > 0 ? rewardsWithdrawableFromIndex + batchSize : voteCount; } Vote memory vote; Assessment memory assessment; for (uint i = rewardsWithdrawableFromIndex; i < withdrawnUntilIndex; i++) { vote = votesOf[staker][i]; assessment = assessments[vote.assessmentId]; if (uint(assessment.poll.end) + uint(config.payoutCooldownInDays) * 1 days >= block.timestamp) { // Poll is not final withdrawnUntilIndex = i; break; } withdrawn += uint(assessment.totalRewardInNXM) * uint(vote.stakedAmount) / (uint(assessment.poll.accepted) + uint(assessment.poll.denied)); } // This is the index where the next withdrawReward call will start iterating from stakeOf[staker].rewardsWithdrawableFromIndex = SafeUintCast.toUint104(withdrawnUntilIndex); ITokenController(getInternalContractAddress(ID.TC)).mint(destination, withdrawn); emit RewardWithdrawn(staker, destination, withdrawn); } /// Creates a new assessment /// /// @dev Is used only by contracts acting as redemption methods for cover product types. /// /// @param totalAssessmentReward The total reward that is shared among the stakers participating /// the assessment. /// @param assessmentDepositInETH The deposit that covers assessment rewards in case it's denied. /// If the assessment verdict is positive, the contract that relies /// on it can send back the deposit at payout. function startAssessment( uint totalAssessmentReward, uint assessmentDepositInETH ) external override onlyInternal returns (uint) { assessments.push(Assessment( Poll( 0, // accepted 0, // denied uint32(block.timestamp), // start uint32(block.timestamp + uint32(config.minVotingPeriodInDays) * 1 days) // end ), uint128(totalAssessmentReward), uint128(assessmentDepositInETH) )); return assessments.length - 1; } /// Casts multiple votes on assessments and optionally allows to increase the stake in the same /// transaction. /// /// @dev See stake and castVote functions. /// /// @param assessmentIds Array of assessment indexes for which the votes are cast. /// @param votes Array of votes corresponding to each assessment id from the /// assessmentIds param. Elements that are false represent a deny vote and /// those that are true represent an accept vote. /// @param stakeIncrease When a non-zero value is given, this function will also increase the /// stake in the same transaction. function castVotes( uint[] calldata assessmentIds, bool[] calldata votes, string[] calldata ipfsAssessmentDataHashes, uint96 stakeIncrease ) external override onlyMember whenNotPaused { require( assessmentIds.length == votes.length, "The lengths of the assessment ids and votes arrays mismatch" ); require( assessmentIds.length == ipfsAssessmentDataHashes.length, "The lengths of the assessment ids and ipfs assessment data hashes arrays mismatch" ); if (stakeIncrease > 0) { stake(stakeIncrease); } for (uint i = 0; i < assessmentIds.length; i++) { castVote(assessmentIds[i], votes[i], ipfsAssessmentDataHashes[i]); } } /// Casts a vote on an assessment /// /// @dev Resets the poll's end date on the first vote. The first vote can only be an accept vote. /// If no votes are cast during minVotingPeriodInDays it is automatically considered denied. When /// the poll ends in less than silentEndingPeriodInDays, the end date is extended with a potion of /// silentEndingPeriodInDays proportional to the user's stake compared to the /// total stake on that assessment, namely the sum of tokens used for both accept and deny votes, /// but no greater than silentEndingPeriodInDays. /// /// @param assessmentId The index of the assessment for which the vote is cast /// @param isAcceptVote True to accept, false to deny function castVote(uint assessmentId, bool isAcceptVote, string memory ipfsAssessmentDataHash) internal { { require(!hasAlreadyVotedOn[msg.sender][assessmentId], "Already voted"); hasAlreadyVotedOn[msg.sender][assessmentId] = true; } uint96 stakeAmount = stakeOf[msg.sender].amount; require(stakeAmount > 0, "A stake is required to cast votes"); Poll memory poll = assessments[assessmentId].poll; require(block.timestamp < poll.end, "Voting is closed"); require( poll.accepted > 0 || isAcceptVote, "At least one accept vote is required to vote deny" ); if (poll.accepted == 0) { // Reset the poll end date on the first accept vote poll.end = uint32(block.timestamp + uint(config.minVotingPeriodInDays) * 1 days); } // Check if poll ends in less than 24 hours uint silentEndingPeriod = uint(config.silentEndingPeriodInDays) * 1 days; if (poll.end - block.timestamp < silentEndingPeriod) { // Extend proportionally to the user's stake but up to 1 day maximum poll.end += uint32( Math.min( silentEndingPeriod, silentEndingPeriod * uint(stakeAmount) / (uint(poll.accepted + poll.denied)) ) ); } if (isAcceptVote) { poll.accepted += stakeAmount; } else { poll.denied += stakeAmount; } assessments[assessmentId].poll = poll; votesOf[msg.sender].push(Vote( uint80(assessmentId), isAcceptVote, uint32(block.timestamp), stakeAmount )); emit VoteCast(msg.sender, assessmentId, stakeAmount, isAcceptVote, ipfsAssessmentDataHash); } /// Allows governance to submit a merkle tree root hash representing fraudulent stakers /// /// @dev Leaves' inputs are the sequence of bytes obtained by concatenating: /// - Staker address (20 bytes or 160 bits) /// - The index of the last fraudulent vote (32 bytes or 256 bits) /// - Amount of stake to be burned (12 bytes or 96 bits) /// - The number of previous fraud attempts (2 bytes or 16 bits) /// /// @param root The merkle tree root hash function submitFraud(bytes32 root) external override onlyGovernance { fraudResolution.push(root); emit FraudSubmitted(root); } /// Allows anyone to undo fraudulent votes and burn the fraudulent assessors present in the /// merkle tree whose hash is submitted through submitFraud /// /// @param rootIndex The index of the merkle tree root hash stored in /// fraudResolution. /// @param proof The path from the leaf to the root. /// @param assessor The address of the fraudulent assessor. /// @param lastFraudulentVoteIndex The index of the last fraudulent vote cast by the assessor. /// @param burnAmount The amount of stake that needs to be burned. /// @param fraudCount The number of times the assessor has taken part in fraudulent /// voting. /// @param voteBatchSize The number of iterations that prevents an unbounded loop and /// allows chunked processing. Can also be 0 if chunking is not /// necessary. function processFraud( uint256 rootIndex, bytes32[] calldata proof, address assessor, uint256 lastFraudulentVoteIndex, uint96 burnAmount, uint16 fraudCount, uint256 voteBatchSize ) external override whenNotPaused { require( MerkleProof.verify( proof, fraudResolution[rootIndex], keccak256(abi.encodePacked(assessor, lastFraudulentVoteIndex, burnAmount, fraudCount)) ), "Invalid merkle proof" ); Stake memory _stake = stakeOf[assessor]; // Make sure we don't burn beyond lastFraudulentVoteIndex uint processUntil = _stake.rewardsWithdrawableFromIndex + voteBatchSize; if (processUntil >= lastFraudulentVoteIndex) { processUntil = lastFraudulentVoteIndex + 1; } for (uint j = _stake.rewardsWithdrawableFromIndex; j < processUntil; j++) { IAssessment.Vote memory vote = votesOf[assessor][j]; IAssessment.Poll memory poll = assessments[vote.assessmentId].poll; { if (uint32(block.timestamp) >= uint(poll.end) + uint(config.payoutCooldownInDays) * 1 days) { // Once the cooldown period ends the poll result is final, thus skip continue; } } if (vote.accepted) { poll.accepted -= vote.stakedAmount; } else { poll.denied -= vote.stakedAmount; } // If the poll ends in less than 24h, extend it to 24h uint32 nextDay = uint32(block.timestamp + 1 days); if (poll.end < nextDay) { poll.end = nextDay; } emit FraudProcessed(vote.assessmentId, assessor, poll); assessments[vote.assessmentId].poll = poll; } // Burns an assessor only once for each merkle tree root, no matter how many times this function // runs on the same account. When a transaction is too big to fit in one block, it is batched // in multiple transactions according to voteBatchSize. After burning the tokens, fraudCount // is incremented. If another merkle root is submitted that contains the same addres, the leaf // should use the updated fraudCount stored in the Stake struct as input. if (fraudCount == _stake.fraudCount) { // Make sure this doesn't revert if the stake amount is already subtracted due to a previous // burn from a different merkle tree. burnAmount = burnAmount > _stake.amount ? _stake.amount : burnAmount; _stake.amount -= burnAmount; _stake.fraudCount++; // TODO: consider burning the tokens in the token controller contract ramm().updateTwap(); nxm.burn(burnAmount); } if (uint104(processUntil) > _stake.rewardsWithdrawableFromIndex) { _stake.rewardsWithdrawableFromIndex = uint104(processUntil); } stakeOf[assessor] = _stake; } /// Updates configurable parameters through governance /// /// @param paramNames An array of elements from UintParams enum /// @param values An array of the new values, each one corresponding to the parameter /// from paramNames on the same position. function updateUintParameters( UintParams[] calldata paramNames, uint[] calldata values ) external override onlyGovernance { Configuration memory newConfig = config; for (uint i = 0; i < paramNames.length; i++) { if (paramNames[i] == IAssessment.UintParams.minVotingPeriodInDays) { newConfig.minVotingPeriodInDays = uint8(values[i]); continue; } if (paramNames[i] == IAssessment.UintParams.stakeLockupPeriodInDays) { newConfig.stakeLockupPeriodInDays = uint8(values[i]); continue; } if (paramNames[i] == IAssessment.UintParams.payoutCooldownInDays) { newConfig.payoutCooldownInDays = uint8(values[i]); continue; } if (paramNames[i] == IAssessment.UintParams.silentEndingPeriodInDays) { newConfig.silentEndingPeriodInDays = uint8(values[i]); continue; } } config = newConfig; } /// @dev Updates internal contract addresses to the ones stored in master. This function is /// automatically called by the master contract when a contract is added or upgraded. function changeDependentContractAddress() external override { internalContracts[uint(ID.TC)] = master.getLatestAddress("TC"); internalContracts[uint(ID.MR)] = master.getLatestAddress("MR"); internalContracts[uint(ID.RA)] = master.getLatestAddress("RA"); Configuration memory currentConfig = config; bool notInitialized = bytes32( abi.encodePacked( currentConfig.minVotingPeriodInDays, currentConfig.payoutCooldownInDays, currentConfig.stakeLockupPeriodInDays, currentConfig.silentEndingPeriodInDays ) ) == bytes32(0); if (notInitialized) { // initialize config config.minVotingPeriodInDays = 3; // days config.payoutCooldownInDays = 1; // days config.stakeLockupPeriodInDays = 14; // days config.silentEndingPeriodInDays = 1; // days // whitelist current contract ITokenController(getInternalContractAddress(ID.TC)).addToWhitelist(address(this)); } } function ramm() internal view returns (IRamm) { return IRamm(internalContracts[uint(ID.RA)]); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The proofs can be generated using the JavaScript library * https://github.com/miguelmota/merkletreejs[merkletreejs]. * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled. * * See `test/utils/cryptography/MerkleProof.test.js` for some examples. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify( bytes32[] memory proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Calldata version of {verify} * * _Available since v4.7._ */ function verifyCalldata( bytes32[] calldata proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} * * _Available since v4.7._ */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be proved to be a part of a Merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * _Available since v4.7._ */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * _Available since v4.7._ */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and the sibling nodes in `proof`, * consuming from one or the other at each step according to the instructions given by * `proofFlags`. * * _Available since v4.7._ */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof} * * _Available since v4.7._ */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.18; import "../interfaces/ISAFURAMaster.sol"; import "../interfaces/IMasterAwareV2.sol"; import "../interfaces/IMemberRoles.sol"; abstract contract MasterAwareV2 is IMasterAwareV2 { ISAFURAMaster public master; mapping(uint => address payable) public internalContracts; modifier onlyMember { require( IMemberRoles(internalContracts[uint(ID.MR)]).checkRole( msg.sender, uint(IMemberRoles.Role.Member) ), "Caller is not a member" ); _; } modifier onlyAdvisoryBoard { require( IMemberRoles(internalContracts[uint(ID.MR)]).checkRole( msg.sender, uint(IMemberRoles.Role.AdvisoryBoard) ), "Caller is not an advisory board member" ); _; } modifier onlyInternal { require(master.isInternal(msg.sender), "Caller is not an internal contract"); _; } modifier onlyMaster { if (address(master) != address(0)) { require(address(master) == msg.sender, "Not master"); } _; } modifier onlyGovernance { require( master.checkIsAuthToGoverned(msg.sender), "Caller is not authorized to govern" ); _; } modifier onlyEmergencyAdmin { require( msg.sender == master.emergencyAdmin(), "Caller is not emergency admin" ); _; } modifier whenPaused { require(master.isPause(), "System is not paused"); _; } modifier whenNotPaused { require(!master.isPause(), "System is paused"); _; } function getInternalContractAddress(ID id) internal view returns (address payable) { return internalContracts[uint(id)]; } function changeMasterAddress(address masterAddress) public onlyMaster { master = ISAFURAMaster(masterAddress); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface IAssessment { /* ========== DATA STRUCTURES ========== */ enum UintParams { minVotingPeriodInDays, stakeLockupPeriodInDays, payoutCooldownInDays, silentEndingPeriodInDays } struct Configuration { // The minimum number of days the users can vote on polls uint8 minVotingPeriodInDays; // Number of days the users must wait from their last vote to withdraw their stake. uint8 stakeLockupPeriodInDays; // Number of days the users must wait after a poll closes to redeem payouts. uint8 payoutCooldownInDays; // Number of days representing the silence period. It is used to extend a poll's end date when // a vote is cast during the silence period before the end date. uint8 silentEndingPeriodInDays; } struct Stake { uint96 amount; uint104 rewardsWithdrawableFromIndex; uint16 fraudCount; /*uint32 unused,*/ } // Holds data for a vote belonging to an assessor. // // The structure is used to keep track of user's votes. Each vote is used to determine // a user's share of rewards or to create a fraud resolution which excludes fraudulent votes // from the initial poll. struct Vote { // Identifier of the claim or incident uint80 assessmentId; // If the assessor votes to accept the event it's true otherwise it's false bool accepted; // Date and time when the vote was cast uint32 timestamp; // How many tokens were staked when the vote was cast uint96 stakedAmount; } // Holds poll results for an assessment. // // The structure is used to keep track of all votes on a given assessment such as how many NXM were // used to cast accept and deny votes as well as when the poll started and when it ends. struct Poll { // The amount of NXM from accept votes uint96 accepted; // The amount of NXM from deny votes uint96 denied; // Timestamp of when the poll started. uint32 start; // Timestamp of when the poll ends. uint32 end; } // Holds data for an assessment belonging to an assessable event (individual claims, yield token // incidents etc.). // // The structure is used to keep track of the total reward that should be distributed to // assessors, the assessment deposit the claimants made to start the assessment, and the poll // coresponding to this assessment. struct Assessment { // See Poll struct Poll poll; // The amount of NXM representing the assessment reward which is split among those who voted. uint128 totalRewardInNXM; // An amount of ETH which is sent back to the claimant when the poll result is positive, // otherwise it is kep it the pool to back the assessment rewards. This allows claimants to // open an unlimited amount of claims and prevents unbacked NXM to be minted through the // assessment process. uint128 assessmentDepositInETH; } /* ========== VIEWS ========== */ function getAssessmentsCount() external view returns (uint); function assessments(uint id) external view returns (Poll memory poll, uint128 totalReward, uint128 assessmentDeposit); function getPoll(uint assessmentId) external view returns (Poll memory); function getRewards(address user) external view returns ( uint totalPendingAmount, uint withdrawableAmount, uint withdrawableUntilIndex ); function getVoteCountOfAssessor(address assessor) external view returns (uint); function votesOf(address user, uint id) external view returns (uint80 assessmentId, bool accepted, uint32 timestamp, uint96 stakedAmount); function stakeOf(address user) external view returns (uint96 amount, uint104 rewardsWithdrawableFromIndex, uint16 fraudCount); function config() external view returns ( uint8 minVotingPeriodInDays, uint8 stakeLockupPeriodInDays, uint8 payoutCooldownInDays, uint8 silentEndingPeriodInDays ); function hasAlreadyVotedOn(address voter, uint pollId) external view returns (bool); /* === MUTATIVE FUNCTIONS ==== */ function stake(uint96 amount) external; function unstake(uint96 amount, address to) external; function withdrawRewards( address user, uint104 batchSize ) external returns (uint withdrawn, uint withdrawnUntilIndex); function withdrawRewardsTo( address destination, uint104 batchSize ) external returns (uint withdrawn, uint withdrawnUntilIndex); function startAssessment(uint totalReward, uint assessmentDeposit) external returns (uint); function castVotes( uint[] calldata assessmentIds, bool[] calldata votes, string[] calldata ipfsAssessmentDataHashes, uint96 stakeIncrease ) external; function submitFraud(bytes32 root) external; function processFraud( uint256 rootIndex, bytes32[] calldata proof, address assessor, uint256 lastFraudulentVoteIndex, uint96 burnAmount, uint16 fraudCount, uint256 voteBatchSize ) external; function updateUintParameters(UintParams[] calldata paramNames, uint[] calldata values) external; /* ========== EVENTS ========== */ event StakeDeposited(address user, uint104 amount); event StakeWithdrawn(address indexed user, address to, uint96 amount); event VoteCast(address indexed user, uint256 assessmentId, uint96 stakedAmount, bool accepted, string ipfsAssessmentDataHash); event RewardWithdrawn(address user, address to, uint256 amount); event FraudProcessed(uint assessmentId, address assessor, Poll poll); event FraudSubmitted(bytes32 root); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface IMasterAwareV2 { // TODO: if you update this enum, update lib/constants.js as well enum ID { TC, // TokenController.sol P1, // Pool.sol MR, // MemberRoles.sol MC, // MCR.sol CO, // Cover.sol SP, // StakingProducts.sol PS, // LegacyPooledStaking.sol GV, // Governance.sol GW, // LegacyGateway.sol - removed CL, // CoverMigrator.sol - removed AS, // Assessment.sol CI, // IndividualClaims.sol - Claims for Individuals CG, // YieldTokenIncidents.sol - Claims for Groups RA, // Ramm.sol ST, // SafeTracker.sol CP // CoverProducts.sol } function changeMasterAddress(address masterAddress) external; function changeDependentContractAddress() external; function internalContracts(uint) external view returns (address payable); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface IMemberRoles { enum Role {Unassigned, AdvisoryBoard, Member, Owner, Auditor} function join(address _userAddress, uint nonce, bytes calldata signature) external payable; function switchMembership(address _newAddress) external; function switchMembershipAndAssets( address newAddress, uint[] calldata coverIds, uint[] calldata stakingTokenIds ) external; function switchMembershipOf(address member, address _newAddress) external; function totalRoles() external view returns (uint256); function changeAuthorized(uint _roleId, address _newAuthorized) external; function setKycAuthAddress(address _add) external; function members(uint _memberRoleId) external view returns (uint, address[] memory memberArray); function numberOfMembers(uint _memberRoleId) external view returns (uint); function authorized(uint _memberRoleId) external view returns (address); function roles(address _memberAddress) external view returns (uint[] memory); function checkRole(address _memberAddress, uint _roleId) external view returns (bool); function getMemberLengthForAllRoles() external view returns (uint[] memory totalMembers); function memberAtIndex(uint _memberRoleId, uint index) external view returns (address, bool); function membersLength(uint _memberRoleId) external view returns (uint); event MemberRole(uint256 indexed roleId, bytes32 roleName, string roleDescription); event MemberJoined(address indexed newMember, uint indexed nonce); event switchedMembership(address indexed previousMember, address indexed newMember, uint timeStamp); event MembershipWithdrawn(address indexed member, uint timestamp); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; import "./IPriceFeedOracle.sol"; struct SwapDetails { uint104 minAmount; uint104 maxAmount; uint32 lastSwapTime; // 2 decimals of precision. 0.01% -> 0.0001 -> 1e14 uint16 maxSlippageRatio; } struct Asset { address assetAddress; bool isCoverAsset; bool isAbandoned; } interface IPool { function swapOperator() external view returns (address); function getAsset(uint assetId) external view returns (Asset memory); function getAssets() external view returns (Asset[] memory); function transferAssetToSwapOperator(address asset, uint amount) external; function setSwapDetailsLastSwapTime(address asset, uint32 lastSwapTime) external; function getAssetSwapDetails(address assetAddress) external view returns (SwapDetails memory); function sendPayout(uint assetIndex, address payable payoutAddress, uint amount, uint ethDepositAmount) external; function sendEth(address payoutAddress, uint amount) external; function upgradeCapitalPool(address payable newPoolAddress) external; function priceFeedOracle() external view returns (IPriceFeedOracle); function getPoolValueInEth() external view returns (uint); function calculateMCRRatio(uint totalAssetValue, uint mcrEth) external pure returns (uint); function getInternalTokenPriceInAsset(uint assetId) external view returns (uint tokenPrice); function getInternalTokenPriceInAssetAndUpdateTwap(uint assetId) external returns (uint tokenPrice); function getTokenPrice() external view returns (uint tokenPrice); function getMCRRatio() external view returns (uint); function setSwapValue(uint value) external; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface Aggregator { function decimals() external view returns (uint8); function latestAnswer() external view returns (int); } interface IPriceFeedOracle { struct OracleAsset { Aggregator aggregator; uint8 decimals; } function ETH() external view returns (address); function assets(address) external view returns (Aggregator, uint8); function getAssetToEthRate(address asset) external view returns (uint); function getAssetForEth(address asset, uint ethIn) external view returns (uint); function getEthForAsset(address asset, uint amount) external view returns (uint); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; import "./IPool.sol"; import "./ISAFURAToken.sol"; import "./ITokenController.sol"; interface IRamm { // storage structs struct Slot0 { uint128 nxmReserveA; uint128 nxmReserveB; } struct Slot1 { uint128 ethReserve; uint88 budget; uint32 updatedAt; bool swapPaused; // emergency pause } struct Observation { uint32 timestamp; uint112 priceCumulativeAbove; uint112 priceCumulativeBelow; } // memory structs struct State { uint nxmA; uint nxmB; uint eth; uint budget; uint ratchetSpeedB; uint timestamp; } struct Context { uint capital; uint supply; uint mcr; } struct CumulativePriceCalculationProps { uint previousEthReserve; uint currentEthReserve; uint previousNxmA; uint currentNxmA; uint previousNxmB; uint currentNxmB; uint previousTimestamp; uint observationTimestamp; } struct CumulativePriceCalculationTimes { uint secondsUntilBVAbove; uint secondsUntilBVBelow; uint timeElapsed; uint bvTimeBelow; uint bvTimeAbove; uint ratchetTimeAbove; uint ratchetTimeBelow; } /* ========== VIEWS ========== */ function getReserves() external view returns ( uint ethReserve, uint nxmA, uint nxmB, uint remainingBudget ); function getSpotPrices() external view returns (uint spotPriceA, uint spotPriceB); function getBookValue() external view returns (uint bookValue); function getInternalPrice() external view returns (uint internalPrice); /* ==== MUTATIVE FUNCTIONS ==== */ function updateTwap() external; function getInternalPriceAndUpdateTwap() external returns (uint internalPrice); function swap(uint nxmIn, uint minAmountOut, uint deadline) external payable returns (uint amountOut); function removeBudget() external; function setEmergencySwapPause(bool _swapPaused) external; /* ========== EVENTS AND ERRORS ========== */ event EthSwappedForNxm(address indexed member, uint ethIn, uint nxmOut); event NxmSwappedForEth(address indexed member, uint nxmIn, uint ethOut); event ObservationUpdated(uint32 timestamp, uint112 priceCumulativeAbove, uint112 priceCumulativeBelow); event BudgetRemoved(); event SwapPauseConfigured(bool paused); event EthInjected(uint value); event EthExtracted(uint value); // Pause error SystemPaused(); error SwapPaused(); // Input error OneInputOnly(); error OneInputRequired(); // Expiry error SwapExpired(uint deadline, uint blockTimestamp); // Insufficient amount out error InsufficientAmountOut(uint amountOut, uint minAmountOut); // Buffer Zone error NoSwapsInBufferZone(); // ETH Transfer error EthTransferFailed(); // Circuit breakers error EthCircuitBreakerHit(); error NxmCircuitBreakerHit(); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface ISAFURAMaster { function tokenAddress() external view returns (address); function owner() external view returns (address); function emergencyAdmin() external view returns (address); function masterInitialized() external view returns (bool); function isInternal(address _add) external view returns (bool); function isPause() external view returns (bool check); function isMember(address _add) external view returns (bool); function checkIsAuthToGoverned(address _add) external view returns (bool); function getLatestAddress(bytes2 _contractName) external view returns (address payable contractAddress); function contractAddresses(bytes2 code) external view returns (address payable); function upgradeMultipleContracts( bytes2[] calldata _contractCodes, address payable[] calldata newAddresses ) external; function removeContracts(bytes2[] calldata contractCodesToRemove) external; function addNewInternalContracts( bytes2[] calldata _contractCodes, address payable[] calldata newAddresses, uint[] calldata _types ) external; function updateOwnerParameters(bytes8 code, address payable val) external; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface ISAFURAToken { function burn(uint256 amount) external returns (bool); function burnFrom(address from, uint256 value) external returns (bool); function operatorTransfer(address from, uint256 value) external returns (bool); function mint(address account, uint256 amount) external; function isLockedForMV(address member) external view returns (uint); function whiteListed(address member) external view returns (bool); function addToWhiteList(address _member) external returns (bool); function removeFromWhiteList(address _member) external returns (bool); function changeOperator(address _newOperator) external returns (bool); function lockForMemberVote(address _of, uint _days) external; /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; import "./ISAFURAToken.sol"; interface ITokenController { struct StakingPoolNXMBalances { uint128 rewards; uint128 deposits; } struct CoverInfo { uint16 claimCount; bool hasOpenClaim; bool hasAcceptedClaim; uint96 requestedPayoutAmount; // note: still 128 bits available here, can be used later } struct StakingPoolOwnershipOffer { address proposedManager; uint96 deadline; } function coverInfo(uint id) external view returns ( uint16 claimCount, bool hasOpenClaim, bool hasAcceptedClaim, uint96 requestedPayoutAmount ); function withdrawCoverNote( address _of, uint[] calldata _coverIds, uint[] calldata _indexes ) external; function changeOperator(address _newOperator) external; function operatorTransfer(address _from, address _to, uint _value) external returns (bool); function burnFrom(address _of, uint amount) external returns (bool); function addToWhitelist(address _member) external; function removeFromWhitelist(address _member) external; function mint(address _member, uint _amount) external; function lockForMemberVote(address _of, uint _days) external; function withdrawClaimAssessmentTokens(address[] calldata users) external; function getLockReasons(address _of) external view returns (bytes32[] memory reasons); function totalSupply() external view returns (uint); function totalBalanceOf(address _of) external view returns (uint amount); function totalBalanceOfWithoutDelegations(address _of) external view returns (uint amount); function getTokenPrice() external view returns (uint tokenPrice); function token() external view returns (ISAFURAToken); function getStakingPoolManager(uint poolId) external view returns (address manager); function getManagerStakingPools(address manager) external view returns (uint[] memory poolIds); function isStakingPoolManager(address member) external view returns (bool); function getStakingPoolOwnershipOffer(uint poolId) external view returns (address proposedManager, uint deadline); function transferStakingPoolsOwnership(address from, address to) external; function assignStakingPoolManager(uint poolId, address manager) external; function createStakingPoolOwnershipOffer(uint poolId, address proposedManager, uint deadline) external; function acceptStakingPoolOwnershipOffer(uint poolId) external; function cancelStakingPoolOwnershipOffer(uint poolId) external; function mintStakingPoolNXMRewards(uint amount, uint poolId) external; function burnStakingPoolNXMRewards(uint amount, uint poolId) external; function depositStakedNXM(address from, uint amount, uint poolId) external; function withdrawNXMStakeAndRewards(address to, uint stakeToWithdraw, uint rewardsToWithdraw, uint poolId) external; function burnStakedNXM(uint amount, uint poolId) external; function stakingPoolNXMBalances(uint poolId) external view returns(uint128 rewards, uint128 deposits); function tokensLocked(address _of, bytes32 _reason) external view returns (uint256 amount); function getWithdrawableCoverNotes( address coverOwner ) external view returns ( uint[] memory coverIds, bytes32[] memory lockReasons, uint withdrawableAmount ); function getPendingRewards(address member) external view returns (uint); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.18; /** * @dev Simple library that defines min, max and babylonian sqrt functions */ library Math { function min(uint a, uint b) internal pure returns (uint) { return a < b ? a : b; } function max(uint a, uint b) internal pure returns (uint) { return a > b ? a : b; } function sum(uint[] memory items) internal pure returns (uint) { uint count = items.length; uint total; for (uint i = 0; i < count; i++) { total += items[i]; } return total; } function divRound(uint a, uint b) internal pure returns (uint) { return (a + b / 2) / b; } function divCeil(uint a, uint b) internal pure returns (uint) { return (a + b - 1) / b; } function roundUp(uint a, uint b) internal pure returns (uint) { return divCeil(a, b) * b; } // babylonian method function sqrt(uint y) internal pure returns (uint) { if (y > 3) { uint z = y; uint x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } return z; } if (y != 0) { return 1; } return 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; /** * @dev Wrappers over Solidity's uintXX casting operators with added overflow * checks. * * Downcasting from uint256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeUintCast { /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { require(value < 2**248, "SafeCast: value doesn\'t fit in 248 bits"); return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { require(value < 2**240, "SafeCast: value doesn\'t fit in 240 bits"); return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { require(value < 2**232, "SafeCast: value doesn\'t fit in 232 bits"); return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { require(value < 2**224, "SafeCast: value doesn\'t fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { require(value < 2**216, "SafeCast: value doesn\'t fit in 216 bits"); return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { require(value < 2**208, "SafeCast: value doesn\'t fit in 208 bits"); return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { require(value < 2**200, "SafeCast: value doesn\'t fit in 200 bits"); return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { require(value < 2**192, "SafeCast: value doesn\'t fit in 192 bits"); return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { require(value < 2**184, "SafeCast: value doesn\'t fit in 184 bits"); return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { require(value < 2**176, "SafeCast: value doesn\'t fit in 176 bits"); return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { require(value < 2**168, "SafeCast: value doesn\'t fit in 168 bits"); return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { require(value < 2**160, "SafeCast: value doesn\'t fit in 160 bits"); return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { require(value < 2**152, "SafeCast: value doesn\'t fit in 152 bits"); return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { require(value < 2**144, "SafeCast: value doesn\'t fit in 144 bits"); return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { require(value < 2**136, "SafeCast: value doesn\'t fit in 136 bits"); return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { require(value < 2**120, "SafeCast: value doesn\'t fit in 120 bits"); return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { require(value < 2**112, "SafeCast: value doesn\'t fit in 112 bits"); return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { require(value < 2**104, "SafeCast: value doesn\'t fit in 104 bits"); return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { require(value < 2**96, "SafeCast: value doesn\'t fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { require(value < 2**88, "SafeCast: value doesn\'t fit in 88 bits"); return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { require(value < 2**80, "SafeCast: value doesn\'t fit in 80 bits"); return uint80(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { require(value < 2**56, "SafeCast: value doesn\'t fit in 56 bits"); return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { require(value < 2**48, "SafeCast: value doesn\'t fit in 48 bits"); return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { require(value < 2**40, "SafeCast: value doesn\'t fit in 40 bits"); return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { require(value < 2**24, "SafeCast: value doesn\'t fit in 24 bits"); return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits. */ function toUint8(uint256 value) internal pure returns (uint8) { require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits"); return uint8(value); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract ABI
API[{"inputs":[{"internalType":"address","name":"nxmAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"assessmentId","type":"uint256"},{"indexed":false,"internalType":"address","name":"assessor","type":"address"},{"components":[{"internalType":"uint96","name":"accepted","type":"uint96"},{"internalType":"uint96","name":"denied","type":"uint96"},{"internalType":"uint32","name":"start","type":"uint32"},{"internalType":"uint32","name":"end","type":"uint32"}],"indexed":false,"internalType":"struct IAssessment.Poll","name":"poll","type":"tuple"}],"name":"FraudProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"FraudSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint104","name":"amount","type":"uint104"}],"name":"StakeDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"StakeWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"assessmentId","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"stakedAmount","type":"uint96"},{"indexed":false,"internalType":"bool","name":"accepted","type":"bool"},{"indexed":false,"internalType":"string","name":"ipfsAssessmentDataHash","type":"string"}],"name":"VoteCast","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"assessments","outputs":[{"components":[{"internalType":"uint96","name":"accepted","type":"uint96"},{"internalType":"uint96","name":"denied","type":"uint96"},{"internalType":"uint32","name":"start","type":"uint32"},{"internalType":"uint32","name":"end","type":"uint32"}],"internalType":"struct IAssessment.Poll","name":"poll","type":"tuple"},{"internalType":"uint128","name":"totalRewardInNXM","type":"uint128"},{"internalType":"uint128","name":"assessmentDepositInETH","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"assessmentIds","type":"uint256[]"},{"internalType":"bool[]","name":"votes","type":"bool[]"},{"internalType":"string[]","name":"ipfsAssessmentDataHashes","type":"string[]"},{"internalType":"uint96","name":"stakeIncrease","type":"uint96"}],"name":"castVotes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"changeDependentContractAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"masterAddress","type":"address"}],"name":"changeMasterAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"config","outputs":[{"internalType":"uint8","name":"minVotingPeriodInDays","type":"uint8"},{"internalType":"uint8","name":"stakeLockupPeriodInDays","type":"uint8"},{"internalType":"uint8","name":"payoutCooldownInDays","type":"uint8"},{"internalType":"uint8","name":"silentEndingPeriodInDays","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"fraudResolution","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAssessmentsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assessmentId","type":"uint256"}],"name":"getPoll","outputs":[{"components":[{"internalType":"uint96","name":"accepted","type":"uint96"},{"internalType":"uint96","name":"denied","type":"uint96"},{"internalType":"uint32","name":"start","type":"uint32"},{"internalType":"uint32","name":"end","type":"uint32"}],"internalType":"struct IAssessment.Poll","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"getRewards","outputs":[{"internalType":"uint256","name":"totalPendingAmountInNXM","type":"uint256"},{"internalType":"uint256","name":"withdrawableAmountInNXM","type":"uint256"},{"internalType":"uint256","name":"withdrawableUntilIndex","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"assessor","type":"address"}],"name":"getVoteCountOfAssessor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"hasAlreadyVotedOn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"internalContracts","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"master","outputs":[{"internalType":"contract ISAFURAMaster","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nxm","outputs":[{"internalType":"contract ISAFURAToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rootIndex","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"address","name":"assessor","type":"address"},{"internalType":"uint256","name":"lastFraudulentVoteIndex","type":"uint256"},{"internalType":"uint96","name":"burnAmount","type":"uint96"},{"internalType":"uint16","name":"fraudCount","type":"uint16"},{"internalType":"uint256","name":"voteBatchSize","type":"uint256"}],"name":"processFraud","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakeOf","outputs":[{"internalType":"uint96","name":"amount","type":"uint96"},{"internalType":"uint104","name":"rewardsWithdrawableFromIndex","type":"uint104"},{"internalType":"uint16","name":"fraudCount","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"totalAssessmentReward","type":"uint256"},{"internalType":"uint256","name":"assessmentDepositInETH","type":"uint256"}],"name":"startAssessment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"submitFraud","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint96","name":"amount","type":"uint96"},{"internalType":"address","name":"to","type":"address"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum IAssessment.UintParams[]","name":"paramNames","type":"uint8[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"updateUintParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"votesOf","outputs":[{"internalType":"uint80","name":"assessmentId","type":"uint80"},{"internalType":"bool","name":"accepted","type":"bool"},{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"uint96","name":"stakedAmount","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"uint104","name":"batchSize","type":"uint104"}],"name":"withdrawRewards","outputs":[{"internalType":"uint256","name":"withdrawn","type":"uint256"},{"internalType":"uint256","name":"withdrawnUntilIndex","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"destination","type":"address"},{"internalType":"uint104","name":"batchSize","type":"uint104"}],"name":"withdrawRewardsTo","outputs":[{"internalType":"uint256","name":"withdrawn","type":"uint256"},{"internalType":"uint256","name":"withdrawnUntilIndex","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b5060405162003a5338038062003a53833981016040819052620000349162000046565b6001600160a01b031660805262000078565b6000602082840312156200005957600080fd5b81516001600160a01b03811681146200007157600080fd5b9392505050565b6080516139aa620000a9600039600081816101a80152818161058d015281816107eb0152611fd201526139aa6000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c80638d21e857116100c3578063e6e852561161007c578063e6e852561461044b578063eb96236014610453578063ee97f7f31461047c578063f2d748161461048f578063f6e0f60b146104b7578063fa15af7e146104ca57600080fd5b80638d21e8571461035a5780638fead5521461036d578063952946d1146103be578063c5d26985146103d1578063c672bf6c146103fa578063d46655f41461043857600080fd5b80635a81d265116101155780635a81d2651461027c57806361f129ad1461028f57806376fcbd5d146102a257806376fe6754146102c357806379502c55146102d657806379ee54f71461032c57600080fd5b80630dfced2b1461015d5780630ea9c984146101725780631a8cbcaa1461017a57806330e45f05146101a357806342623360146101e25780634eb6a3b21461025a575b600080fd5b61017061016b366004613202565b6104dd565b005b6101706108c3565b61018d610188366004613239565b610be1565b60405161019a9190613291565b60405180910390f35b6101ca7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161019a565b6102296101f036600461329f565b6003602052600090815260409020546001600160601b03811690600160601b81046001600160681b031690600160c81b900461ffff1683565b604080516001600160601b0390941684526001600160681b03909216602084015261ffff169082015260600161019a565b61026d610268366004613239565b610c7d565b60405161019a939291906132c3565b61017061028a366004613337565b610d0b565b61017061029d3660046133e2565b611051565b6102b56102b0366004613239565b611406565b60405190815260200161019a565b6101706102d13660046133fd565b611427565b6002546102ff9060ff808216916101008104821691620100008204811691630100000090041684565b6040805160ff9586168152938516602085015291841691830191909152909116606082015260800161019a565b61033f61033a36600461329f565b611708565b6040805193845260208401929092529082015260600161019a565b610170610368366004613469565b6119c7565b61038061037b366004613507565b6120f9565b604080516001600160501b039095168552921515602085015263ffffffff909116918301919091526001600160601b0316606082015260800161019a565b6101706103cc366004613239565b61215a565b6102b56103df36600461329f565b6001600160a01b031660009081526004602052604090205490565b610428610408366004613507565b600560209081526000928352604080842090915290825290205460ff1681565b604051901515815260200161019a565b61017061044636600461329f565b612247565b6007546102b5565b6101ca610461366004613239565b6001602052600090815260409020546001600160a01b031681565b6000546101ca906001600160a01b031681565b6104a261049d366004613533565b6122c1565b6040805192835260208301919091520161019a565b6102b56104c536600461356d565b612366565b6104a26104d8366004613533565b612562565b60008054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561052e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610552919061359d565b156105785760405162461bcd60e51b815260040161056f906135ba565b60405180910390fd5b6040516398fd371f60e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906398fd371f90602401602060405180830381865afa1580156105dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060091906135e4565b42101561067a576001600160a01b038116331461067a5760405162461bcd60e51b815260206004820152603260248201527f4173736573736d656e743a204e584d206973206c6f636b656420666f7220766f60448201527174696e6720696e20676f7665726e616e636560701b606482015260840161056f565b33600090815260046020526040902054801561079d573360009081526004602052604081206106aa600184613613565b815481106106ba576106ba613626565b60009182526020918290206040805160808101825292909101546001600160501b0381168352600160501b810460ff908116151594840194909452600160581b810463ffffffff1691830191909152600160781b90046001600160601b0316606082015260025490925061073891610100909104166201518061363c565b816040015163ffffffff1661074d9190613653565b421161079b5760405162461bcd60e51b815260206004820152601960248201527f5374616b6520697320696e206c6f636b757020706572696f6400000000000000604482015260640161056f565b505b33600090815260036020526040812080548592906107c59084906001600160601b0316613666565b92506101000a8154816001600160601b0302191690836001600160601b031602179055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb83856040518363ffffffff1660e01b815260040161083792919061368d565b6020604051808303816000875af1158015610856573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061087a919061359d565b50336001600160a01b03167fcb4980f3d99f91eefd64011186d3c941533eb8e28989b14afc5c5713c4f1e55f83856040516108b692919061368d565b60405180910390a2505050565b6000546040516227050b60e31b815261544360f01b60048201526001600160a01b0390911690630138285890602401602060405180830381865afa15801561090f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093391906136af565b600080805260016020527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4980546001600160a01b039384166001600160a01b0319909116179055546040516227050b60e31b81526126a960f11b6004820152911690630138285890602401602060405180830381865afa1580156109bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109df91906136af565b60026000908152600160205260008051602061395583398151915280546001600160a01b039384166001600160a01b0319909116179055546040516227050b60e31b815261524160f01b6004820152911690630138285890602401602060405180830381865afa158015610a57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7b91906136af565b600d6000908152600160209081527f86b3fa87ee245373978e0d2d334dbde866c9b8b039036b87c5eb2fd89bcb6bab80546001600160a01b03949094166001600160a01b0319909416939093179092556040805160808101825260025460ff808216835261010082048082168488015262010000830480831685870152630100000084049283166060860152945160f893841b6001600160f81b03199081169882019890985294831b87166021860152821b86166022850152901b90931660238201528190602401604051602081830303815290604052610b5b906136e2565b1490508015610bdd576002805463ffffffff19166301010e03179055610b8160006125fb565b60405163e43252d760e01b81523060048201526001600160a01b03919091169063e43252d790602401600060405180830381600087803b158015610bc457600080fd5b505af1158015610bd8573d6000803e3d6000fd5b505050505b5050565b60408051608081018252600080825260208201819052918101829052606081019190915260078281548110610c1857610c18613626565b6000918252602091829020604080516080810182526002909302909101546001600160601b038082168452600160601b8204169383019390935263ffffffff600160c01b8404811691830191909152600160e01b909204909116606082015292915050565b60078181548110610c8d57600080fd5b600091825260209182902060408051608081018252600290930290910180546001600160601b038082168552600160601b8204169484019490945263ffffffff600160c01b8504811692840192909252600160e01b9093041660608201526001909101549091506001600160801b0380821691600160801b90041683565b6002600081905260016020526000805160206139558339815191525460405163505ef22f60e01b815233600482015260248101929092526001600160a01b03169063505ef22f90604401602060405180830381865afa158015610d72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d96919061359d565b610ddb5760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba10309036b2b6b132b960511b604482015260640161056f565b60008054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e50919061359d565b15610e6d5760405162461bcd60e51b815260040161056f906135ba565b858414610ee25760405162461bcd60e51b815260206004820152603b60248201527f546865206c656e67746873206f6620746865206173736573736d656e7420696460448201527f7320616e6420766f74657320617272617973206d69736d617463680000000000606482015260840161056f565b858214610f715760405162461bcd60e51b815260206004820152605160248201527f546865206c656e67746873206f6620746865206173736573736d656e7420696460448201527f7320616e642069706673206173736573736d656e7420646174612068617368656064820152700e640c2e4e4c2f2e640dad2e6dac2e8c6d607b1b608482015260a40161056f565b6001600160601b03811615610f8957610f8981611051565b60005b8681101561104757611035888883818110610fa957610fa9613626565b90506020020135878784818110610fc257610fc2613626565b9050602002016020810190610fd79190613709565b868685818110610fe957610fe9613626565b9050602002810190610ffb9190613726565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061263392505050565b8061103f8161376d565b915050610f8c565b5050505050505050565b60008054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110c6919061359d565b156110e35760405162461bcd60e51b815260040161056f906135ba565b600260005260016020526000805160206139558339815191525460405163505ef22f60e01b8152336004820152600360248201526001600160a01b039091169063505ef22f90604401602060405180830381865afa158015611149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116d919061359d565b806111fe57506002600052600160208190526000805160206139558339815191525460405163505ef22f60e01b815233600482015260248101929092526001600160a01b03169063505ef22f90604401602060405180830381865afa1580156111da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111fe919061359d565b806112905750600260005260016020526000805160206139558339815191525460405163505ef22f60e01b81523360048281019190915260248201526001600160a01b039091169063505ef22f90604401602060405180830381865afa15801561126c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611290919061359d565b6112f25760405162461bcd60e51b815260206004820152602d60248201527f4f6e6c79206f776e65722c2061647669736f727920626f6172642c206175646960448201526c746f722063616e207374616b6560981b606482015260840161056f565b336000908152600360205260408120805483929061131a9084906001600160601b0316613786565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555061134860006125fb565b604051630d1af10360e01b81523360048201523060248201526001600160601b03831660448201526001600160a01b039190911690630d1af103906064016020604051808303816000875af11580156113a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c9919061359d565b507fdef41a302ea97342af2a80a031302289f058ae936d3c7ce9e5ae74db9755c53633826040516113fb92919061368d565b60405180910390a150565b6006818154811061141657600080fd5b600091825260209091200154905081565b600054604051632c1a733d60e11b81523360048201526001600160a01b0390911690635834e67a90602401602060405180830381865afa15801561146f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611493919061359d565b6114af5760405162461bcd60e51b815260040161056f906137a6565b6040805160808101825260025460ff808216835261010082048116602084015262010000820481169383019390935263010000009004909116606082015260005b848110156116a657600086868381811061150c5761150c613626565b905060200201602081019061152191906137e8565b6003811115611532576115326136cc565b0361155c5783838281811061154957611549613626565b602002919091013560ff16835250611694565b600186868381811061157057611570613626565b905060200201602081019061158591906137e8565b6003811115611596576115966136cc565b036115ca578383828181106115ad576115ad613626565b90506020020135826020019060ff16908160ff1681525050611694565b60028686838181106115de576115de613626565b90506020020160208101906115f391906137e8565b6003811115611604576116046136cc565b036116315783838281811061161b5761161b613626565b602002919091013560ff16604084015250611694565b600386868381811061164557611645613626565b905060200201602081019061165a91906137e8565b600381111561166b5761166b6136cc565b036116945783838281811061168257611682613626565b602002919091013560ff166060840152505b8061169e8161376d565b9150506114f0565b508051600280546020840151604085015160609095015160ff90811663010000000263ff0000001996821662010000029690961663ffff0000199282166101000261ffff19909416919095161791909117169190911791909117905550505050565b6001600160a01b03811660009081526003602090815260408083205481516080810183528481529283018490529082018390526060820183905282918291600160601b90046001600160681b0316906117956040805160e0810182526000606082018181526080830182905260a0830182905260c083018290528252602082018190529181019190915290565b6001600160a01b038716600090815260046020526040812054906001600160681b0385165b828110156119ae576001600160a01b038a1660009081526004602052604090208054829081106117ec576117ec613626565b60009182526020918290206040805160808101825292909101546001600160501b038116808452600160501b820460ff16151594840194909452600160581b810463ffffffff1691830191909152600160781b90046001600160601b03166060820152600780549197509190811061186657611866613626565b60009182526020918290206040805160e081018252600290930290910180546001600160601b0380821660608601908152600160601b8304909116608086015263ffffffff600160c01b8304811660a0870152600160e01b90920490911660c08501528352600101546001600160801b0380821694840194909452600160801b900490921691810191909152935081158015611931575060025442906119189062010000900460ff166201518061363c565b85516060015161192e919063ffffffff16613653565b10155b1561194157600191508096508897505b835160208101519051611960916001600160601b039081169116613653565b85606001516001600160601b031685602001516001600160801b0316611986919061363c565b6119909190613809565b61199a908a613653565b9850806119a68161376d565b9150506117ba565b50806119bb578195508796505b50505050509193909250565b60008054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3c919061359d565b15611a595760405162461bcd60e51b815260040161056f906135ba565b611b2687878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050600680549092508c91508110611aa557611aa5613626565b906000526020600020015487878787604051602001611b0b949392919060609490941b6bffffffffffffffffffffffff19168452601484019290925260a01b6001600160a01b031916603483015260f01b6001600160f01b031916604082015260420190565b60405160208183030381529060405280519060200120612bb7565b611b695760405162461bcd60e51b815260206004820152601460248201527324b73b30b634b21036b2b935b63290383937b7b360611b604482015260640161056f565b6001600160a01b0385166000908152600360209081526040808320815160608101835290546001600160601b0381168252600160601b81046001600160681b0316938201849052600160c81b900461ffff16918101919091529190611bcf908490613653565b9050858110611be657611be3866001613653565b90505b60208201516001600160681b03165b81811015611ebe576001600160a01b0388166000908152600460205260408120805483908110611c2757611c27613626565b600091825260208083206040805160808101825293909101546001600160501b038116808552600160501b820460ff16151593850193909352600160581b810463ffffffff1691840191909152600160781b90046001600160601b0316606083015260078054929450918110611c9f57611c9f613626565b6000918252602091829020604080516080810182526002938402909201546001600160601b038082168452600160601b8204169483019490945263ffffffff600160c01b8504811691830191909152600160e01b909304909216606083015254909150611d199060ff62010000909104166201518061363c565b816060015163ffffffff16611d2e9190613653565b4263ffffffff1610611d41575050611eac565b816020015115611d7057606082015181518290611d5f908390613666565b6001600160601b0316905250611d93565b816060015181602001818151611d869190613666565b6001600160601b03169052505b6000611da24262015180613653565b90508063ffffffff16826060015163ffffffff161015611dc95763ffffffff811660608301525b82516040517fdbd68c2d2fa78db6879081ebd946b9e36e8dc720b3675f60d0b4bf944af91f6d91611dfd918e90869061382b565b60405180910390a181600784600001516001600160501b031681548110611e2657611e26613626565b600091825260209182902083516002929092020180549284015160408501516060909501516001600160601b039384166001600160c01b031990951694909417600160601b9390911692909202919091176001600160c01b0316600160c01b63ffffffff948516026001600160e01b031617600160e01b93909216929092021790555050505b80611eb68161376d565b915050611bf5565b50816040015161ffff168461ffff160361204b5781600001516001600160601b0316856001600160601b031611611ef55784611ef8565b81515b94508482600001818151611f0c9190613666565b6001600160601b031690525060408201805190611f288261385f565b61ffff16905250600d60005260016020527f86b3fa87ee245373978e0d2d334dbde866c9b8b039036b87c5eb2fd89bcb6bab546001600160a01b03166001600160a01b0316638516e6dc6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611f9e57600080fd5b505af1158015611fb2573d6000803e3d6000fd5b5050604051630852cd8d60e31b81526001600160601b03881660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031692506342966c6891506024016020604051808303816000875af1158015612025573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612049919061359d565b505b81602001516001600160681b0316816001600160681b03161115612079576001600160681b03811660208301525b506001600160a01b039095166000908152600360209081526040918290208751815492890151939098015161ffff16600160c81b0261ffff60c81b196001600160681b03909416600160601b026001600160c81b03199093166001600160601b039099169890981791909117919091169590951790945550505050505050565b6004602052816000526040600020818154811061211557600080fd5b6000918252602090912001546001600160501b0381169250600160501b810460ff169150600160581b810463ffffffff1690600160781b90046001600160601b031684565b600054604051632c1a733d60e11b81523360048201526001600160a01b0390911690635834e67a90602401602060405180830381865afa1580156121a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121c6919061359d565b6121e25760405162461bcd60e51b815260040161056f906137a6565b600680546001810182556000919091527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f018190556040518181527f3b64045b921584edfe69830a1035d178f18adf23cd3277bb90ae01776911c441906020016113fb565b6000546001600160a01b03161561229f576000546001600160a01b0316331461229f5760405162461bcd60e51b815260206004820152600a6024820152692737ba1036b0b9ba32b960b11b604482015260640161056f565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000805460408051600162f6c75960e01b03198152905183926001600160a01b03169163ff0938a79160048083019260209291908290030181865afa15801561230e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612332919061359d565b1561234f5760405162461bcd60e51b815260040161056f906135ba565b61235a338585612bcd565b915091505b9250929050565b600080546040516323c5b10760e21b81523360048201526001600160a01b0390911690638f16c41c90602401602060405180830381865afa1580156123af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123d3919061359d565b61242a5760405162461bcd60e51b815260206004820152602260248201527f43616c6c6572206973206e6f7420616e20696e7465726e616c20636f6e74726160448201526118dd60f21b606482015260840161056f565b6040805160e08101909152600060608201818152608083019190915263ffffffff421660a083015260025460079291829160c08301906124709060ff1662015180613880565b6124809063ffffffff1642613653565b63ffffffff9081169091529082526001600160801b03808816602080850191909152878216604094850152855460018181018855600097885296829020865180516002909302909101805482850151838901516060909401518816600160e01b026001600160e01b0394909816600160c01b02939093166001600160c01b036001600160601b03948516600160601b026001600160c01b0319909316949095169390931717929092161793909317835584015193909201518216600160801b029290911691909117908201556007546125599190613613565b90505b92915050565b6000805460408051600162f6c75960e01b03198152905183926001600160a01b03169163ff0938a79160048083019260209291908290030181865afa1580156125af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d3919061359d565b156125f05760405162461bcd60e51b815260040161056f906135ba565b61235a848585612bcd565b60006001600083600f811115612613576126136136cc565b81526020810191909152604001600020546001600160a01b031692915050565b33600090815260056020908152604080832086845290915290205460ff161561268e5760405162461bcd60e51b815260206004820152600d60248201526c105b1c9958591e481d9bdd1959609a1b604482015260640161056f565b3360008181526005602090815260408083208784528252808320805460ff191660011790559282526003905220546001600160601b03168061271c5760405162461bcd60e51b815260206004820152602160248201527f41207374616b6520697320726571756972656420746f206361737420766f74656044820152607360f81b606482015260840161056f565b60006007858154811061273157612731613626565b6000918252602091829020604080516080810182526002909302909101546001600160601b038082168452600160601b8204169383019390935263ffffffff600160c01b8404811691830191909152600160e01b9092049091166060820181905290915042106127d65760405162461bcd60e51b815260206004820152601060248201526f159bdd1a5b99c81a5cc818db1bdcd95960821b604482015260640161056f565b80516001600160601b03161515806127eb5750835b6128515760405162461bcd60e51b815260206004820152603160248201527f4174206c65617374206f6e652061636365707420766f746520697320726571756044820152706972656420746f20766f74652064656e7960781b606482015260840161056f565b80516001600160601b031660000361288c576002546128769060ff166201518061363c565b6128809042613653565b63ffffffff1660608201525b6002546000906128a9906301000000900460ff166201518061363c565b90508042836060015163ffffffff166128c29190613613565b10156129285761290d81836020015184600001516128e09190613786565b6001600160601b0316856001600160601b0316846128fe919061363c565b6129089190613809565b6130d3565b8260600181815161291e91906138a8565b63ffffffff169052505b84156129515782826000018181516129409190613786565b6001600160601b0316905250612970565b82826020018181516129639190613786565b6001600160601b03169052505b816007878154811061298457612984613626565b906000526020600020906002020160000160008201518160000160006101000a8154816001600160601b0302191690836001600160601b03160217905550602082015181600001600c6101000a8154816001600160601b0302191690836001600160601b0316021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555090505060046000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060800160405280886001600160501b0316815260200187151581526020014263ffffffff168152602001856001600160601b03168152509080600181540180825580915050600190039060005260206000200160009091909190915060008201518160000160006101000a8154816001600160501b0302191690836001600160501b03160217905550602082015181600001600a6101000a81548160ff021916908315150217905550604082015181600001600b6101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001600f6101000a8154816001600160601b0302191690836001600160601b031602179055505050336001600160a01b03167f3d458ddf59469b3687c2080e0d452be616c72cf52b89108fc9175327b93de2cd87858888604051612ba794939291906138c5565b60405180910390a2505050505050565b600082612bc485846130e9565b14949350505050565b6002600081815260016020526000805160206139558339815191525460405163505ef22f60e01b81526001600160a01b03868116600483015260248201949094529192839291169063505ef22f90604401602060405180830381865afa158015612c3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5f919061359d565b612cb75760405162461bcd60e51b815260206004820152602360248201527f44657374696e6174696f6e2061646472657373206973206e6f742061206d656d6044820152623132b960e91b606482015260840161056f565b6001600160a01b038516600090815260036020908152604080832054600490925290912054600160601b9091046001600160681b031690808210612d3d5760405162461bcd60e51b815260206004820152601760248201527f4e6f20776974686472617761626c652072657761726473000000000000000000604482015260640161056f565b6000856001600160681b031611612d545780612d68565b612d5e8583613934565b6001600160681b03165b925050612d9560408051608081018252600080825260208201819052918101829052606081019190915290565b6040805160e0810182526000606082018181526080830182905260a0830182905260c08301829052825260208201819052918101919091526001600160681b0383165b84811015612fbd576001600160a01b0389166000908152600460205260409020805482908110612e0a57612e0a613626565b60009182526020918290206040805160808101825292909101546001600160501b038116808452600160501b820460ff16151594840194909452600160581b810463ffffffff1691830191909152600160781b90046001600160601b031660608201526007805491955091908110612e8457612e84613626565b60009182526020918290206040805160e081018252600293840290920180546001600160601b0380821660608601908152600160601b8304909116608086015263ffffffff600160c01b8304811660a0870152600160e01b90920490911660c08501528352600101546001600160801b0380821695840195909552600160801b900490931692810192909252549092504290612f2d9060ff62010000909104166201518061363c565b835160600151612f43919063ffffffff16613653565b10612f5057809450612fbd565b815160208101519051612f6f916001600160601b039081169116613653565b83606001516001600160601b031683602001516001600160801b0316612f95919061363c565b612f9f9190613809565b612fa99087613653565b955080612fb58161376d565b915050612dd8565b50612fc784613136565b6001600160a01b038916600090815260036020526040812080546001600160681b0393909316600160601b026cffffffffffffffffffffffffff60601b1990931692909217909155613018906125fb565b6040516340c10f1960e01b81526001600160a01b0389811660048301526024820188905291909116906340c10f1990604401600060405180830381600087803b15801561306457600080fd5b505af1158015613078573d6000803e3d6000fd5b5050604080516001600160a01b03808d1682528b1660208201529081018890527fe06fab35f3c220725c11d544884aff93ebf67222c8310c487c71f27c844593e89250606001905060405180910390a1505050935093915050565b60008183106130e25781612559565b5090919050565b600081815b845181101561312e5761311a8286838151811061310d5761310d613626565b602002602001015161319f565b9150806131268161376d565b9150506130ee565b509392505050565b6000600160681b821061319b5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663034206269747360c81b606482015260840161056f565b5090565b60008183106131bb576000828152602084905260409020612559565b6000838152602083905260409020612559565b80356001600160601b03811681146131e557600080fd5b919050565b6001600160a01b03811681146131ff57600080fd5b50565b6000806040838503121561321557600080fd5b61321e836131ce565b9150602083013561322e816131ea565b809150509250929050565b60006020828403121561324b57600080fd5b5035919050565b6001600160601b0380825116835280602083015116602084015250604081015163ffffffff808216604085015280606084015116606085015250505050565b6080810161255c8284613252565b6000602082840312156132b157600080fd5b81356132bc816131ea565b9392505050565b60c081016132d18286613252565b6001600160801b03808516608084015280841660a084015250949350505050565b60008083601f84011261330457600080fd5b50813567ffffffffffffffff81111561331c57600080fd5b6020830191508360208260051b850101111561235f57600080fd5b60008060008060008060006080888a03121561335257600080fd5b873567ffffffffffffffff8082111561336a57600080fd5b6133768b838c016132f2565b909950975060208a013591508082111561338f57600080fd5b61339b8b838c016132f2565b909750955060408a01359150808211156133b457600080fd5b506133c18a828b016132f2565b90945092506133d49050606089016131ce565b905092959891949750929550565b6000602082840312156133f457600080fd5b612559826131ce565b6000806000806040858703121561341357600080fd5b843567ffffffffffffffff8082111561342b57600080fd5b613437888389016132f2565b9096509450602087013591508082111561345057600080fd5b5061345d878288016132f2565b95989497509550505050565b60008060008060008060008060e0898b03121561348557600080fd5b88359750602089013567ffffffffffffffff8111156134a357600080fd5b6134af8b828c016132f2565b90985096505060408901356134c3816131ea565b9450606089013593506134d860808a016131ce565b925060a089013561ffff811681146134ef57600080fd5b8092505060c089013590509295985092959890939650565b6000806040838503121561351a57600080fd5b8235613525816131ea565b946020939093013593505050565b6000806040838503121561354657600080fd5b8235613551816131ea565b915060208301356001600160681b038116811461322e57600080fd5b6000806040838503121561358057600080fd5b50508035926020909101359150565b80151581146131ff57600080fd5b6000602082840312156135af57600080fd5b81516132bc8161358f565b60208082526010908201526f14de5cdd195b481a5cc81c185d5cd95960821b604082015260600190565b6000602082840312156135f657600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561255c5761255c6135fd565b634e487b7160e01b600052603260045260246000fd5b808202811582820484141761255c5761255c6135fd565b8082018082111561255c5761255c6135fd565b6001600160601b03828116828216039080821115613686576136866135fd565b5092915050565b6001600160a01b039290921682526001600160601b0316602082015260400190565b6000602082840312156136c157600080fd5b81516132bc816131ea565b634e487b7160e01b600052602160045260246000fd5b80516020808301519190811015613703576000198160200360031b1b821691505b50919050565b60006020828403121561371b57600080fd5b81356132bc8161358f565b6000808335601e1984360301811261373d57600080fd5b83018035915067ffffffffffffffff82111561375857600080fd5b60200191503681900382131561235f57600080fd5b60006001820161377f5761377f6135fd565b5060010190565b6001600160601b03818116838216019080821115613686576136866135fd565b60208082526022908201527f43616c6c6572206973206e6f7420617574686f72697a656420746f20676f7665604082015261393760f11b606082015260800190565b6000602082840312156137fa57600080fd5b8135600481106132bc57600080fd5b60008261382657634e487b7160e01b600052601260045260246000fd5b500490565b6001600160501b03841681526001600160a01b038316602082015260c081016138576040830184613252565b949350505050565b600061ffff808316818103613876576138766135fd565b6001019392505050565b63ffffffff8181168382160280821691908281146138a0576138a06135fd565b505092915050565b63ffffffff818116838216019080821115613686576136866135fd565b848152600060206001600160601b03861681840152841515604084015260806060840152835180608085015260005b818110156139105785810183015185820160a0015282016138f4565b50600060a0828601015260a0601f19601f8301168501019250505095945050505050565b6001600160681b03818116838216019080821115613686576136866135fd56fed9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330fa264697066735822122006bf4a0d4dd8849c076698116ef8d15aac34576c3a9f75c5bb8570e614c5b0d864736f6c63430008120033000000000000000000000000ecef1e050432c9304b23b3226659bf8981cf83a2
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101585760003560e01c80638d21e857116100c3578063e6e852561161007c578063e6e852561461044b578063eb96236014610453578063ee97f7f31461047c578063f2d748161461048f578063f6e0f60b146104b7578063fa15af7e146104ca57600080fd5b80638d21e8571461035a5780638fead5521461036d578063952946d1146103be578063c5d26985146103d1578063c672bf6c146103fa578063d46655f41461043857600080fd5b80635a81d265116101155780635a81d2651461027c57806361f129ad1461028f57806376fcbd5d146102a257806376fe6754146102c357806379502c55146102d657806379ee54f71461032c57600080fd5b80630dfced2b1461015d5780630ea9c984146101725780631a8cbcaa1461017a57806330e45f05146101a357806342623360146101e25780634eb6a3b21461025a575b600080fd5b61017061016b366004613202565b6104dd565b005b6101706108c3565b61018d610188366004613239565b610be1565b60405161019a9190613291565b60405180910390f35b6101ca7f000000000000000000000000ecef1e050432c9304b23b3226659bf8981cf83a281565b6040516001600160a01b03909116815260200161019a565b6102296101f036600461329f565b6003602052600090815260409020546001600160601b03811690600160601b81046001600160681b031690600160c81b900461ffff1683565b604080516001600160601b0390941684526001600160681b03909216602084015261ffff169082015260600161019a565b61026d610268366004613239565b610c7d565b60405161019a939291906132c3565b61017061028a366004613337565b610d0b565b61017061029d3660046133e2565b611051565b6102b56102b0366004613239565b611406565b60405190815260200161019a565b6101706102d13660046133fd565b611427565b6002546102ff9060ff808216916101008104821691620100008204811691630100000090041684565b6040805160ff9586168152938516602085015291841691830191909152909116606082015260800161019a565b61033f61033a36600461329f565b611708565b6040805193845260208401929092529082015260600161019a565b610170610368366004613469565b6119c7565b61038061037b366004613507565b6120f9565b604080516001600160501b039095168552921515602085015263ffffffff909116918301919091526001600160601b0316606082015260800161019a565b6101706103cc366004613239565b61215a565b6102b56103df36600461329f565b6001600160a01b031660009081526004602052604090205490565b610428610408366004613507565b600560209081526000928352604080842090915290825290205460ff1681565b604051901515815260200161019a565b61017061044636600461329f565b612247565b6007546102b5565b6101ca610461366004613239565b6001602052600090815260409020546001600160a01b031681565b6000546101ca906001600160a01b031681565b6104a261049d366004613533565b6122c1565b6040805192835260208301919091520161019a565b6102b56104c536600461356d565b612366565b6104a26104d8366004613533565b612562565b60008054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561052e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610552919061359d565b156105785760405162461bcd60e51b815260040161056f906135ba565b60405180910390fd5b6040516398fd371f60e01b81523360048201527f000000000000000000000000ecef1e050432c9304b23b3226659bf8981cf83a26001600160a01b0316906398fd371f90602401602060405180830381865afa1580156105dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060091906135e4565b42101561067a576001600160a01b038116331461067a5760405162461bcd60e51b815260206004820152603260248201527f4173736573736d656e743a204e584d206973206c6f636b656420666f7220766f60448201527174696e6720696e20676f7665726e616e636560701b606482015260840161056f565b33600090815260046020526040902054801561079d573360009081526004602052604081206106aa600184613613565b815481106106ba576106ba613626565b60009182526020918290206040805160808101825292909101546001600160501b0381168352600160501b810460ff908116151594840194909452600160581b810463ffffffff1691830191909152600160781b90046001600160601b0316606082015260025490925061073891610100909104166201518061363c565b816040015163ffffffff1661074d9190613653565b421161079b5760405162461bcd60e51b815260206004820152601960248201527f5374616b6520697320696e206c6f636b757020706572696f6400000000000000604482015260640161056f565b505b33600090815260036020526040812080548592906107c59084906001600160601b0316613666565b92506101000a8154816001600160601b0302191690836001600160601b031602179055507f000000000000000000000000ecef1e050432c9304b23b3226659bf8981cf83a26001600160a01b031663a9059cbb83856040518363ffffffff1660e01b815260040161083792919061368d565b6020604051808303816000875af1158015610856573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061087a919061359d565b50336001600160a01b03167fcb4980f3d99f91eefd64011186d3c941533eb8e28989b14afc5c5713c4f1e55f83856040516108b692919061368d565b60405180910390a2505050565b6000546040516227050b60e31b815261544360f01b60048201526001600160a01b0390911690630138285890602401602060405180830381865afa15801561090f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093391906136af565b600080805260016020527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4980546001600160a01b039384166001600160a01b0319909116179055546040516227050b60e31b81526126a960f11b6004820152911690630138285890602401602060405180830381865afa1580156109bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109df91906136af565b60026000908152600160205260008051602061395583398151915280546001600160a01b039384166001600160a01b0319909116179055546040516227050b60e31b815261524160f01b6004820152911690630138285890602401602060405180830381865afa158015610a57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7b91906136af565b600d6000908152600160209081527f86b3fa87ee245373978e0d2d334dbde866c9b8b039036b87c5eb2fd89bcb6bab80546001600160a01b03949094166001600160a01b0319909416939093179092556040805160808101825260025460ff808216835261010082048082168488015262010000830480831685870152630100000084049283166060860152945160f893841b6001600160f81b03199081169882019890985294831b87166021860152821b86166022850152901b90931660238201528190602401604051602081830303815290604052610b5b906136e2565b1490508015610bdd576002805463ffffffff19166301010e03179055610b8160006125fb565b60405163e43252d760e01b81523060048201526001600160a01b03919091169063e43252d790602401600060405180830381600087803b158015610bc457600080fd5b505af1158015610bd8573d6000803e3d6000fd5b505050505b5050565b60408051608081018252600080825260208201819052918101829052606081019190915260078281548110610c1857610c18613626565b6000918252602091829020604080516080810182526002909302909101546001600160601b038082168452600160601b8204169383019390935263ffffffff600160c01b8404811691830191909152600160e01b909204909116606082015292915050565b60078181548110610c8d57600080fd5b600091825260209182902060408051608081018252600290930290910180546001600160601b038082168552600160601b8204169484019490945263ffffffff600160c01b8504811692840192909252600160e01b9093041660608201526001909101549091506001600160801b0380821691600160801b90041683565b6002600081905260016020526000805160206139558339815191525460405163505ef22f60e01b815233600482015260248101929092526001600160a01b03169063505ef22f90604401602060405180830381865afa158015610d72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d96919061359d565b610ddb5760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba10309036b2b6b132b960511b604482015260640161056f565b60008054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e50919061359d565b15610e6d5760405162461bcd60e51b815260040161056f906135ba565b858414610ee25760405162461bcd60e51b815260206004820152603b60248201527f546865206c656e67746873206f6620746865206173736573736d656e7420696460448201527f7320616e6420766f74657320617272617973206d69736d617463680000000000606482015260840161056f565b858214610f715760405162461bcd60e51b815260206004820152605160248201527f546865206c656e67746873206f6620746865206173736573736d656e7420696460448201527f7320616e642069706673206173736573736d656e7420646174612068617368656064820152700e640c2e4e4c2f2e640dad2e6dac2e8c6d607b1b608482015260a40161056f565b6001600160601b03811615610f8957610f8981611051565b60005b8681101561104757611035888883818110610fa957610fa9613626565b90506020020135878784818110610fc257610fc2613626565b9050602002016020810190610fd79190613709565b868685818110610fe957610fe9613626565b9050602002810190610ffb9190613726565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061263392505050565b8061103f8161376d565b915050610f8c565b5050505050505050565b60008054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110c6919061359d565b156110e35760405162461bcd60e51b815260040161056f906135ba565b600260005260016020526000805160206139558339815191525460405163505ef22f60e01b8152336004820152600360248201526001600160a01b039091169063505ef22f90604401602060405180830381865afa158015611149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116d919061359d565b806111fe57506002600052600160208190526000805160206139558339815191525460405163505ef22f60e01b815233600482015260248101929092526001600160a01b03169063505ef22f90604401602060405180830381865afa1580156111da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111fe919061359d565b806112905750600260005260016020526000805160206139558339815191525460405163505ef22f60e01b81523360048281019190915260248201526001600160a01b039091169063505ef22f90604401602060405180830381865afa15801561126c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611290919061359d565b6112f25760405162461bcd60e51b815260206004820152602d60248201527f4f6e6c79206f776e65722c2061647669736f727920626f6172642c206175646960448201526c746f722063616e207374616b6560981b606482015260840161056f565b336000908152600360205260408120805483929061131a9084906001600160601b0316613786565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555061134860006125fb565b604051630d1af10360e01b81523360048201523060248201526001600160601b03831660448201526001600160a01b039190911690630d1af103906064016020604051808303816000875af11580156113a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c9919061359d565b507fdef41a302ea97342af2a80a031302289f058ae936d3c7ce9e5ae74db9755c53633826040516113fb92919061368d565b60405180910390a150565b6006818154811061141657600080fd5b600091825260209091200154905081565b600054604051632c1a733d60e11b81523360048201526001600160a01b0390911690635834e67a90602401602060405180830381865afa15801561146f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611493919061359d565b6114af5760405162461bcd60e51b815260040161056f906137a6565b6040805160808101825260025460ff808216835261010082048116602084015262010000820481169383019390935263010000009004909116606082015260005b848110156116a657600086868381811061150c5761150c613626565b905060200201602081019061152191906137e8565b6003811115611532576115326136cc565b0361155c5783838281811061154957611549613626565b602002919091013560ff16835250611694565b600186868381811061157057611570613626565b905060200201602081019061158591906137e8565b6003811115611596576115966136cc565b036115ca578383828181106115ad576115ad613626565b90506020020135826020019060ff16908160ff1681525050611694565b60028686838181106115de576115de613626565b90506020020160208101906115f391906137e8565b6003811115611604576116046136cc565b036116315783838281811061161b5761161b613626565b602002919091013560ff16604084015250611694565b600386868381811061164557611645613626565b905060200201602081019061165a91906137e8565b600381111561166b5761166b6136cc565b036116945783838281811061168257611682613626565b602002919091013560ff166060840152505b8061169e8161376d565b9150506114f0565b508051600280546020840151604085015160609095015160ff90811663010000000263ff0000001996821662010000029690961663ffff0000199282166101000261ffff19909416919095161791909117169190911791909117905550505050565b6001600160a01b03811660009081526003602090815260408083205481516080810183528481529283018490529082018390526060820183905282918291600160601b90046001600160681b0316906117956040805160e0810182526000606082018181526080830182905260a0830182905260c083018290528252602082018190529181019190915290565b6001600160a01b038716600090815260046020526040812054906001600160681b0385165b828110156119ae576001600160a01b038a1660009081526004602052604090208054829081106117ec576117ec613626565b60009182526020918290206040805160808101825292909101546001600160501b038116808452600160501b820460ff16151594840194909452600160581b810463ffffffff1691830191909152600160781b90046001600160601b03166060820152600780549197509190811061186657611866613626565b60009182526020918290206040805160e081018252600290930290910180546001600160601b0380821660608601908152600160601b8304909116608086015263ffffffff600160c01b8304811660a0870152600160e01b90920490911660c08501528352600101546001600160801b0380821694840194909452600160801b900490921691810191909152935081158015611931575060025442906119189062010000900460ff166201518061363c565b85516060015161192e919063ffffffff16613653565b10155b1561194157600191508096508897505b835160208101519051611960916001600160601b039081169116613653565b85606001516001600160601b031685602001516001600160801b0316611986919061363c565b6119909190613809565b61199a908a613653565b9850806119a68161376d565b9150506117ba565b50806119bb578195508796505b50505050509193909250565b60008054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3c919061359d565b15611a595760405162461bcd60e51b815260040161056f906135ba565b611b2687878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050600680549092508c91508110611aa557611aa5613626565b906000526020600020015487878787604051602001611b0b949392919060609490941b6bffffffffffffffffffffffff19168452601484019290925260a01b6001600160a01b031916603483015260f01b6001600160f01b031916604082015260420190565b60405160208183030381529060405280519060200120612bb7565b611b695760405162461bcd60e51b815260206004820152601460248201527324b73b30b634b21036b2b935b63290383937b7b360611b604482015260640161056f565b6001600160a01b0385166000908152600360209081526040808320815160608101835290546001600160601b0381168252600160601b81046001600160681b0316938201849052600160c81b900461ffff16918101919091529190611bcf908490613653565b9050858110611be657611be3866001613653565b90505b60208201516001600160681b03165b81811015611ebe576001600160a01b0388166000908152600460205260408120805483908110611c2757611c27613626565b600091825260208083206040805160808101825293909101546001600160501b038116808552600160501b820460ff16151593850193909352600160581b810463ffffffff1691840191909152600160781b90046001600160601b0316606083015260078054929450918110611c9f57611c9f613626565b6000918252602091829020604080516080810182526002938402909201546001600160601b038082168452600160601b8204169483019490945263ffffffff600160c01b8504811691830191909152600160e01b909304909216606083015254909150611d199060ff62010000909104166201518061363c565b816060015163ffffffff16611d2e9190613653565b4263ffffffff1610611d41575050611eac565b816020015115611d7057606082015181518290611d5f908390613666565b6001600160601b0316905250611d93565b816060015181602001818151611d869190613666565b6001600160601b03169052505b6000611da24262015180613653565b90508063ffffffff16826060015163ffffffff161015611dc95763ffffffff811660608301525b82516040517fdbd68c2d2fa78db6879081ebd946b9e36e8dc720b3675f60d0b4bf944af91f6d91611dfd918e90869061382b565b60405180910390a181600784600001516001600160501b031681548110611e2657611e26613626565b600091825260209182902083516002929092020180549284015160408501516060909501516001600160601b039384166001600160c01b031990951694909417600160601b9390911692909202919091176001600160c01b0316600160c01b63ffffffff948516026001600160e01b031617600160e01b93909216929092021790555050505b80611eb68161376d565b915050611bf5565b50816040015161ffff168461ffff160361204b5781600001516001600160601b0316856001600160601b031611611ef55784611ef8565b81515b94508482600001818151611f0c9190613666565b6001600160601b031690525060408201805190611f288261385f565b61ffff16905250600d60005260016020527f86b3fa87ee245373978e0d2d334dbde866c9b8b039036b87c5eb2fd89bcb6bab546001600160a01b03166001600160a01b0316638516e6dc6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611f9e57600080fd5b505af1158015611fb2573d6000803e3d6000fd5b5050604051630852cd8d60e31b81526001600160601b03881660048201527f000000000000000000000000ecef1e050432c9304b23b3226659bf8981cf83a26001600160a01b031692506342966c6891506024016020604051808303816000875af1158015612025573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612049919061359d565b505b81602001516001600160681b0316816001600160681b03161115612079576001600160681b03811660208301525b506001600160a01b039095166000908152600360209081526040918290208751815492890151939098015161ffff16600160c81b0261ffff60c81b196001600160681b03909416600160601b026001600160c81b03199093166001600160601b039099169890981791909117919091169590951790945550505050505050565b6004602052816000526040600020818154811061211557600080fd5b6000918252602090912001546001600160501b0381169250600160501b810460ff169150600160581b810463ffffffff1690600160781b90046001600160601b031684565b600054604051632c1a733d60e11b81523360048201526001600160a01b0390911690635834e67a90602401602060405180830381865afa1580156121a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121c6919061359d565b6121e25760405162461bcd60e51b815260040161056f906137a6565b600680546001810182556000919091527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f018190556040518181527f3b64045b921584edfe69830a1035d178f18adf23cd3277bb90ae01776911c441906020016113fb565b6000546001600160a01b03161561229f576000546001600160a01b0316331461229f5760405162461bcd60e51b815260206004820152600a6024820152692737ba1036b0b9ba32b960b11b604482015260640161056f565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000805460408051600162f6c75960e01b03198152905183926001600160a01b03169163ff0938a79160048083019260209291908290030181865afa15801561230e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612332919061359d565b1561234f5760405162461bcd60e51b815260040161056f906135ba565b61235a338585612bcd565b915091505b9250929050565b600080546040516323c5b10760e21b81523360048201526001600160a01b0390911690638f16c41c90602401602060405180830381865afa1580156123af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123d3919061359d565b61242a5760405162461bcd60e51b815260206004820152602260248201527f43616c6c6572206973206e6f7420616e20696e7465726e616c20636f6e74726160448201526118dd60f21b606482015260840161056f565b6040805160e08101909152600060608201818152608083019190915263ffffffff421660a083015260025460079291829160c08301906124709060ff1662015180613880565b6124809063ffffffff1642613653565b63ffffffff9081169091529082526001600160801b03808816602080850191909152878216604094850152855460018181018855600097885296829020865180516002909302909101805482850151838901516060909401518816600160e01b026001600160e01b0394909816600160c01b02939093166001600160c01b036001600160601b03948516600160601b026001600160c01b0319909316949095169390931717929092161793909317835584015193909201518216600160801b029290911691909117908201556007546125599190613613565b90505b92915050565b6000805460408051600162f6c75960e01b03198152905183926001600160a01b03169163ff0938a79160048083019260209291908290030181865afa1580156125af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d3919061359d565b156125f05760405162461bcd60e51b815260040161056f906135ba565b61235a848585612bcd565b60006001600083600f811115612613576126136136cc565b81526020810191909152604001600020546001600160a01b031692915050565b33600090815260056020908152604080832086845290915290205460ff161561268e5760405162461bcd60e51b815260206004820152600d60248201526c105b1c9958591e481d9bdd1959609a1b604482015260640161056f565b3360008181526005602090815260408083208784528252808320805460ff191660011790559282526003905220546001600160601b03168061271c5760405162461bcd60e51b815260206004820152602160248201527f41207374616b6520697320726571756972656420746f206361737420766f74656044820152607360f81b606482015260840161056f565b60006007858154811061273157612731613626565b6000918252602091829020604080516080810182526002909302909101546001600160601b038082168452600160601b8204169383019390935263ffffffff600160c01b8404811691830191909152600160e01b9092049091166060820181905290915042106127d65760405162461bcd60e51b815260206004820152601060248201526f159bdd1a5b99c81a5cc818db1bdcd95960821b604482015260640161056f565b80516001600160601b03161515806127eb5750835b6128515760405162461bcd60e51b815260206004820152603160248201527f4174206c65617374206f6e652061636365707420766f746520697320726571756044820152706972656420746f20766f74652064656e7960781b606482015260840161056f565b80516001600160601b031660000361288c576002546128769060ff166201518061363c565b6128809042613653565b63ffffffff1660608201525b6002546000906128a9906301000000900460ff166201518061363c565b90508042836060015163ffffffff166128c29190613613565b10156129285761290d81836020015184600001516128e09190613786565b6001600160601b0316856001600160601b0316846128fe919061363c565b6129089190613809565b6130d3565b8260600181815161291e91906138a8565b63ffffffff169052505b84156129515782826000018181516129409190613786565b6001600160601b0316905250612970565b82826020018181516129639190613786565b6001600160601b03169052505b816007878154811061298457612984613626565b906000526020600020906002020160000160008201518160000160006101000a8154816001600160601b0302191690836001600160601b03160217905550602082015181600001600c6101000a8154816001600160601b0302191690836001600160601b0316021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555090505060046000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060800160405280886001600160501b0316815260200187151581526020014263ffffffff168152602001856001600160601b03168152509080600181540180825580915050600190039060005260206000200160009091909190915060008201518160000160006101000a8154816001600160501b0302191690836001600160501b03160217905550602082015181600001600a6101000a81548160ff021916908315150217905550604082015181600001600b6101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001600f6101000a8154816001600160601b0302191690836001600160601b031602179055505050336001600160a01b03167f3d458ddf59469b3687c2080e0d452be616c72cf52b89108fc9175327b93de2cd87858888604051612ba794939291906138c5565b60405180910390a2505050505050565b600082612bc485846130e9565b14949350505050565b6002600081815260016020526000805160206139558339815191525460405163505ef22f60e01b81526001600160a01b03868116600483015260248201949094529192839291169063505ef22f90604401602060405180830381865afa158015612c3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5f919061359d565b612cb75760405162461bcd60e51b815260206004820152602360248201527f44657374696e6174696f6e2061646472657373206973206e6f742061206d656d6044820152623132b960e91b606482015260840161056f565b6001600160a01b038516600090815260036020908152604080832054600490925290912054600160601b9091046001600160681b031690808210612d3d5760405162461bcd60e51b815260206004820152601760248201527f4e6f20776974686472617761626c652072657761726473000000000000000000604482015260640161056f565b6000856001600160681b031611612d545780612d68565b612d5e8583613934565b6001600160681b03165b925050612d9560408051608081018252600080825260208201819052918101829052606081019190915290565b6040805160e0810182526000606082018181526080830182905260a0830182905260c08301829052825260208201819052918101919091526001600160681b0383165b84811015612fbd576001600160a01b0389166000908152600460205260409020805482908110612e0a57612e0a613626565b60009182526020918290206040805160808101825292909101546001600160501b038116808452600160501b820460ff16151594840194909452600160581b810463ffffffff1691830191909152600160781b90046001600160601b031660608201526007805491955091908110612e8457612e84613626565b60009182526020918290206040805160e081018252600293840290920180546001600160601b0380821660608601908152600160601b8304909116608086015263ffffffff600160c01b8304811660a0870152600160e01b90920490911660c08501528352600101546001600160801b0380821695840195909552600160801b900490931692810192909252549092504290612f2d9060ff62010000909104166201518061363c565b835160600151612f43919063ffffffff16613653565b10612f5057809450612fbd565b815160208101519051612f6f916001600160601b039081169116613653565b83606001516001600160601b031683602001516001600160801b0316612f95919061363c565b612f9f9190613809565b612fa99087613653565b955080612fb58161376d565b915050612dd8565b50612fc784613136565b6001600160a01b038916600090815260036020526040812080546001600160681b0393909316600160601b026cffffffffffffffffffffffffff60601b1990931692909217909155613018906125fb565b6040516340c10f1960e01b81526001600160a01b0389811660048301526024820188905291909116906340c10f1990604401600060405180830381600087803b15801561306457600080fd5b505af1158015613078573d6000803e3d6000fd5b5050604080516001600160a01b03808d1682528b1660208201529081018890527fe06fab35f3c220725c11d544884aff93ebf67222c8310c487c71f27c844593e89250606001905060405180910390a1505050935093915050565b60008183106130e25781612559565b5090919050565b600081815b845181101561312e5761311a8286838151811061310d5761310d613626565b602002602001015161319f565b9150806131268161376d565b9150506130ee565b509392505050565b6000600160681b821061319b5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663034206269747360c81b606482015260840161056f565b5090565b60008183106131bb576000828152602084905260409020612559565b6000838152602083905260409020612559565b80356001600160601b03811681146131e557600080fd5b919050565b6001600160a01b03811681146131ff57600080fd5b50565b6000806040838503121561321557600080fd5b61321e836131ce565b9150602083013561322e816131ea565b809150509250929050565b60006020828403121561324b57600080fd5b5035919050565b6001600160601b0380825116835280602083015116602084015250604081015163ffffffff808216604085015280606084015116606085015250505050565b6080810161255c8284613252565b6000602082840312156132b157600080fd5b81356132bc816131ea565b9392505050565b60c081016132d18286613252565b6001600160801b03808516608084015280841660a084015250949350505050565b60008083601f84011261330457600080fd5b50813567ffffffffffffffff81111561331c57600080fd5b6020830191508360208260051b850101111561235f57600080fd5b60008060008060008060006080888a03121561335257600080fd5b873567ffffffffffffffff8082111561336a57600080fd5b6133768b838c016132f2565b909950975060208a013591508082111561338f57600080fd5b61339b8b838c016132f2565b909750955060408a01359150808211156133b457600080fd5b506133c18a828b016132f2565b90945092506133d49050606089016131ce565b905092959891949750929550565b6000602082840312156133f457600080fd5b612559826131ce565b6000806000806040858703121561341357600080fd5b843567ffffffffffffffff8082111561342b57600080fd5b613437888389016132f2565b9096509450602087013591508082111561345057600080fd5b5061345d878288016132f2565b95989497509550505050565b60008060008060008060008060e0898b03121561348557600080fd5b88359750602089013567ffffffffffffffff8111156134a357600080fd5b6134af8b828c016132f2565b90985096505060408901356134c3816131ea565b9450606089013593506134d860808a016131ce565b925060a089013561ffff811681146134ef57600080fd5b8092505060c089013590509295985092959890939650565b6000806040838503121561351a57600080fd5b8235613525816131ea565b946020939093013593505050565b6000806040838503121561354657600080fd5b8235613551816131ea565b915060208301356001600160681b038116811461322e57600080fd5b6000806040838503121561358057600080fd5b50508035926020909101359150565b80151581146131ff57600080fd5b6000602082840312156135af57600080fd5b81516132bc8161358f565b60208082526010908201526f14de5cdd195b481a5cc81c185d5cd95960821b604082015260600190565b6000602082840312156135f657600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561255c5761255c6135fd565b634e487b7160e01b600052603260045260246000fd5b808202811582820484141761255c5761255c6135fd565b8082018082111561255c5761255c6135fd565b6001600160601b03828116828216039080821115613686576136866135fd565b5092915050565b6001600160a01b039290921682526001600160601b0316602082015260400190565b6000602082840312156136c157600080fd5b81516132bc816131ea565b634e487b7160e01b600052602160045260246000fd5b80516020808301519190811015613703576000198160200360031b1b821691505b50919050565b60006020828403121561371b57600080fd5b81356132bc8161358f565b6000808335601e1984360301811261373d57600080fd5b83018035915067ffffffffffffffff82111561375857600080fd5b60200191503681900382131561235f57600080fd5b60006001820161377f5761377f6135fd565b5060010190565b6001600160601b03818116838216019080821115613686576136866135fd565b60208082526022908201527f43616c6c6572206973206e6f7420617574686f72697a656420746f20676f7665604082015261393760f11b606082015260800190565b6000602082840312156137fa57600080fd5b8135600481106132bc57600080fd5b60008261382657634e487b7160e01b600052601260045260246000fd5b500490565b6001600160501b03841681526001600160a01b038316602082015260c081016138576040830184613252565b949350505050565b600061ffff808316818103613876576138766135fd565b6001019392505050565b63ffffffff8181168382160280821691908281146138a0576138a06135fd565b505092915050565b63ffffffff818116838216019080821115613686576136866135fd565b848152600060206001600160601b03861681840152841515604084015260806060840152835180608085015260005b818110156139105785810183015185820160a0015282016138f4565b50600060a0828601015260a0601f19601f8301168501019250505095945050505050565b6001600160681b03818116838216019080821115613686576136866135fd56fed9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330fa264697066735822122006bf4a0d4dd8849c076698116ef8d15aac34576c3a9f75c5bb8570e614c5b0d864736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ecef1e050432c9304b23b3226659bf8981cf83a2
-----Decoded View---------------
Arg [0] : nxmAddress (address): 0xeceF1e050432c9304B23b3226659bF8981Cf83a2
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000ecef1e050432c9304b23b3226659bf8981cf83a2
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.