More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 81,954 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Commit | 37990277 | 3 days ago | IN | 0 xDAI | 0.00003662 | ||||
Commit | 37989670 | 3 days ago | IN | 0 xDAI | 0.00003662 | ||||
Commit | 37984500 | 4 days ago | IN | 0 xDAI | 0.00005493 | ||||
Commit | 37983437 | 4 days ago | IN | 0 xDAI | 0.0000549 | ||||
Commit | 37981154 | 4 days ago | IN | 0 xDAI | 0.00005493 | ||||
Commit | 37843597 | 12 days ago | IN | 0 xDAI | 0.0000366 | ||||
Commit | 37821557 | 13 days ago | IN | 0 xDAI | 0.00004135 | ||||
Commit | 37799209 | 15 days ago | IN | 0 xDAI | 0.00003662 | ||||
Commit | 37730052 | 19 days ago | IN | 0 xDAI | 0.00005493 | ||||
Commit | 37707554 | 20 days ago | IN | 0 xDAI | 0.00005493 | ||||
Commit | 37704667 | 20 days ago | IN | 0 xDAI | 0.00005493 | ||||
Commit | 37694182 | 21 days ago | IN | 0 xDAI | 0.00005493 | ||||
Commit | 37479705 | 34 days ago | IN | 0 xDAI | 0.00005493 | ||||
Commit | 37460100 | 35 days ago | IN | 0 xDAI | 0.00005493 | ||||
Commit | 37457670 | 35 days ago | IN | 0 xDAI | 0.00003753 | ||||
Commit | 37452502 | 35 days ago | IN | 0 xDAI | 0.00005493 | ||||
Commit | 37444595 | 36 days ago | IN | 0 xDAI | 0.0000549 | ||||
Commit | 37434717 | 37 days ago | IN | 0 xDAI | 0.00005493 | ||||
Commit | 37428483 | 37 days ago | IN | 0 xDAI | 0.00005493 | ||||
Commit | 37426356 | 37 days ago | IN | 0 xDAI | 0.00005493 | ||||
Commit | 37411767 | 38 days ago | IN | 0 xDAI | 0.00005493 | ||||
Commit | 37409799 | 38 days ago | IN | 0 xDAI | 0.00005493 | ||||
Commit | 37407819 | 38 days ago | IN | 0 xDAI | 0.00005493 | ||||
Commit | 37406150 | 38 days ago | IN | 0 xDAI | 0.00004455 | ||||
Commit | 37399606 | 39 days ago | IN | 0 xDAI | 0.00005493 |
View more zero value Internal Transactions in Advanced View mode
Loading...
Loading
Contract Name:
Redistribution
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 1000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BSD-3-Clause pragma solidity ^0.8.19; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "./Util/TransformedChunkProof.sol"; import "./Util/ChunkProof.sol"; import "./Util/Signatures.sol"; import "./interface/IPostageStamp.sol"; interface IPriceOracle { function adjustPrice(uint16 redundancy) external; } interface IStakeRegistry { struct Stake { bytes32 overlay; uint256 stakeAmount; uint256 lastUpdatedBlockNumber; } function freezeDeposit(address _owner, uint256 _time) external; function lastUpdatedBlockNumberOfAddress(address _owner) external view returns (uint256); function overlayOfAddress(address _owner) external view returns (bytes32); function nodeEffectiveStake(address _owner) external view returns (uint256); } /** * @title Redistribution contract * @author The Swarm Authors * @dev Implements a Schelling Co-ordination game to form consensus around the Reserve Commitment hash. This takes * place in three phases: _commit_, _reveal_ and _claim_. * * A node, upon establishing that it _isParticipatingInUpcomingRound_, i.e. it's overlay falls within proximity order * of its reported depth with the _currentRoundAnchor_, prepares a "reserve commitment hash" using the chunks * it currently stores in its reserve and calculates the "storage depth" (see Bee for details). These values, if calculated * honestly, and with the right chunks stored, should be the same for every node in a neighbourhood. This is the Schelling point. * Each eligible node can then use these values, together with a random, single use, secret _revealNonce_ and their * _overlay_ as the pre-image values for the obsfucated _commit_, using the _wrapCommit_ method. * * Once the _commit_ round has elapsed, participating nodes must provide the values used to calculate their obsfucated * _commit_ hash, which, once verified for correctness and proximity to the anchor are retained in the _currentReveals_. * Nodes that have committed but do not reveal the correct values used to create the pre-image will have their stake * "frozen" for a period of rounds proportional to their reported depth. * * During the _reveal_ round, randomness is updated after every successful reveal. Once the reveal round is concluded, * the _currentRoundAnchor_ is updated and users can determine if they will be eligible their overlay will be eligible * for the next commit phase using _isParticipatingInUpcomingRound_. * * When the _reveal_ phase has been concluded, the claim phase can begin. At this point, the truth teller and winner * are already determined. By calling _isWinner_, an applicant node can run the relevant logic to determine if they have * been selected as the beneficiary of this round. When calling _claim_, the current pot from the PostageStamp contract * is withdrawn and transferred to that beneficiaries address. Nodes that have revealed values that differ from the truth, * have their stakes "frozen" for a period of rounds proportional to their reported depth. */ contract Redistribution is AccessControl, Pausable { // ----------------------------- Type declarations ------------------------------ // An eligible user may commit to an _obfuscatedHash_ during the commit phase... struct Commit { bytes32 overlay; address owner; bool revealed; uint256 stake; bytes32 obfuscatedHash; uint256 revealIndex; } // ...then provide the actual values that are the constituents of the pre-image of the _obfuscatedHash_ // during the reveal phase. struct Reveal { bytes32 overlay; address owner; uint8 depth; uint256 stake; uint256 stakeDensity; bytes32 hash; } struct ChunkInclusionProof { bytes32[] proofSegments; bytes32 proveSegment; // _RCspan is known for RC 32*32 // Inclusion proof of transformed address bytes32[] proofSegments2; bytes32 proveSegment2; // proveSegmentIndex2 known from deterministic random selection; uint64 chunkSpan; bytes32[] proofSegments3; // _proveSegment3 known, is equal _proveSegment2 // proveSegmentIndex3 know, is equal _proveSegmentIndex2; // chunkSpan2 is equal to chunkSpan (as the data is the same) // PostageProof postageProof; SOCProof[] socProof; } struct SOCProof { address signer; // signer Ethereum address to check against bytes signature; bytes32 identifier; // bytes32 chunkAddr; // wrapped chunk address } struct PostageProof { bytes signature; bytes32 postageId; uint64 index; uint64 timeStamp; // address signer; it is provided by the postage stamp contract // bytes32 chunkAddr; it equals to the proveSegment argument } // The address of the linked PostageStamp contract. IPostageStamp public PostageContract; // The address of the linked PriceOracle contract. IPriceOracle public OracleContract; // The address of the linked Staking contract. IStakeRegistry public Stakes; // Commits for the current round. Commit[] public currentCommits; // Reveals for the current round. Reveal[] public currentReveals; // The current anchor that being processed for the reveal and claim phases of the round. bytes32 private currentRevealRoundAnchor; // The current random value from which we will random. // inputs for selection of the truth teller and beneficiary. bytes32 private seed; // The number of the currently active round phases. uint64 public currentCommitRound; uint64 public currentRevealRound; uint64 public currentClaimRound; // Settings for slashing and freezing uint8 private penaltyMultiplierDisagreement = 1; uint8 private penaltyMultiplierNonRevealed = 2; uint8 private penaltyRandomFactor = 100; // Use 100 as value to ignore random factor in freezing penalty // alpha=0.097612 beta=0.0716570 k=16 uint256 private sampleMaxValue = 1284401000000000000000000000000000000000000000000000000000000000000000000; // The reveal of the winner of the last round. Reveal public winner; // The length of a round in blocks. uint256 private constant ROUND_LENGTH = 152; // Maximum value of the keccack256 hash. bytes32 private constant MAX_H = 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff; // ----------------------------- Events ------------------------------ /** * @dev Emitted when the winner of a round is selected in the claim phase */ event WinnerSelected(Reveal winner); /** * @dev Emitted when the truth oracle of a round is selected in the claim phase. */ event TruthSelected(bytes32 hash, uint8 depth); // Next two events to be removed after testing phase pending some other usefulness being found. /** * @dev Emits the number of commits being processed by the claim phase. */ event CountCommits(uint256 _count); /** * @dev Emits the number of reveals being processed by the claim phase. */ event CountReveals(uint256 _count); /** * @dev Logs that an overlay has committed */ event Committed(uint256 roundNumber, bytes32 overlay); /** * @dev Emit from Postagestamp contract valid chunk count at the end of claim */ event ChunkCount(uint256 validChunkCount); /** * @dev Bytes32 anhor of current reveal round */ event CurrentRevealAnchor(uint256 roundNumber, bytes32 anchor); /** * @dev Logs that an overlay has revealed */ event Revealed( uint256 roundNumber, bytes32 overlay, uint256 stake, uint256 stakeDensity, bytes32 reserveCommitment, uint8 depth ); /** * @dev Logs for inclusion proof */ event transformedChunkAddressFromInclusionProof(uint256 indexInRC, bytes32 chunkAddress); // ----------------------------- Errors ------------------------------ error NotCommitPhase(); // Game is not in commit phase error NoCommitsReceived(); // Round didn't receive any commits error PhaseLastBlock(); // We don't permit commits in last block of the phase error CommitRoundOver(); // Commit phase in this round is over error CommitRoundNotStarted(); // Commit phase in this round has not started yet error NotMatchingOwner(); // Sender of commit is not matching the overlay address error MustStake2Rounds(); // Before entering the game node must stake 2 rounds prior error NotStaked(); // Node didn't add any staking error WrongPhase(); // Checking in wrong phase, need to check duing claim phase of current round for next round or commit in current round error AlreadyCommitted(); // Node already committed in this round error NotRevealPhase(); // Game is not in reveal phase error OutOfDepthReveal(bytes32); // Anchor is out of reported depth in Reveal phase, anchor data available as argument error OutOfDepthClaim(uint8); // Anchor is out of reported depth in Claim phase, entryProof index is argument error OutOfDepth(); // Anchor is out of reported depth error AlreadyRevealed(); // Node already revealed error NoMatchingCommit(); // No matching commit and hash error NotClaimPhase(); // Game is not in the claim phase error NoReveals(); // Round did not receive any reveals error FirstRevealDone(); // We don't want to return value after first reveal error AlreadyClaimed(); // This round was already claimed error NotAdmin(); // Caller of trx is not admin error OnlyPauser(); // Only account with pauser role can call pause/unpause error SocVerificationFailed(bytes32); // Soc verification failed for this element error SocCalcNotMatching(bytes32); // Soc address calculation does not match with the witness error IndexOutsideSet(bytes32); // Stamp available: index resides outside of the valid index set error SigRecoveryFailed(bytes32); // Stamp authorized: signature recovery failed for element error BatchDoesNotExist(bytes32); // Stamp alive: batch remaining balance validation failed for attached stamp error BucketDiffers(bytes32); // Stamp aligned: postage bucket differs from address bucket error InclusionProofFailed(uint8, bytes32); // 1 = RC inclusion proof failed for element // 2 = First sister segment in data must match, // 3 = Inclusion proof failed for original address of element // 4 = Inclusion proof failed for transformed address of element error RandomElementCheckFailed(); // Random element order check failed error LastElementCheckFailed(); // Last element order check failed error ReserveCheckFailed(bytes32 trALast); // Reserve size estimation check failed // ----------------------------- CONSTRUCTOR ------------------------------ /** * @param staking the address of the linked Staking contract. * @param postageContract the address of the linked PostageStamp contract. * @param oracleContract the address of the linked PriceOracle contract. */ constructor(address staking, address postageContract, address oracleContract) { Stakes = IStakeRegistry(staking); PostageContract = IPostageStamp(postageContract); OracleContract = IPriceOracle(oracleContract); _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); } //////////////////////////////////////// // STATE CHANGING // //////////////////////////////////////// /** * @notice Begin application for a round if eligible. Commit a hashed value for which the pre-image will be * subsequently revealed. * @dev If a node's overlay is _inProximity_(_depth_) of the _currentRoundAnchor_, that node may compute an * _obfuscatedHash_ by providing their _overlay_, reported storage _depth_, reserve commitment _hash_ and a * randomly generated, and secret _revealNonce_ to the _wrapCommit_ method. * @param _obfuscatedHash The calculated hash resultant of the required pre-image values. * and be derived from the same key pair as the message sender. * @param _roundNumber Node needs to provide round number for which commit is valid */ function commit(bytes32 _obfuscatedHash, uint64 _roundNumber) external whenNotPaused { uint64 cr = currentRound(); bytes32 _overlay = Stakes.overlayOfAddress(msg.sender); uint256 _stake = Stakes.nodeEffectiveStake(msg.sender); uint256 _lastUpdate = Stakes.lastUpdatedBlockNumberOfAddress(msg.sender); if (!currentPhaseCommit()) { revert NotCommitPhase(); } if (block.number % ROUND_LENGTH == (ROUND_LENGTH / 4) - 1) { revert PhaseLastBlock(); } if (cr > _roundNumber) { revert CommitRoundOver(); } if (cr < _roundNumber) { revert CommitRoundNotStarted(); } if (_lastUpdate == 0) { revert NotStaked(); } if (_lastUpdate >= block.number - 2 * ROUND_LENGTH) { revert MustStake2Rounds(); } // if we are in a new commit phase, reset the array of commits and // set the currentCommitRound to be the current one if (cr != currentCommitRound) { delete currentCommits; currentCommitRound = cr; } uint256 commitsArrayLength = currentCommits.length; for (uint256 i = 0; i < commitsArrayLength; ) { if (currentCommits[i].overlay == _overlay) { revert AlreadyCommitted(); } unchecked { ++i; } } currentCommits.push( Commit({ overlay: _overlay, owner: msg.sender, revealed: false, stake: _stake, obfuscatedHash: _obfuscatedHash, revealIndex: 0 }) ); emit Committed(_roundNumber, _overlay); } /** * @notice Reveal the pre-image values used to generate commit provided during this round's commit phase. * @param _depth The reported depth. * @param _hash The reserve commitment hash. * @param _revealNonce The nonce used to generate the commit that is being revealed. */ function reveal(uint8 _depth, bytes32 _hash, bytes32 _revealNonce) external whenNotPaused { uint64 cr = currentRound(); bytes32 _overlay = Stakes.overlayOfAddress(msg.sender); if (_depth < currentMinimumDepth()) { revert OutOfDepth(); } if (!currentPhaseReveal()) { revert NotRevealPhase(); } if (cr != currentCommitRound) { revert NoCommitsReceived(); } if (cr != currentRevealRound) { currentRevealRoundAnchor = currentRoundAnchor(); delete currentReveals; // We set currentRevealRound ONLY after we set current anchor currentRevealRound = cr; emit CurrentRevealAnchor(cr, currentRevealRoundAnchor); updateRandomness(); } bytes32 obfuscatedHash = wrapCommit(_overlay, _depth, _hash, _revealNonce); uint256 id = findCommit(_overlay, obfuscatedHash); Commit memory revealedCommit = currentCommits[id]; // Check that commit is in proximity of the current anchor if (!inProximity(revealedCommit.overlay, currentRevealRoundAnchor, _depth)) { revert OutOfDepthReveal(currentRevealRoundAnchor); } // Check that the commit has not already been revealed if (revealedCommit.revealed) { revert AlreadyRevealed(); } currentCommits[id].revealed = true; currentCommits[id].revealIndex = currentReveals.length; currentReveals.push( Reveal({ overlay: revealedCommit.overlay, owner: revealedCommit.owner, depth: _depth, stake: revealedCommit.stake, stakeDensity: revealedCommit.stake * uint256(2 ** _depth), hash: _hash }) ); emit Revealed( cr, revealedCommit.overlay, revealedCommit.stake, revealedCommit.stake * uint256(2 ** _depth), _hash, _depth ); } /** * @notice Helper function to get this round truth * @dev */ function claim( ChunkInclusionProof calldata entryProof1, ChunkInclusionProof calldata entryProof2, ChunkInclusionProof calldata entryProofLast ) external whenNotPaused { winnerSelection(); Reveal memory winnerSelected = winner; uint256 indexInRC1; uint256 indexInRC2; bytes32 _currentRevealRoundAnchor = currentRevealRoundAnchor; bytes32 _seed = seed; // rand(14) indexInRC1 = uint256(_seed) % 15; // rand(13) indexInRC2 = uint256(_seed) % 14; if (indexInRC2 >= indexInRC1) { indexInRC2++; } if (!inProximity(entryProofLast.proveSegment, _currentRevealRoundAnchor, winnerSelected.depth)) { revert OutOfDepthClaim(3); } inclusionFunction(entryProofLast, 30); stampFunction(entryProofLast); socFunction(entryProofLast); if (!inProximity(entryProof1.proveSegment, _currentRevealRoundAnchor, winnerSelected.depth)) { revert OutOfDepthClaim(2); } inclusionFunction(entryProof1, indexInRC1 * 2); stampFunction(entryProof1); socFunction(entryProof1); if (!inProximity(entryProof2.proveSegment, _currentRevealRoundAnchor, winnerSelected.depth)) { revert OutOfDepthClaim(1); } inclusionFunction(entryProof2, indexInRC2 * 2); stampFunction(entryProof2); socFunction(entryProof2); checkOrder( indexInRC1, indexInRC2, entryProof1.proofSegments[0], entryProof2.proofSegments[0], entryProofLast.proofSegments[0] ); estimateSize(entryProofLast.proofSegments[0]); PostageContract.withdraw(winnerSelected.owner); emit WinnerSelected(winnerSelected); emit ChunkCount(PostageContract.validChunkCount()); } function winnerSelection() internal { uint64 cr = currentRound(); if (!currentPhaseClaim()) { revert NotClaimPhase(); } if (cr != currentRevealRound) { revert NoReveals(); } if (cr <= currentClaimRound) { revert AlreadyClaimed(); } uint256 currentWinnerSelectionSum = 0; uint256 redundancyCount = 0; bytes32 randomNumber; uint256 randomNumberTrunc; bytes32 truthRevealedHash; uint8 truthRevealedDepth; uint256 currentCommitsLength = currentCommits.length; emit CountCommits(currentCommitsLength); emit CountReveals(currentReveals.length); (truthRevealedHash, truthRevealedDepth) = getCurrentTruth(); emit TruthSelected(truthRevealedHash, truthRevealedDepth); string memory winnerSelectionAnchor = currentWinnerSelectionAnchor(); for (uint256 i = 0; i < currentCommitsLength; ) { Commit memory currentCommit = currentCommits[i]; uint256 revIndex = currentCommit.revealIndex; Reveal memory currentReveal = currentReveals[revIndex]; // Select winner with valid truth if ( currentCommit.revealed && truthRevealedHash == currentReveal.hash && truthRevealedDepth == currentReveal.depth ) { currentWinnerSelectionSum += currentReveal.stakeDensity; randomNumber = keccak256(abi.encodePacked(winnerSelectionAnchor, redundancyCount)); randomNumberTrunc = uint256(randomNumber & MAX_H); if (randomNumberTrunc * currentWinnerSelectionSum < currentReveal.stakeDensity * (uint256(MAX_H) + 1)) { winner = currentReveal; } redundancyCount++; } // Freeze deposit if any truth is false, make it a penaltyRandomFactor chance for this to happen if ( currentCommit.revealed && (truthRevealedHash != currentReveal.hash || truthRevealedDepth != currentReveal.depth) && (block.prevrandao % 100 < penaltyRandomFactor) ) { Stakes.freezeDeposit( currentReveal.owner, penaltyMultiplierDisagreement * ROUND_LENGTH * uint256(2 ** truthRevealedDepth) ); } // Slash deposits if revealed is false if (!currentCommit.revealed) { // slash in later phase (ph5) // Stakes.slashDeposit(currentCommits[i].overlay, currentCommits[i].stake); Stakes.freezeDeposit( currentCommit.owner, penaltyMultiplierNonRevealed * ROUND_LENGTH * uint256(2 ** truthRevealedDepth) ); } unchecked { ++i; } } OracleContract.adjustPrice(uint16(redundancyCount)); currentClaimRound = cr; } function inclusionFunction(ChunkInclusionProof calldata entryProof, uint256 indexInRC) internal { uint256 randomChunkSegmentIndex = uint256(seed) % 128; bytes32 calculatedTransformedAddr = TransformedBMTChunk.transformedChunkAddressFromInclusionProof( entryProof.proofSegments3, entryProof.proveSegment2, randomChunkSegmentIndex, entryProof.chunkSpan, currentRevealRoundAnchor ); emit transformedChunkAddressFromInclusionProof(indexInRC, calculatedTransformedAddr); if ( winner.hash != BMTChunk.chunkAddressFromInclusionProof( entryProof.proofSegments, entryProof.proveSegment, indexInRC, 32 * 32 ) ) { revert InclusionProofFailed(1, calculatedTransformedAddr); } if (entryProof.proofSegments2[0] != entryProof.proofSegments3[0]) { revert InclusionProofFailed(2, calculatedTransformedAddr); } bytes32 originalAddress = entryProof.socProof.length > 0 ? entryProof.socProof[0].chunkAddr // soc attestation in socFunction : entryProof.proveSegment; if ( originalAddress != BMTChunk.chunkAddressFromInclusionProof( entryProof.proofSegments2, entryProof.proveSegment2, randomChunkSegmentIndex, entryProof.chunkSpan ) ) { revert InclusionProofFailed(3, calculatedTransformedAddr); } // In case of SOC, the transformed address is hashed together with its address in the sample if (entryProof.socProof.length > 0) { calculatedTransformedAddr = keccak256( abi.encode( entryProof.proveSegment, // SOC address calculatedTransformedAddr ) ); } if (entryProof.proofSegments[0] != calculatedTransformedAddr) { revert InclusionProofFailed(4, calculatedTransformedAddr); } } /** * @notice Set freezing parameters */ function setFreezingParams( uint8 _penaltyMultiplierDisagreement, uint8 _penaltyMultiplierNonRevealed, uint8 _penaltyRandomFactor ) external { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) { revert NotAdmin(); } penaltyMultiplierDisagreement = _penaltyMultiplierDisagreement; penaltyMultiplierNonRevealed = _penaltyMultiplierNonRevealed; penaltyRandomFactor = _penaltyRandomFactor; } /** * @notice changes the max sample value used for reserve estimation */ function setSampleMaxValue(uint256 _sampleMaxValue) external { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) { revert NotAdmin(); } sampleMaxValue = _sampleMaxValue; } /** * @notice Updates the source of randomness. Uses block.difficulty in pre-merge chains, this is substituted * to block.prevrandao in post merge chains. */ function updateRandomness() private { seed = keccak256(abi.encode(seed, block.prevrandao)); } /** * @dev Pause the contract. The contract is provably stopped by renouncing the pauser role and the admin role after pausing, can only be called by the `PAUSER` */ function pause() public { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) { revert OnlyPauser(); } _pause(); } /** * @dev Unpause the contract, can only be called by the pauser when paused */ function unPause() public { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) { revert OnlyPauser(); } _unpause(); } //////////////////////////////////////// // STATE READING // //////////////////////////////////////// // ----------------------------- Anchor calculations ------------------------------ /** * @notice Returns the current random seed which is used to determine later utilised random numbers. * If rounds have elapsed without reveals, hash the seed with an incremented nonce to produce a new * random seed and hence a new round anchor. */ function currentSeed() public view returns (bytes32) { uint64 cr = currentRound(); bytes32 currentSeedValue = seed; if (cr > currentRevealRound + 1) { uint256 difference = cr - currentRevealRound - 1; currentSeedValue = keccak256(abi.encodePacked(currentSeedValue, difference)); } return currentSeedValue; } /** * @notice Returns the seed which will become current once the next commit phase begins. * Used to determine what the next round's anchor will be. */ function nextSeed() public view returns (bytes32) { uint64 cr = currentRound() + 1; bytes32 currentSeedValue = seed; if (cr > currentRevealRound + 1) { uint256 difference = cr - currentRevealRound - 1; currentSeedValue = keccak256(abi.encodePacked(currentSeedValue, difference)); } return currentSeedValue; } /** * @notice The random value used to choose the selected truth teller. */ function currentTruthSelectionAnchor() private view returns (string memory) { if (!currentPhaseClaim()) { revert NotClaimPhase(); } uint64 cr = currentRound(); if (cr != currentRevealRound) { revert NoReveals(); } return string(abi.encodePacked(seed, "0")); } /** * @notice The random value used to choose the selected beneficiary. */ function currentWinnerSelectionAnchor() private view returns (string memory) { if (!currentPhaseClaim()) { revert NotClaimPhase(); } uint64 cr = currentRound(); if (cr != currentRevealRound) { revert NoReveals(); } return string(abi.encodePacked(seed, "1")); } /** * @notice The anchor used to determine eligibility for the current round. * @dev A node must be within proximity order of less than or equal to the storage depth they intend to report. */ function currentRoundAnchor() public view returns (bytes32 returnVal) { // This will be called in reveal phase and set as currentRevealRoundAnchor or in // commit phase when checking eligibility for next round by isParticipatingInUpcomingRound if (currentPhaseCommit() || (currentRound() > currentRevealRound && !currentPhaseClaim())) { return currentSeed(); } // This will be called by isParticipatingInUpcomingRound check in claim phase if (currentPhaseClaim()) { return nextSeed(); } // Without this, this function will output 0x0 after first reveal which is value and we prefere it reverts if (currentPhaseReveal() && currentRound() == currentRevealRound) { revert FirstRevealDone(); } } /** * @notice Returns true if an overlay address _A_ is within proximity order _minimum_ of _B_. * @param A An overlay address to compare. * @param B An overlay address to compare. * @param minimum Minimum proximity order. */ function inProximity(bytes32 A, bytes32 B, uint8 minimum) public pure returns (bool) { if (minimum == 0) { return true; } return uint256(A ^ B) < uint256(2 ** (256 - minimum)); } // ----------------------------- Commit ------------------------------ /** * @notice The number of the current round. */ function currentRound() public view returns (uint64) { return uint64(block.number / ROUND_LENGTH); } /** * @notice Returns true if current block is during commit phase. */ function currentPhaseCommit() public view returns (bool) { if (block.number % ROUND_LENGTH < ROUND_LENGTH / 4) { return true; } return false; } /** * @notice Determine if a the owner of a given overlay can participate in the upcoming round. * @param _owner The address of the applicant from. * @param _depth The storage depth the applicant intends to report. */ function isParticipatingInUpcomingRound(address _owner, uint8 _depth) public view returns (bool) { uint256 _lastUpdate = Stakes.lastUpdatedBlockNumberOfAddress(_owner); if (currentPhaseReveal()) { revert WrongPhase(); } if (_lastUpdate == 0) { revert NotStaked(); } if (_lastUpdate >= block.number - 2 * ROUND_LENGTH) { revert MustStake2Rounds(); } return inProximity(Stakes.overlayOfAddress(_owner), currentRoundAnchor(), _depth); } // ----------------------------- Reveal ------------------------------ /** * @notice Returns minimum depth reveal has to have to participate in this round */ function currentMinimumDepth() public view returns (uint8) { // We are checking value in reveal phase, as the currentCommitRound is set to the current round // but the currentClaimRound is still set to the last time claim was made // We add 1 to ensure that for the next round the minimum depth is the same as last winner depth uint256 difference = currentCommitRound - currentClaimRound; uint8 skippedRounds = uint8(difference > 254 ? 254 : difference) + 1; uint8 lastWinnerDepth = winner.depth; // We ensure that skippedRounds is not bigger than lastWinnerDepth, because of overflow return skippedRounds >= lastWinnerDepth ? 0 : lastWinnerDepth - skippedRounds; } /** * @notice Helper function to get this node reveal in commits * @dev */ function findCommit(bytes32 _overlay, bytes32 _obfuscatedHash) internal view returns (uint256) { for (uint256 i = 0; i < currentCommits.length; ) { if (currentCommits[i].overlay == _overlay && _obfuscatedHash == currentCommits[i].obfuscatedHash) { return i; } unchecked { ++i; } } revert NoMatchingCommit(); } /** * @notice Hash the pre-image values to the obsfucated hash. * @dev _revealNonce_ must be randomly generated, used once and kept secret until the reveal phase. * @param _overlay The overlay address of the applicant. * @param _depth The reported depth. * @param _hash The reserve commitment hash. * @param revealNonce A random, single use, secret nonce. */ function wrapCommit( bytes32 _overlay, uint8 _depth, bytes32 _hash, bytes32 revealNonce ) public pure returns (bytes32) { return keccak256(abi.encodePacked(_overlay, _depth, _hash, revealNonce)); } /** * @notice Returns true if current block is during reveal phase. */ function currentPhaseReveal() public view returns (bool) { uint256 number = block.number % ROUND_LENGTH; if (number >= ROUND_LENGTH / 4 && number < ROUND_LENGTH / 2) { return true; } return false; } /** * @notice Returns true if current block is during reveal phase. */ function currentRoundReveals() public view returns (Reveal[] memory) { if (!currentPhaseClaim()) { revert NotClaimPhase(); } uint64 cr = currentRound(); if (cr != currentRevealRound) { revert NoReveals(); } return currentReveals; } // ----------------------------- Claim ------------------------------ /** * @notice Returns true if current block is during claim phase. */ function currentPhaseClaim() public view returns (bool) { if (block.number % ROUND_LENGTH >= ROUND_LENGTH / 2) { return true; } return false; } function getCurrentTruth() internal view returns (bytes32 Hash, uint8 Depth) { uint256 currentSum; bytes32 randomNumber; uint256 randomNumberTrunc; bytes32 truthRevealedHash; uint8 truthRevealedDepth; uint256 revIndex; string memory truthSelectionAnchor = currentTruthSelectionAnchor(); uint256 commitsArrayLength = currentCommits.length; for (uint256 i = 0; i < commitsArrayLength; ) { if (currentCommits[i].revealed) { revIndex = currentCommits[i].revealIndex; currentSum += currentReveals[revIndex].stakeDensity; randomNumber = keccak256(abi.encodePacked(truthSelectionAnchor, i)); randomNumberTrunc = uint256(randomNumber & MAX_H); // question is whether randomNumber / MAX_H < probability // where probability is stakeDensity / currentSum // to avoid resorting to floating points all divisions should be // simplified with multiplying both sides (as long as divisor > 0) // randomNumber / (MAX_H + 1) < stakeDensity / currentSum // ( randomNumber / (MAX_H + 1) ) * currentSum < stakeDensity // randomNumber * currentSum < stakeDensity * (MAX_H + 1) if (randomNumberTrunc * currentSum < currentReveals[revIndex].stakeDensity * (uint256(MAX_H) + 1)) { truthRevealedHash = currentReveals[revIndex].hash; truthRevealedDepth = currentReveals[revIndex].depth; } } unchecked { ++i; } } return (truthRevealedHash, truthRevealedDepth); } /** * @notice Determine if a the owner of a given overlay will be the beneficiary of the claim phase. * @param _overlay The overlay address of the applicant. */ function isWinner(bytes32 _overlay) public view returns (bool) { if (!currentPhaseClaim()) { revert NotClaimPhase(); } uint64 cr = currentRound(); if (cr != currentRevealRound) { revert NoReveals(); } if (cr <= currentClaimRound) { revert AlreadyClaimed(); } uint256 currentWinnerSelectionSum; bytes32 winnerIs; bytes32 randomNumber; uint256 randomNumberTrunc; bytes32 truthRevealedHash; uint8 truthRevealedDepth; uint256 revIndex; string memory winnerSelectionAnchor = currentWinnerSelectionAnchor(); uint256 redundancyCount = 0; // Get current truth (truthRevealedHash, truthRevealedDepth) = getCurrentTruth(); uint256 commitsArrayLength = currentCommits.length; for (uint256 i = 0; i < commitsArrayLength; ) { revIndex = currentCommits[i].revealIndex; // Deterministically read winner if ( currentCommits[i].revealed && truthRevealedHash == currentReveals[revIndex].hash && truthRevealedDepth == currentReveals[revIndex].depth ) { currentWinnerSelectionSum += currentReveals[revIndex].stakeDensity; randomNumber = keccak256(abi.encodePacked(winnerSelectionAnchor, redundancyCount)); randomNumberTrunc = uint256(randomNumber & MAX_H); if ( randomNumberTrunc * currentWinnerSelectionSum < currentReveals[revIndex].stakeDensity * (uint256(MAX_H) + 1) ) { winnerIs = currentReveals[revIndex].overlay; } redundancyCount++; } unchecked { ++i; } } return (winnerIs == _overlay); } // ----------------------------- Claim verifications ------------------------------ function socFunction(ChunkInclusionProof calldata entryProof) internal pure { if (entryProof.socProof.length == 0) return; if ( !Signatures.socVerify( entryProof.socProof[0].signer, // signer Ethereum address to check against entryProof.socProof[0].signature, entryProof.socProof[0].identifier, entryProof.socProof[0].chunkAddr ) ) { revert SocVerificationFailed(entryProof.socProof[0].chunkAddr); } if ( calculateSocAddress(entryProof.socProof[0].identifier, entryProof.socProof[0].signer) != entryProof.proveSegment ) { revert SocCalcNotMatching(entryProof.socProof[0].chunkAddr); } } function stampFunction(ChunkInclusionProof calldata entryProof) internal view { // authentic (address batchOwner, uint8 batchDepth, uint8 bucketDepth, , , ) = PostageContract.batches( entryProof.postageProof.postageId ); // alive if (batchOwner == address(0)) { revert BatchDoesNotExist(entryProof.postageProof.postageId); // Batch does not exist or expired } uint32 postageIndex = getPostageIndex(entryProof.postageProof.index); uint256 maxPostageIndex = postageStampIndexCount(batchDepth, bucketDepth); // available if (postageIndex >= maxPostageIndex) { revert IndexOutsideSet(entryProof.postageProof.postageId); } // aligned uint64 postageBucket = getPostageBucket(entryProof.postageProof.index); uint64 addressBucket = addressToBucket(entryProof.proveSegment, bucketDepth); if (postageBucket != addressBucket) { revert BucketDiffers(entryProof.postageProof.postageId); } // authorized if ( !Signatures.postageVerify( batchOwner, entryProof.postageProof.signature, entryProof.proveSegment, entryProof.postageProof.postageId, entryProof.postageProof.index, entryProof.postageProof.timeStamp ) ) { revert SigRecoveryFailed(entryProof.postageProof.postageId); } } function addressToBucket(bytes32 swarmAddress, uint8 bucketDepth) internal pure returns (uint32) { uint32 prefix = uint32(uint256(swarmAddress) >> (256 - 32)); return prefix >> (32 - bucketDepth); } function postageStampIndexCount(uint8 postageDepth, uint8 bucketDepth) internal pure returns (uint256) { return 1 << (postageDepth - bucketDepth); } function getPostageIndex(uint64 signedIndex) internal pure returns (uint32) { return uint32(signedIndex); } function getPostageBucket(uint64 signedIndex) internal pure returns (uint64) { return uint32(signedIndex >> 32); } function calculateSocAddress(bytes32 identifier, address signer) internal pure returns (bytes32) { return keccak256(abi.encodePacked(identifier, signer)); } function checkOrder(uint256 a, uint256 b, bytes32 trA1, bytes32 trA2, bytes32 trALast) internal pure { if (a < b) { if (uint256(trA1) >= uint256(trA2)) { revert RandomElementCheckFailed(); } if (uint256(trA2) >= uint256(trALast)) { revert LastElementCheckFailed(); } } else { if (uint256(trA2) >= uint256(trA1)) { revert RandomElementCheckFailed(); } if (uint256(trA1) >= uint256(trALast)) { revert LastElementCheckFailed(); } } } function estimateSize(bytes32 trALast) internal view { if (uint256(trALast) >= sampleMaxValue) { revert ReserveCheckFailed(trALast); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(account), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * May emit a {RoleGranted} event. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: BSD-3-Clause pragma solidity ^0.8.19; interface IPostageStamp { function withdraw(address beneficiary) external; function validChunkCount() external view returns (uint256); function batchOwner(bytes32 _batchId) external view returns (address); function batchDepth(bytes32 _batchId) external view returns (uint8); function batchBucketDepth(bytes32 _batchId) external view returns (uint8); function remainingBalance(bytes32 _batchId) external view returns (uint256); function minimumInitialBalancePerChunk() external view returns (uint256); function setPrice(uint256 _price) external; function batches( bytes32 ) external view returns ( address owner, uint8 depth, uint8 bucketDepth, bool immutableFlag, uint256 normalisedBalance, uint256 lastUpdatedBlockNumber ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; library BMTChunk { // max chunk payload size uint256 public constant MAX_CHUNK_PAYLOAD_SIZE = 4096; // segment byte size uint256 public constant SEGMENT_SIZE = 32; /** * @notice Changes the endianness of a uint64. * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel * @param _b The unsigned integer to reverse * @return v - The reversed value */ function reverseUint64(uint64 _b) public pure returns (uint64) { uint256 v = _b; // swap bytes v = ((v >> 8) & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) | ((v & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) << 8); // swap 2-byte long pairs v = ((v >> 16) & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) | ((v & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) << 16); // swap 4-byte long pairs v = ((v >> 32) & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) | ((v & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) << 32); return uint64(v); } /** Calculates the root hash from the provided inclusion proof segments and its corresponding segment index * @param _proofSegments Proof segments. * @param _proveSegment Segment to prove. * @param _proveSegmentIndex Prove segment index * @return _calculatedHash chunk hash */ function rootHashFromInclusionProof( bytes32[] memory _proofSegments, bytes32 _proveSegment, uint256 _proveSegmentIndex ) internal pure returns (bytes32 _calculatedHash) { _calculatedHash = _proveSegment; for (uint256 i = 0; i < _proofSegments.length; i++) { bool mergeFromRight = _proveSegmentIndex % 2 == 0; _calculatedHash = mergeSegment(_calculatedHash, _proofSegments[i], mergeFromRight); _proveSegmentIndex >>= 1; } return _calculatedHash; } /** * Calculate the chunk address from the Binary Merkle Tree of the chunk data * * The BMT chunk address is the hash of the 8 byte span and the root * hash of a binary Merkle tree (BMT) built on the 32-byte segments * of the underlying data. * @param _proofSegments Proof segments. * @param _proveSegment Segment to prove. * @param _proveSegmentIndex Prove segment index * @param _chunkSpan chunk bytes length * @return _chunkHash chunk hash */ function chunkAddressFromInclusionProof( bytes32[] memory _proofSegments, bytes32 _proveSegment, uint256 _proveSegmentIndex, uint64 _chunkSpan ) internal pure returns (bytes32) { bytes32 rootHash = rootHashFromInclusionProof(_proofSegments, _proveSegment, _proveSegmentIndex); return keccak256(abi.encodePacked(reverseUint64(_chunkSpan), rootHash)); } function mergeSegment( bytes32 _calculatedHash, bytes32 _proofSegment, bool mergeFromRight ) internal pure returns (bytes32 res) { if (mergeFromRight) { res = keccak256(abi.encode(_calculatedHash, _proofSegment)); } else { res = keccak256(abi.encode(_proofSegment, _calculatedHash)); } return res; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; library Signatures { error InvalidSignatureLength(); /** Hash of the message to sign */ function getPostageMessageHash( bytes32 _chunkAddr, bytes32 _batchId, uint64 _index, uint64 _timeStamp ) internal pure returns (bytes32) { return keccak256(abi.encodePacked(_chunkAddr, _batchId, _index, _timeStamp)); } function postageVerify( address _signer, // signer Ethereum address to check against bytes memory _signature, bytes32 _chunkAddr, bytes32 _postageId, uint64 _index, uint64 _timeStamp ) internal pure returns (bool) { bytes32 messageHash = getPostageMessageHash(_chunkAddr, _postageId, _index, _timeStamp); bytes32 ethMessageHash = getEthSignedMessageHash(messageHash); return recoverSigner(ethMessageHash, _signature) == _signer; } function getEthSignedMessageHash(bytes32 _messageHash) internal pure returns (bytes32) { /* Signature is produced by signing a keccak256 hash with the following format: "\x19Ethereum Signed Message\n" + len(msg) + msg */ return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _messageHash)); } function recoverSigner( bytes32 _ethSignedMessageHash, // it has to be prefixed message: https://ethereum.stackexchange.com/questions/19582/does-ecrecover-in-solidity-expects-the-x19ethereum-signed-message-n-prefix/21037 bytes memory _signature ) internal pure returns (address) { (bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature); return ecrecover(_ethSignedMessageHash, v, r, s); } function splitSignature(bytes memory sig) internal pure returns (bytes32 r_, bytes32 s_, uint8 v_) { if (sig.length != 65) { revert InvalidSignatureLength(); } assembly { /* verbose explanation: https://ethereum.stackexchange.com/questions/135591/split-signature-function-in-solidity-by-example-docs First 32 bytes stores the length of the signature add(sig, 32) = pointer of sig + 32 effectively, skips first 32 bytes of signature mload(p) loads next 32 bytes starting at the memory address p into memory */ // first 32 bytes, after the length prefix r_ := mload(add(sig, 32)) // second 32 bytes s_ := mload(add(sig, 64)) // final byte (first byte of the next 32 bytes) v_ := byte(0, mload(add(sig, 96))) } // implicitly return (r, s, v) } function getSocMessageHash(bytes32 _identifier, bytes32 _chunkAddr) internal pure returns (bytes32) { return keccak256(abi.encodePacked(_identifier, _chunkAddr)); } function socVerify( address _signer, // signer Ethereum address to check against bytes memory _signature, bytes32 _identifier, bytes32 _chunkAddr ) internal pure returns (bool) { bytes32 messageHash = getSocMessageHash(_identifier, _chunkAddr); bytes32 ethMessageHash = getEthSignedMessageHash(messageHash); return recoverSigner(ethMessageHash, _signature) == _signer; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; library TransformedBMTChunk { // max chunk payload size uint256 public constant MAX_CHUNK_PAYLOAD_SIZE = 4096; // segment byte size uint256 public constant SEGMENT_SIZE = 32; /** Calculates the root hash from the provided inclusion proof segments and its corresponding segment index * @param _proofSegments Proof segments. * @param _proveSegment Segment to prove. * @param _proveSegmentIndex Prove segment index * @return _calculatedHash chunk hash */ function transformedRootHashFromInclusionProof( bytes32[] memory _proofSegments, bytes32 _proveSegment, uint256 _proveSegmentIndex, bytes32 key ) internal pure returns (bytes32 _calculatedHash) { _calculatedHash = _proveSegment; for (uint256 i = 0; i < _proofSegments.length; i++) { bool mergeFromRight = _proveSegmentIndex % 2 == 0 ? true : false; _calculatedHash = transformedMergeSegment(_calculatedHash, _proofSegments[i], mergeFromRight, key); _proveSegmentIndex >>= 1; } return _calculatedHash; } /** * @notice Changes the endianness of a uint64. * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel * @param _b The unsigned integer to reverse * @return v - The reversed value */ function reverseUint64(uint64 _b) public pure returns (uint64) { uint256 v = _b; // swap bytes v = ((v >> 8) & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) | ((v & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) << 8); // swap 2-byte long pairs v = ((v >> 16) & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) | ((v & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) << 16); // swap 4-byte long pairs v = ((v >> 32) & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) | ((v & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) << 32); return uint64(v); } /** * Calculate the chunk address from the Binary Merkle Tree of the chunk data * * The BMT chunk address is the hash of the 8 byte span and the root * hash of a binary Merkle tree (BMT) built on the 32-byte segments * of the underlying data. * @param _proofSegments Proof segments. * @param _proveSegment Segment to prove. * @param _proveSegmentIndex Prove segment index * @param _chunkSpan chunk bytes length * @return _chunkHash chunk hash */ function transformedChunkAddressFromInclusionProof( bytes32[] memory _proofSegments, bytes32 _proveSegment, uint256 _proveSegmentIndex, uint64 _chunkSpan, bytes32 key ) internal pure returns (bytes32) { bytes32 rootHash = transformedRootHashFromInclusionProof( _proofSegments, _proveSegment, _proveSegmentIndex, key ); return keccak256(abi.encodePacked(key, reverseUint64(_chunkSpan), rootHash)); } function transformedMergeSegment( bytes32 _calculatedHash, bytes32 _proofSegment, bool mergeFromRight, bytes32 key ) internal pure returns (bytes32 res) { if (mergeFromRight) { res = keccak256(abi.encode(key, _calculatedHash, _proofSegment)); } else { res = keccak256(abi.encode(key, _proofSegment, _calculatedHash)); } return res; } }
{ "optimizer": { "enabled": true, "runs": 1000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"staking","type":"address"},{"internalType":"address","name":"postageContract","type":"address"},{"internalType":"address","name":"oracleContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyClaimed","type":"error"},{"inputs":[],"name":"AlreadyCommitted","type":"error"},{"inputs":[],"name":"AlreadyRevealed","type":"error"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"BatchDoesNotExist","type":"error"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"BucketDiffers","type":"error"},{"inputs":[],"name":"CommitRoundNotStarted","type":"error"},{"inputs":[],"name":"CommitRoundOver","type":"error"},{"inputs":[],"name":"FirstRevealDone","type":"error"},{"inputs":[{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"InclusionProofFailed","type":"error"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"IndexOutsideSet","type":"error"},{"inputs":[],"name":"InvalidSignatureLength","type":"error"},{"inputs":[],"name":"LastElementCheckFailed","type":"error"},{"inputs":[],"name":"MustStake2Rounds","type":"error"},{"inputs":[],"name":"NoCommitsReceived","type":"error"},{"inputs":[],"name":"NoMatchingCommit","type":"error"},{"inputs":[],"name":"NoReveals","type":"error"},{"inputs":[],"name":"NotAdmin","type":"error"},{"inputs":[],"name":"NotClaimPhase","type":"error"},{"inputs":[],"name":"NotCommitPhase","type":"error"},{"inputs":[],"name":"NotMatchingOwner","type":"error"},{"inputs":[],"name":"NotRevealPhase","type":"error"},{"inputs":[],"name":"NotStaked","type":"error"},{"inputs":[],"name":"OnlyPauser","type":"error"},{"inputs":[],"name":"OutOfDepth","type":"error"},{"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"OutOfDepthClaim","type":"error"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"OutOfDepthReveal","type":"error"},{"inputs":[],"name":"PhaseLastBlock","type":"error"},{"inputs":[],"name":"RandomElementCheckFailed","type":"error"},{"inputs":[{"internalType":"bytes32","name":"trALast","type":"bytes32"}],"name":"ReserveCheckFailed","type":"error"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"SigRecoveryFailed","type":"error"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"SocCalcNotMatching","type":"error"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"SocVerificationFailed","type":"error"},{"inputs":[],"name":"WrongPhase","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"validChunkCount","type":"uint256"}],"name":"ChunkCount","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"roundNumber","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"overlay","type":"bytes32"}],"name":"Committed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_count","type":"uint256"}],"name":"CountCommits","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_count","type":"uint256"}],"name":"CountReveals","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"roundNumber","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"anchor","type":"bytes32"}],"name":"CurrentRevealAnchor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"roundNumber","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"overlay","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"stake","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakeDensity","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"reserveCommitment","type":"bytes32"},{"indexed":false,"internalType":"uint8","name":"depth","type":"uint8"}],"name":"Revealed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"},{"indexed":false,"internalType":"uint8","name":"depth","type":"uint8"}],"name":"TruthSelected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"bytes32","name":"overlay","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint8","name":"depth","type":"uint8"},{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"stakeDensity","type":"uint256"},{"internalType":"bytes32","name":"hash","type":"bytes32"}],"indexed":false,"internalType":"struct Redistribution.Reveal","name":"winner","type":"tuple"}],"name":"WinnerSelected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"indexInRC","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"chunkAddress","type":"bytes32"}],"name":"transformedChunkAddressFromInclusionProof","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OracleContract","outputs":[{"internalType":"contract IPriceOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PostageContract","outputs":[{"internalType":"contract IPostageStamp","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"Stakes","outputs":[{"internalType":"contract IStakeRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32[]","name":"proofSegments","type":"bytes32[]"},{"internalType":"bytes32","name":"proveSegment","type":"bytes32"},{"internalType":"bytes32[]","name":"proofSegments2","type":"bytes32[]"},{"internalType":"bytes32","name":"proveSegment2","type":"bytes32"},{"internalType":"uint64","name":"chunkSpan","type":"uint64"},{"internalType":"bytes32[]","name":"proofSegments3","type":"bytes32[]"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32","name":"postageId","type":"bytes32"},{"internalType":"uint64","name":"index","type":"uint64"},{"internalType":"uint64","name":"timeStamp","type":"uint64"}],"internalType":"struct Redistribution.PostageProof","name":"postageProof","type":"tuple"},{"components":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"bytes32","name":"chunkAddr","type":"bytes32"}],"internalType":"struct Redistribution.SOCProof[]","name":"socProof","type":"tuple[]"}],"internalType":"struct Redistribution.ChunkInclusionProof","name":"entryProof1","type":"tuple"},{"components":[{"internalType":"bytes32[]","name":"proofSegments","type":"bytes32[]"},{"internalType":"bytes32","name":"proveSegment","type":"bytes32"},{"internalType":"bytes32[]","name":"proofSegments2","type":"bytes32[]"},{"internalType":"bytes32","name":"proveSegment2","type":"bytes32"},{"internalType":"uint64","name":"chunkSpan","type":"uint64"},{"internalType":"bytes32[]","name":"proofSegments3","type":"bytes32[]"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32","name":"postageId","type":"bytes32"},{"internalType":"uint64","name":"index","type":"uint64"},{"internalType":"uint64","name":"timeStamp","type":"uint64"}],"internalType":"struct Redistribution.PostageProof","name":"postageProof","type":"tuple"},{"components":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"bytes32","name":"chunkAddr","type":"bytes32"}],"internalType":"struct Redistribution.SOCProof[]","name":"socProof","type":"tuple[]"}],"internalType":"struct Redistribution.ChunkInclusionProof","name":"entryProof2","type":"tuple"},{"components":[{"internalType":"bytes32[]","name":"proofSegments","type":"bytes32[]"},{"internalType":"bytes32","name":"proveSegment","type":"bytes32"},{"internalType":"bytes32[]","name":"proofSegments2","type":"bytes32[]"},{"internalType":"bytes32","name":"proveSegment2","type":"bytes32"},{"internalType":"uint64","name":"chunkSpan","type":"uint64"},{"internalType":"bytes32[]","name":"proofSegments3","type":"bytes32[]"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32","name":"postageId","type":"bytes32"},{"internalType":"uint64","name":"index","type":"uint64"},{"internalType":"uint64","name":"timeStamp","type":"uint64"}],"internalType":"struct Redistribution.PostageProof","name":"postageProof","type":"tuple"},{"components":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"bytes32","name":"chunkAddr","type":"bytes32"}],"internalType":"struct Redistribution.SOCProof[]","name":"socProof","type":"tuple[]"}],"internalType":"struct Redistribution.ChunkInclusionProof","name":"entryProofLast","type":"tuple"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_obfuscatedHash","type":"bytes32"},{"internalType":"uint64","name":"_roundNumber","type":"uint64"}],"name":"commit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentClaimRound","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentCommitRound","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"currentCommits","outputs":[{"internalType":"bytes32","name":"overlay","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"revealed","type":"bool"},{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"bytes32","name":"obfuscatedHash","type":"bytes32"},{"internalType":"uint256","name":"revealIndex","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentMinimumDepth","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentPhaseClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentPhaseCommit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentPhaseReveal","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentRevealRound","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"currentReveals","outputs":[{"internalType":"bytes32","name":"overlay","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint8","name":"depth","type":"uint8"},{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"stakeDensity","type":"uint256"},{"internalType":"bytes32","name":"hash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentRound","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentRoundAnchor","outputs":[{"internalType":"bytes32","name":"returnVal","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentRoundReveals","outputs":[{"components":[{"internalType":"bytes32","name":"overlay","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint8","name":"depth","type":"uint8"},{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"stakeDensity","type":"uint256"},{"internalType":"bytes32","name":"hash","type":"bytes32"}],"internalType":"struct Redistribution.Reveal[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentSeed","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"A","type":"bytes32"},{"internalType":"bytes32","name":"B","type":"bytes32"},{"internalType":"uint8","name":"minimum","type":"uint8"}],"name":"inProximity","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint8","name":"_depth","type":"uint8"}],"name":"isParticipatingInUpcomingRound","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_overlay","type":"bytes32"}],"name":"isWinner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextSeed","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_depth","type":"uint8"},{"internalType":"bytes32","name":"_hash","type":"bytes32"},{"internalType":"bytes32","name":"_revealNonce","type":"bytes32"}],"name":"reveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_penaltyMultiplierDisagreement","type":"uint8"},{"internalType":"uint8","name":"_penaltyMultiplierNonRevealed","type":"uint8"},{"internalType":"uint8","name":"_penaltyRandomFactor","type":"uint8"}],"name":"setFreezingParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sampleMaxValue","type":"uint256"}],"name":"setSampleMaxValue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"winner","outputs":[{"internalType":"bytes32","name":"overlay","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint8","name":"depth","type":"uint8"},{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"stakeDensity","type":"uint256"},{"internalType":"bytes32","name":"hash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_overlay","type":"bytes32"},{"internalType":"uint8","name":"_depth","type":"uint8"},{"internalType":"bytes32","name":"_hash","type":"bytes32"},{"internalType":"bytes32","name":"revealNonce","type":"bytes32"}],"name":"wrapCommit","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"}]
Contract Creation Code
60806040526008805462ffffff60c01b19166264020160c01b1790557dba1914b54e0348a1028d1a103a95ed55c4004b9d332400000000000000006009553480156200004a57600080fd5b5060405162004b0538038062004b058339810160408190526200006d916200019d565b60018054600380546001600160a01b03199081166001600160a01b03888116919091179092556001600160a81b0319909216610100868316021790925560028054909116918316919091179055620000c7600033620000d0565b505050620001e7565b620000dc8282620000e0565b5050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16620000dc576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556200013c3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b80516001600160a01b03811681146200019857600080fd5b919050565b600080600060608486031215620001b357600080fd5b620001be8462000180565b9250620001ce6020850162000180565b9150620001de6040850162000180565b90509250925092565b61490e80620001f76000396000f3fe608060405234801561001057600080fd5b50600436106102775760003560e01c806377c75d1011610160578063b6cd5822116100d8578063dfbf53ae1161008c578063f69ee1d111610071578063f69ee1d1146105d5578063f7b188a5146105e8578063fb00f2f3146105f057600080fd5b8063dfbf53ae14610592578063f4e6fcca146105c257600080fd5b8063ce987745116100bd578063ce98774514610564578063d1e8b63d14610577578063d547741f1461057f57600080fd5b8063b6cd582214610537578063c46b40291461054a57600080fd5b80638456cb591161012f5780638d8b6428116101145780638d8b6428146104f057806391d14854146104f8578063a217fddf1461052f57600080fd5b80638456cb59146104e05780638a19c8bc146104e857600080fd5b806377c75d101461045a5780637fe019c61461046d57806382b39b1b1461048857806383220626146104d857600080fd5b80635c975abb116101f357806364c34a85116101c257806369da9114116101a757806369da9114146103de5780636f94aaf2146103f157806372286cba1461040c57600080fd5b806364c34a85146103a957806369bfac01146103b157600080fd5b80635c975abb146103705780635d4844ea1461037b57806362fd29ae1461038e57806363f5cf7c1461039657600080fd5b80632a4e62491161024a5780632f3906da1161022f5780632f3906da1461034257806336568abe1461034a5780635838d6731461035d57600080fd5b80632a4e6249146103185780632f2ff15d1461032d57600080fd5b806301ffc9a71461027c5780631736d472146102a457806318350096146102b7578063248a9ca3146102e7575b600080fd5b61028f61028a36600461405f565b610603565b60405190151581526020015b60405180910390f35b61028f6102b23660046140ad565b61066c565b6001546102cf9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161029b565b61030a6102f53660046140e6565b60009081526020819052604090206001015490565b60405190815260200161029b565b6103206107fa565b60405161029b91906140ff565b61034061033b36600461418e565b610907565b005b61028f610931565b61034061035836600461418e565b61097b565b61034061036b3660046141d0565b610a0c565b60015460ff1661028f565b6003546102cf906001600160a01b031681565b61030a610f54565b6103406103a4366004614215565b611020565b61030a6113bb565b6008546103c59067ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161029b565b6002546102cf906001600160a01b031681565b6008546103c590600160801b900467ffffffffffffffff1681565b61041f61041a3660046140e6565b61149b565b604080519687526001600160a01b039095166020870152921515938501939093526060840152608083019190915260a082015260c00161029b565b61028f6104683660046140e6565b6114f2565b6008546103c590600160401b900467ffffffffffffffff1681565b61049b6104963660046140e6565b6117a2565b604080519687526001600160a01b03909516602087015260ff909316938501939093526060840152608083019190915260a082015260c00161029b565b61030a6117b2565b6103406117bd565b6103c5611816565b61028f611823565b61028f61050636600461418e565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b61030a600081565b61034061054536600461429d565b61184d565b610552611d8a565b60405160ff909116815260200161029b565b61030a6105723660046142d2565b611e0f565b61028f611e7d565b61034061058d36600461418e565b611ea2565b600a54600b54600c54600d54600e5461049b94936001600160a01b03811693600160a01b90910460ff1692909186565b6103406105d036600461430f565b611ec7565b6103406105e33660046140e6565b611fae565b610340612002565b61028f6105fe36600461435a565b612059565b60006001600160e01b031982167f7965db0b00000000000000000000000000000000000000000000000000000000148061066657507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b60035460405163d1052d1f60e01b81526001600160a01b038481166004830152600092839291169063d1052d1f90602401602060405180830381865afa1580156106ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106de9190614388565b90506106e8610931565b1561071f576040517fe2586bcc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060000361073f576040516273e5c360e31b815260040160405180910390fd5b61074b609860026143b7565b61075590436143ce565b811061077457604051630a0744c560e01b815260040160405180910390fd5b6003546040516397adedb560e01b81526001600160a01b0386811660048301526107f29216906397adedb590602401602060405180830381865afa1580156107c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e49190614388565b6107ec6113bb565b85612059565b949350505050565b6060610804611823565b61082157604051633788c6c160e11b815260040160405180910390fd5b600061082b611816565b60085490915067ffffffffffffffff808316600160401b909204161461086457604051636fbabc7760e01b815260040160405180910390fd5b6005805480602002602001604051908101604052809291908181526020016000905b828210156108fd5760008481526020908190206040805160c08101825260058602909201805483526001808201546001600160a01b03811685870152600160a01b900460ff169284019290925260028101546060840152600381015460808401526004015460a08301529083529092019101610886565b5050505091505090565b60008281526020819052604090206001015461092281612096565b61092c83836120a3565b505050565b60008061093f6098436143f7565b905061094d6004609861440b565b811015801561096657506109636002609861440b565b81105b1561097357600191505090565b600091505090565b6001600160a01b03811633146109fe5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b610a088282612141565b5050565b610a146121c0565b6000610a1e611816565b6003546040516397adedb560e01b81523360048201529192506000916001600160a01b03909116906397adedb590602401602060405180830381865afa158015610a6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a909190614388565b6003546040517f830a053e0000000000000000000000000000000000000000000000000000000081523360048201529192506000916001600160a01b039091169063830a053e90602401602060405180830381865afa158015610af7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1b9190614388565b60035460405163d1052d1f60e01b81523360048201529192506000916001600160a01b039091169063d1052d1f90602401602060405180830381865afa158015610b69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8d9190614388565b9050610b97611e7d565b610bcd576040517fdc816a8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001610bdb6004609861440b565b610be591906143ce565b610bf06098436143f7565b03610c27576040517f5baef6b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8467ffffffffffffffff168467ffffffffffffffff161115610c75576040517f50ff7c0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8467ffffffffffffffff168467ffffffffffffffff161015610cc3576040517f7a0c0fd600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600003610ce3576040516273e5c360e31b815260040160405180910390fd5b610cef609860026143b7565b610cf990436143ce565b8110610d1857604051630a0744c560e01b815260040160405180910390fd5b60085467ffffffffffffffff858116911614610d5857610d3a60046000613ff6565b6008805467ffffffffffffffff191667ffffffffffffffff86161790555b60045460005b81811015610dcb578460048281548110610d7a57610d7a61441f565b90600052602060002090600502016000015403610dc3576040517fbfec555800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600101610d5e565b506040805160c081018252858152336020808301918252600083850181815260608501898152608086018e815260a0870184815260048054600181018255955296517f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b60059095029485015594517f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19c8401805493516001600160a01b0390921674ffffffffffffffffffffffffffffffffffffffffff1990941693909317600160a01b9115159190910217909155517f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19d82015591517f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19e83015591517f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19f90910155815167ffffffffffffffff891681529081018690527f68e0867601a98978930107aee7f425665e61edd70ca594c68ca5da9e81f84c29910160405180910390a150505050505050565b600080610f5f611816565b610f6a906001614435565b60075460085491925090610f9090600160401b900467ffffffffffffffff166001614435565b67ffffffffffffffff168267ffffffffffffffff16111561066657600854600090600190610fcf90600160401b900467ffffffffffffffff168561445d565b610fd9919061445d565b67ffffffffffffffff1690508181604051602001611001929190918252602082015260400190565b6040516020818303038152906040528051906020012091505092915050565b6110286121c0565b611030612213565b6040805160c081018252600a548152600b546001600160a01b0381166020830152600160a01b900460ff1691810191909152600c546060820152600d546080820152600e5460a08201526006546007546000918291611090600f826143f7565b935061109d600e826143f7565b92508383106110b457826110b08161447e565b9350505b6110c78660200135838760400151612059565b6110e757604051633b5f43a360e01b8152600360048201526024016109f5565b6110f286601e61281f565b6110fb86612b31565b61110486612e3e565b6111178860200135838760400151612059565b61113757604051633b5f43a360e01b8152600260048201526024016109f5565b61114b886111468660026143b7565b61281f565b61115488612b31565b61115d88612e3e565b6111708760200135838760400151612059565b61119057604051633b5f43a360e01b8152600160048201526024016109f5565b61119f876111468560026143b7565b6111a887612b31565b6111b187612e3e565b61122784846111c08b80614497565b60008181106111d1576111d161441f565b602002919091013590506111e58b80614497565b60008181106111f6576111f661441f565b6020029190910135905061120a8b80614497565b600081811061121b5761121b61441f565b905060200201356130d2565b6112516112348780614497565b60008181106112455761124561441f565b9050602002013561315f565b60015460208601516040517f51cff8d90000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015261010090920416906351cff8d990602401600060405180830381600087803b1580156112ba57600080fd5b505af11580156112ce573d6000803e3d6000fd5b505050507f788e77979e6e6a8a6a5d2c19c58b1ff9671298f54c85ac6f6aa30379aed5861a8560405161130191906144e8565b60405180910390a17fbee3fc8a3523c1a65fa9308ce1f2b8fd90c24975b141b754603194597846e4dd60018054906101000a90046001600160a01b03166001600160a01b0316638a5e8e326040518163ffffffff1660e01b8152600401602060405180830381865afa15801561137b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139f9190614388565b6040519081526020015b60405180910390a15050505050505050565b60006113c5611e7d565b806114035750600854600160401b900467ffffffffffffffff166113e7611816565b67ffffffffffffffff161180156114035750611401611823565b155b15611415576114106117b2565b905090565b61141d611823565b1561142a57611410610f54565b611432610931565b80156114615750600854600160401b900467ffffffffffffffff16611455611816565b67ffffffffffffffff16145b15611498576040517f36b7884b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b90565b600481815481106114ab57600080fd5b6000918252602090912060059091020180546001820154600283015460038401546004909401549294506001600160a01b03821693600160a01b90920460ff169290919086565b60006114fc611823565b61151957604051633788c6c160e11b815260040160405180910390fd5b6000611523611816565b60085490915067ffffffffffffffff808316600160401b909204161461155c57604051636fbabc7760e01b815260040160405180910390fd5b60085467ffffffffffffffff600160801b90910481169082161161159357604051630c8d9eab60e31b815260040160405180910390fd5b6000806000806000806000806115a761319d565b905060006115b3613257565b600454919650945060005b8181101561178e57600481815481106115d9576115d961441f565b9060005260206000209060050201600401549450600481815481106116005761160061441f565b906000526020600020906005020160010160149054906101000a900460ff16801561164e5750600585815481106116395761163961441f565b90600052602060002090600502016004015487145b801561168c5750600585815481106116685761166861441f565b600091825260209091206001600590920201015460ff878116600160a01b90920416145b1561178657600585815481106116a4576116a461441f565b9060005260206000209060050201600301548b6116c19190614537565b9a5083836040516020016116d692919061456e565b60408051601f19818403018152919052805160209091012098506fffffffffffffffffffffffffffffffff808a169850611711906001614537565b600586815481106117245761172461441f565b90600052602060002090600502016003015461174091906143b7565b61174a8c8a6143b7565b101561177857600585815481106117635761176361441f565b90600052602060002090600502016000015499505b826117828161447e565b9350505b6001016115be565b505050959099149998505050505050505050565b600581815481106114ab57600080fd5b600080610f6a611816565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661180c57604051631d77d47760e21b815260040160405180910390fd5b611814613410565b565b600061141060984361440b565b60006118316002609861440b565b61183c6098436143f7565b106118475750600190565b50600090565b6118556121c0565b600061185f611816565b6003546040516397adedb560e01b81523360048201529192506000916001600160a01b03909116906397adedb590602401602060405180830381865afa1580156118ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118d19190614388565b90506118db611d8a565b60ff168560ff16101561191a576040517f83d9b7bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611922610931565b611958576040517fd1088db600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085467ffffffffffffffff8381169116146119a0576040517f842a9e0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085467ffffffffffffffff838116600160401b9092041614611a88576119c56113bb565b6006556119d460056000613ff6565b600880547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff16600160401b67ffffffffffffffff8516908102919091179091556006546040805192835260208301919091527ff0ae472da9c8da86bda4991a549c03a3cb328b5f360ea11a5b8814f32bb85176910160405180910390a1611a88600754604080516020810192909252449082015260600160408051601f198184030181529190528051602090910120600755565b6000611a9682878787611e0f565b90506000611aa48383613464565b9050600060048281548110611abb57611abb61441f565b60009182526020918290206040805160c081018252600593909302909101805480845260018201546001600160a01b03811695850195909552600160a01b90940460ff1615159183019190915260028101546060830152600381015460808301526004015460a0820152600654909250611b3691908a612059565b611b72576006546040517f14ebbbe40000000000000000000000000000000000000000000000000000000081526004016109f591815260200190565b806040015115611bae576040517fa89ac15100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160048381548110611bc357611bc361441f565b906000526020600020906005020160010160146101000a81548160ff02191690831515021790555060058054905060048381548110611c0457611c0461441f565b90600052602060002090600502016004018190555060056040518060c001604052808360000151815260200183602001516001600160a01b031681526020018a60ff168152602001836060015181526020018a6002611c639190614674565b8460600151611c7291906143b7565b815260209081018a90528254600181810185556000948552938290208351600590920201908155908201519281018054604084015160ff16600160a01b0274ffffffffffffffffffffffffffffffffffffffffff199091166001600160a01b0390951694909417939093179092556060808201516002808501919091556080830151600385015560a0909201516004909301929092558251918301517f13fc17fd71632266fe82092de6dd91a06b4fa68d8dc950492e5421cbed55a6a5928892909190611d40908d90614674565b8560600151611d4f91906143b7565b6040805167ffffffffffffffff909516855260208501939093529183015260608201526080810189905260ff8a1660a082015260c0016113a9565b6008546000908190611daf9067ffffffffffffffff600160801b82048116911661445d565b67ffffffffffffffff169050600060fe8211611dcb5781611dce565b60fe5b611dd9906001614683565b600b5490915060ff600160a01b9091048116908216811115611e0457611dff828261469c565b611e07565b60005b935050505090565b60408051602081018690527fff0000000000000000000000000000000000000000000000000000000000000060f886901b169181019190915260418101839052606181018290526000906081015b604051602081830303815290604052805190602001209050949350505050565b6000611e8b6004609861440b565b611e966098436143f7565b10156118475750600190565b600082815260208190526040902060010154611ebd81612096565b61092c8383612141565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611f1657604051637bfa4b9f60e01b815260040160405180910390fd5b600880547fffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b60ff958616027fffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffff1617600160c81b93851693909302929092177fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff16600160d01b9190931602919091179055565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611ffd57604051637bfa4b9f60e01b815260040160405180910390fd5b600955565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661205157604051631d77d47760e21b815260040160405180910390fd5b61181461350f565b60008160ff1660000361206e5750600161208f565b61207d60ff83166101006146b5565b6120889060026146d0565b8484181090505b9392505050565b6120a08133613548565b50565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a08576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556120fd3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1615610a08576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60015460ff16156118145760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016109f5565b600061221d611816565b9050612227611823565b61224457604051633788c6c160e11b815260040160405180910390fd5b60085467ffffffffffffffff828116600160401b909204161461227a57604051636fbabc7760e01b815260040160405180910390fd5b60085467ffffffffffffffff600160801b9091048116908216116122b157604051630c8d9eab60e31b815260040160405180910390fd5b600454604051818152600091829182918291829182917f6752c5e71c95fb93bc7137adeb115a33fa4e54e2683e33d3f90c2bb1c4b6c2a59060200160405180910390a16005546040519081527f4c03de6a759749c0c9387b7014634dc5c6af610e1366023d90751c783a998f8d9060200160405180910390a1612332613257565b6040805183815260ff831660208201529295509093507f34e8eda4cd857cd2865becf58a47748f31415f4a382cbb2cc0c64b9a27c717be910160405180910390a1600061237d61319d565b905060005b828110156127595760006004828154811061239f5761239f61441f565b600091825260208083206040805160c08101825260059485029092018054835260018101546001600160a01b03811694840194909452600160a01b90930460ff16151590820152600282015460608201526003820154608082015260049091015460a0820181905282549194509291908390811061241f5761241f61441f565b60009182526020918290206040805160c0810182526005939093029091018054835260018101546001600160a01b03811694840194909452600160a01b90930460ff1682820152600283015460608301526003830154608083015260049092015460a082015290840151909150801561249b57508060a0015188145b80156124b05750806040015160ff168760ff16145b156125a55760808101516124c4908d614537565b9b50848b6040516020016124d992919061456e565b60408051601f19818403018152919052805160209091012099506fffffffffffffffffffffffffffffffff808b169950612514906001614537565b816080015161252391906143b7565b61252d8d8b6143b7565b1015612597578051600a556020810151600b8054604084015160ff16600160a01b0274ffffffffffffffffffffffffffffffffffffffffff199091166001600160a01b03909316929092179190911790556060810151600c556080810151600d5560a0810151600e555b8a6125a18161447e565b9b50505b826040015180156125ce57508060a00151881415806125ce5750806040015160ff168760ff1614155b80156125ef5750600854600160d01b900460ff166125ed6064446143f7565b105b1561269b5760035460208201516001600160a01b039091169063d009b2d6906126198a6002614674565b60085461263290609890600160c01b900460ff166143b7565b61263c91906143b7565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561268257600080fd5b505af1158015612696573d6000803e3d6000fd5b505050505b826040015161274b5760035460208401516001600160a01b039091169063d009b2d6906126c98a6002614674565b6008546126e290609890600160c81b900460ff166143b7565b6126ec91906143b7565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561273257600080fd5b505af1158015612746573d6000803e3d6000fd5b505050505b836001019350505050612382565b506002546040517fffb98fe300000000000000000000000000000000000000000000000000000000815261ffff891660048201526001600160a01b039091169063ffb98fe390602401600060405180830381600087803b1580156127bc57600080fd5b505af11580156127d0573d6000803e3d6000fd5b50506008805467ffffffffffffffff909c16600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff909c169b909b17909a5550505050505050505050565b600754600090612831906080906143f7565b9050600061289461284560a0860186614497565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050505060608601358461288c60a0890160808a016146e0565b6006546135bb565b60408051858152602081018390529192507f94e252069a85aa79db21f5bd8ca4e14dd3a3927aa492711017a2c8ddad95af00910160405180910390a161291c6128dd8580614497565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505050602086013585610400613733565b600e54146129475760405163755f0a2560e01b815260016004820152602481018290526044016109f5565b61295460a0850185614497565b60008181106129655761296561441f565b9050602002013584806040019061297c9190614497565b600081811061298d5761298d61441f565b90506020020135146129bc5760405163755f0a2560e01b815260026004820152602481018290526044016109f5565b6000806129cc60e0870187614497565b9050116129dd578460200135612a12565b6129ea60e0860186614497565b60008181106129fb576129fb61441f565b9050602002810190612a0d91906146fb565b606001355b9050612a70612a246040870187614497565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505050606087013585612a6b60a08a0160808b016146e0565b613733565b8114612a995760405163755f0a2560e01b815260036004820152602481018390526044016109f5565b6000612aa860e0870187614497565b90501115612ae05760408051602080880135908201529081018390526060016040516020818303038152906040528051906020012091505b81612aeb8680614497565b6000818110612afc57612afc61441f565b9050602002013514612b2a5760405163755f0a2560e01b8152600481810152602481018390526044016109f5565b5050505050565b6001546000908190819061010090046001600160a01b031663c81e25ab612b5b60c08701876146fb565b602001356040518263ffffffff1660e01b8152600401612b7d91815260200190565b60c060405180830381865afa158015612b9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbe919061471b565b509396509194509250506001600160a01b0384169050612c1e57612be560c08501856146fb565b602001356040517f2396d34e0000000000000000000000000000000000000000000000000000000081526004016109f591815260200190565b6000612c41612c3060c08701876146fb565b6114989060608101906040016146e0565b90506000612c4f84846138a1565b9050808263ffffffff1610612ca457612c6b60c08701876146fb565b602001356040517f1362e4a00000000000000000000000000000000000000000000000000000000081526004016109f591815260200190565b6000612cd3612cb660c08901896146fb565b612cc79060608101906040016146e0565b60201c63ffffffff1690565b90506000612ce58860200135866138bc565b63ffffffff16905067ffffffffffffffff82168114612d4457612d0b60c08901896146fb565b602001356040517f6dd6a24f0000000000000000000000000000000000000000000000000000000081526004016109f591815260200190565b612dea87612d5560c08b018b6146fb565b612d5f9080614793565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050505060208b0135612da560c08d018d6146fb565b60200135612db660c08e018e6146fb565b612dc79060608101906040016146e0565b612dd460c08f018f6146fb565b612de59060808101906060016146e0565b6138e3565b612e3457612dfb60c08901896146fb565b602001356040517fdb12fb9d0000000000000000000000000000000000000000000000000000000081526004016109f591815260200190565b5050505050505050565b612e4b60e0820182614497565b9050600003612e575750565b612f78612e6760e0830183614497565b6000818110612e7857612e7861441f565b9050602002810190612e8a91906146fb565b612e989060208101906147da565b612ea560e0840184614497565b6000818110612eb657612eb661441f565b9050602002810190612ec891906146fb565b612ed6906020810190614793565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612f189250505060e0850185614497565b6000818110612f2957612f2961441f565b9050602002810190612f3b91906146fb565b60400135612f4c60e0860186614497565b6000818110612f5d57612f5d61441f565b9050602002810190612f6f91906146fb565b6060013561397a565b612fe557612f8960e0820182614497565b6000818110612f9a57612f9a61441f565b9050602002810190612fac91906146fb565b606001356040517fd740df610000000000000000000000000000000000000000000000000000000081526004016109f591815260200190565b6020810135613064612ffa60e0840184614497565b600081811061300b5761300b61441f565b905060200281019061301d91906146fb565b6040013561302e60e0850185614497565b600081811061303f5761303f61441f565b905060200281019061305191906146fb565b61305f9060208101906147da565b613a0d565b146120a05761307660e0820182614497565b60008181106130875761308761441f565b905060200281019061309991906146fb565b606001356040517f82f2469d0000000000000000000000000000000000000000000000000000000081526004016109f591815260200190565b8385101561311f578183106130fa57604051633d386eb360e11b815260040160405180910390fd5b80821061311a57604051633588c6d360e11b815260040160405180910390fd5b612b2a565b82821061313f57604051633d386eb360e11b815260040160405180910390fd5b808310612b2a57604051633588c6d360e11b815260040160405180910390fd5b60095481106120a0576040517fb6052cdf000000000000000000000000000000000000000000000000000000008152600481018290526024016109f5565b60606131a7611823565b6131c457604051633788c6c160e11b815260040160405180910390fd5b60006131ce611816565b60085490915067ffffffffffffffff808316600160401b909204161461320757604051636fbabc7760e01b815260040160405180910390fd5b6007546040516020016132429181527f3100000000000000000000000000000000000000000000000000000000000000602082015260210190565b60405160208183030381529060405291505090565b600080600080600080600080600061326d613a5b565b60045490915060005b818110156133ff57600481815481106132915761329161441f565b906000526020600020906005020160010160149054906101000a900460ff16156133f757600481815481106132c8576132c861441f565b9060005260206000209060050201600401549350600584815481106132ef576132ef61441f565b9060005260206000209060050201600301548961330c9190614537565b9850828160405160200161332192919061456e565b60408051601f19818403018152919052805160209091012097506fffffffffffffffffffffffffffffffff808916975061335c906001614537565b6005858154811061336f5761336f61441f565b90600052602060002090600502016003015461338b91906143b7565b6133958a896143b7565b10156133f757600584815481106133ae576133ae61441f565b9060005260206000209060050201600401549550600584815481106133d5576133d561441f565b906000526020600020906005020160010160149054906101000a900460ff1694505b600101613276565b509399929850919650505050505050565b6134186121c0565b6001805460ff1916811790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258335b6040516001600160a01b03909116815260200160405180910390a1565b6000805b6004548110156134dc5783600482815481106134865761348661441f565b9060005260206000209060050201600001541480156134c85750600481815481106134b3576134b361441f565b90600052602060002090600502016003015483145b156134d4579050610666565b600101613468565b506040517fd950091500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613517613ae4565b6001805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33613447565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a085761357981613b36565b613584836020613b48565b6040516020016135959291906147f7565b60408051601f198184030181529082905262461bcd60e51b82526109f591600401614878565b6000806135ca87878786613d0d565b9050826136cf856000808267ffffffffffffffff1690506008817eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff16901b600882901c7eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff161790506010817dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff16901b601082901c7dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff161790506020817bffffffff00000000ffffffff00000000ffffffff00000000ffffffff16901b602082901c7bffffffff00000000ffffffff00000000ffffffff00000000ffffffff1617905080915050919050565b826040516020016137119392919092835260c09190911b77ffffffffffffffffffffffffffffffffffffffffffffffff19166020830152602882015260480190565b6040516020818303038152906040528051906020012091505095945050505050565b600080613741868686613d83565b9050613845836000808267ffffffffffffffff1690506008817eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff16901b600882901c7eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff161790506010817dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff16901b601082901c7dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff161790506020817bffffffff00000000ffffffff00000000ffffffff00000000ffffffff16901b602082901c7bffffffff00000000ffffffff00000000ffffffff00000000ffffffff1617905080915050919050565b8160405160200161388092919060c09290921b77ffffffffffffffffffffffffffffffffffffffffffffffff19168252600882015260280190565b60405160208183030381529060405280519060200120915050949350505050565b60006138ad828461469c565b60ff166001901b905092915050565b600060e083901c6138ce83602061469c565b60ff168163ffffffff16901c91505092915050565b6000806138f286868686613deb565b9050600061394d826040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b9050886001600160a01b0316613963828a613e36565b6001600160a01b0316149998505050505050505050565b6000806139878484613eb5565b905060006139e2826040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b9050866001600160a01b03166139f88288613e36565b6001600160a01b031614979650505050505050565b60008282604051602001613a3d92919091825260601b6bffffffffffffffffffffffff1916602082015260340190565b60405160208183030381529060405280519060200120905092915050565b6060613a65611823565b613a8257604051633788c6c160e11b815260040160405180910390fd5b6000613a8c611816565b60085490915067ffffffffffffffff808316600160401b9092041614613ac557604051636fbabc7760e01b815260040160405180910390fd5b600754604051602001613242918152600360fc1b602082015260210190565b60015460ff166118145760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016109f5565b60606106666001600160a01b03831660145b60606000613b578360026143b7565b613b62906002614537565b67ffffffffffffffff811115613b7a57613b7a6148ab565b6040519080825280601f01601f191660200182016040528015613ba4576020820181803683370190505b509050600360fc1b81600081518110613bbf57613bbf61441f565b60200101906001600160f81b031916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110613c0a57613c0a61441f565b60200101906001600160f81b031916908160001a9053506000613c2e8460026143b7565b613c39906001614537565b90505b6001811115613cbe577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110613c7a57613c7a61441f565b1a60f81b828281518110613c9057613c9061441f565b60200101906001600160f81b031916908160001a90535060049490941c93613cb7816148c1565b9050613c3c565b50831561208f5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109f5565b8260005b8551811015613d7a576000613d276002866143f7565b15613d33576000613d36565b60015b9050613d5d83888481518110613d4e57613d4e61441f565b60200260200101518387613ed1565b9250600185901c9450508080613d729061447e565b915050613d11565b50949350505050565b8160005b8451811015613de3576000613d9d6002856143f7565b6000149050613dc683878481518110613db857613db861441f565b602002602001015183613f31565b9250600184901c9350508080613ddb9061447e565b915050613d87565b509392505050565b604080516020810186905290810184905277ffffffffffffffffffffffffffffffffffffffffffffffff1960c084811b8216606084015283901b166068820152600090607001611e5d565b600080600080613e4585613f98565b6040805160008152602081018083528b905260ff8316918101919091526060810184905260808101839052929550909350915060019060a0016020604051602081039080840390855afa158015613ea0573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b6040805160208101849052908101829052600090606001613a3d565b60008215613f11576040805160208101849052908101869052606081018590526080016040516020818303038152906040528051906020012090506107f2565b604080516020810184905290810185905260608101869052608001611e5d565b60008115613f6a57604080516020810186905290810184905260600160405160208183030381529060405280519060200120905061208f565b5050604080516020808201939093528082019390935280518084038201815260609093019052815191012090565b60008060008351604114613fd8576040517f4be6321b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505060208101516040820151606090920151909260009190911a90565b50805460008255600502906000526020600020908101906120a091905b8082111561405b57600080825560018201805474ffffffffffffffffffffffffffffffffffffffffff1916905560028201819055600382018190556004820155600501614013565b5090565b60006020828403121561407157600080fd5b81356001600160e01b03198116811461208f57600080fd5b6001600160a01b03811681146120a057600080fd5b60ff811681146120a057600080fd5b600080604083850312156140c057600080fd5b82356140cb81614089565b915060208301356140db8161409e565b809150509250929050565b6000602082840312156140f857600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b818110156141825761416f838551805182526001600160a01b03602082015116602083015260ff6040820151166040830152606081015160608301526080810151608083015260a081015160a08301525050565b9284019260c0929092019160010161411b565b50909695505050505050565b600080604083850312156141a157600080fd5b8235915060208301356140db81614089565b803567ffffffffffffffff811681146141cb57600080fd5b919050565b600080604083850312156141e357600080fd5b823591506141f3602084016141b3565b90509250929050565b6000610100828403121561420f57600080fd5b50919050565b60008060006060848603121561422a57600080fd5b833567ffffffffffffffff8082111561424257600080fd5b61424e878388016141fc565b9450602086013591508082111561426457600080fd5b614270878388016141fc565b9350604086013591508082111561428657600080fd5b50614293868287016141fc565b9150509250925092565b6000806000606084860312156142b257600080fd5b83356142bd8161409e565b95602085013595506040909401359392505050565b600080600080608085870312156142e857600080fd5b8435935060208501356142fa8161409e565b93969395505050506040820135916060013590565b60008060006060848603121561432457600080fd5b833561432f8161409e565b9250602084013561433f8161409e565b9150604084013561434f8161409e565b809150509250925092565b60008060006060848603121561436f57600080fd5b8335925060208401359150604084013561434f8161409e565b60006020828403121561439a57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610666576106666143a1565b81810381811115610666576106666143a1565b634e487b7160e01b600052601260045260246000fd5b600082614406576144066143e1565b500690565b60008261441a5761441a6143e1565b500490565b634e487b7160e01b600052603260045260246000fd5b67ffffffffffffffff818116838216019080821115614456576144566143a1565b5092915050565b67ffffffffffffffff828116828216039080821115614456576144566143a1565b600060018201614490576144906143a1565b5060010190565b6000808335601e198436030181126144ae57600080fd5b83018035915067ffffffffffffffff8211156144c957600080fd5b6020019150600581901b36038213156144e157600080fd5b9250929050565b60c081016106668284805182526001600160a01b03602082015116602083015260ff6040820151166040830152606081015160608301526080810151608083015260a081015160a08301525050565b80820180821115610666576106666143a1565b60005b8381101561456557818101518382015260200161454d565b50506000910152565b6000835161458081846020880161454a565b9190910191825250602001919050565b600181815b808511156145cb5781600019048211156145b1576145b16143a1565b808516156145be57918102915b93841c9390800290614595565b509250929050565b6000826145e257506001610666565b816145ef57506000610666565b8160018114614605576002811461460f5761462b565b6001915050610666565b60ff841115614620576146206143a1565b50506001821b610666565b5060208310610133831016604e8410600b841016171561464e575081810a610666565b6146588383614590565b806000190482111561466c5761466c6143a1565b029392505050565b600061208f60ff8416836145d3565b60ff8181168382160190811115610666576106666143a1565b60ff8281168282160390811115610666576106666143a1565b61ffff828116828216039080821115614456576144566143a1565b600061208f61ffff8416836145d3565b6000602082840312156146f257600080fd5b61208f826141b3565b60008235607e1983360301811261471157600080fd5b9190910192915050565b60008060008060008060c0878903121561473457600080fd5b865161473f81614089565b60208801519096506147508161409e565b60408801519095506147618161409e565b6060880151909450801515811461477757600080fd5b809350506080870151915060a087015190509295509295509295565b6000808335601e198436030181126147aa57600080fd5b83018035915067ffffffffffffffff8211156147c557600080fd5b6020019150368190038213156144e157600080fd5b6000602082840312156147ec57600080fd5b813561208f81614089565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161482f81601785016020880161454a565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000601791840191820152835161486c81602884016020880161454a565b01602801949350505050565b602081526000825180602084015261489781604085016020870161454a565b601f01601f19169190910160400192915050565b634e487b7160e01b600052604160045260246000fd5b6000816148d0576148d06143a1565b50600019019056fea26469706673582212200f9f0a55ccd6f0cb7269fe52233ea174faebf4c052751953813f1866c96736b964736f6c63430008130033000000000000000000000000be212ea1a4978a64e8f7636ae18305c38ca092bd00000000000000000000000045a1502382541cd610cc9068e88727426b69629300000000000000000000000086de783bf23bc13daef5a55ec531c198da8f10cf
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102775760003560e01c806377c75d1011610160578063b6cd5822116100d8578063dfbf53ae1161008c578063f69ee1d111610071578063f69ee1d1146105d5578063f7b188a5146105e8578063fb00f2f3146105f057600080fd5b8063dfbf53ae14610592578063f4e6fcca146105c257600080fd5b8063ce987745116100bd578063ce98774514610564578063d1e8b63d14610577578063d547741f1461057f57600080fd5b8063b6cd582214610537578063c46b40291461054a57600080fd5b80638456cb591161012f5780638d8b6428116101145780638d8b6428146104f057806391d14854146104f8578063a217fddf1461052f57600080fd5b80638456cb59146104e05780638a19c8bc146104e857600080fd5b806377c75d101461045a5780637fe019c61461046d57806382b39b1b1461048857806383220626146104d857600080fd5b80635c975abb116101f357806364c34a85116101c257806369da9114116101a757806369da9114146103de5780636f94aaf2146103f157806372286cba1461040c57600080fd5b806364c34a85146103a957806369bfac01146103b157600080fd5b80635c975abb146103705780635d4844ea1461037b57806362fd29ae1461038e57806363f5cf7c1461039657600080fd5b80632a4e62491161024a5780632f3906da1161022f5780632f3906da1461034257806336568abe1461034a5780635838d6731461035d57600080fd5b80632a4e6249146103185780632f2ff15d1461032d57600080fd5b806301ffc9a71461027c5780631736d472146102a457806318350096146102b7578063248a9ca3146102e7575b600080fd5b61028f61028a36600461405f565b610603565b60405190151581526020015b60405180910390f35b61028f6102b23660046140ad565b61066c565b6001546102cf9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161029b565b61030a6102f53660046140e6565b60009081526020819052604090206001015490565b60405190815260200161029b565b6103206107fa565b60405161029b91906140ff565b61034061033b36600461418e565b610907565b005b61028f610931565b61034061035836600461418e565b61097b565b61034061036b3660046141d0565b610a0c565b60015460ff1661028f565b6003546102cf906001600160a01b031681565b61030a610f54565b6103406103a4366004614215565b611020565b61030a6113bb565b6008546103c59067ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161029b565b6002546102cf906001600160a01b031681565b6008546103c590600160801b900467ffffffffffffffff1681565b61041f61041a3660046140e6565b61149b565b604080519687526001600160a01b039095166020870152921515938501939093526060840152608083019190915260a082015260c00161029b565b61028f6104683660046140e6565b6114f2565b6008546103c590600160401b900467ffffffffffffffff1681565b61049b6104963660046140e6565b6117a2565b604080519687526001600160a01b03909516602087015260ff909316938501939093526060840152608083019190915260a082015260c00161029b565b61030a6117b2565b6103406117bd565b6103c5611816565b61028f611823565b61028f61050636600461418e565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b61030a600081565b61034061054536600461429d565b61184d565b610552611d8a565b60405160ff909116815260200161029b565b61030a6105723660046142d2565b611e0f565b61028f611e7d565b61034061058d36600461418e565b611ea2565b600a54600b54600c54600d54600e5461049b94936001600160a01b03811693600160a01b90910460ff1692909186565b6103406105d036600461430f565b611ec7565b6103406105e33660046140e6565b611fae565b610340612002565b61028f6105fe36600461435a565b612059565b60006001600160e01b031982167f7965db0b00000000000000000000000000000000000000000000000000000000148061066657507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b60035460405163d1052d1f60e01b81526001600160a01b038481166004830152600092839291169063d1052d1f90602401602060405180830381865afa1580156106ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106de9190614388565b90506106e8610931565b1561071f576040517fe2586bcc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060000361073f576040516273e5c360e31b815260040160405180910390fd5b61074b609860026143b7565b61075590436143ce565b811061077457604051630a0744c560e01b815260040160405180910390fd5b6003546040516397adedb560e01b81526001600160a01b0386811660048301526107f29216906397adedb590602401602060405180830381865afa1580156107c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e49190614388565b6107ec6113bb565b85612059565b949350505050565b6060610804611823565b61082157604051633788c6c160e11b815260040160405180910390fd5b600061082b611816565b60085490915067ffffffffffffffff808316600160401b909204161461086457604051636fbabc7760e01b815260040160405180910390fd5b6005805480602002602001604051908101604052809291908181526020016000905b828210156108fd5760008481526020908190206040805160c08101825260058602909201805483526001808201546001600160a01b03811685870152600160a01b900460ff169284019290925260028101546060840152600381015460808401526004015460a08301529083529092019101610886565b5050505091505090565b60008281526020819052604090206001015461092281612096565b61092c83836120a3565b505050565b60008061093f6098436143f7565b905061094d6004609861440b565b811015801561096657506109636002609861440b565b81105b1561097357600191505090565b600091505090565b6001600160a01b03811633146109fe5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b610a088282612141565b5050565b610a146121c0565b6000610a1e611816565b6003546040516397adedb560e01b81523360048201529192506000916001600160a01b03909116906397adedb590602401602060405180830381865afa158015610a6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a909190614388565b6003546040517f830a053e0000000000000000000000000000000000000000000000000000000081523360048201529192506000916001600160a01b039091169063830a053e90602401602060405180830381865afa158015610af7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1b9190614388565b60035460405163d1052d1f60e01b81523360048201529192506000916001600160a01b039091169063d1052d1f90602401602060405180830381865afa158015610b69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8d9190614388565b9050610b97611e7d565b610bcd576040517fdc816a8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001610bdb6004609861440b565b610be591906143ce565b610bf06098436143f7565b03610c27576040517f5baef6b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8467ffffffffffffffff168467ffffffffffffffff161115610c75576040517f50ff7c0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8467ffffffffffffffff168467ffffffffffffffff161015610cc3576040517f7a0c0fd600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600003610ce3576040516273e5c360e31b815260040160405180910390fd5b610cef609860026143b7565b610cf990436143ce565b8110610d1857604051630a0744c560e01b815260040160405180910390fd5b60085467ffffffffffffffff858116911614610d5857610d3a60046000613ff6565b6008805467ffffffffffffffff191667ffffffffffffffff86161790555b60045460005b81811015610dcb578460048281548110610d7a57610d7a61441f565b90600052602060002090600502016000015403610dc3576040517fbfec555800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600101610d5e565b506040805160c081018252858152336020808301918252600083850181815260608501898152608086018e815260a0870184815260048054600181018255955296517f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b60059095029485015594517f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19c8401805493516001600160a01b0390921674ffffffffffffffffffffffffffffffffffffffffff1990941693909317600160a01b9115159190910217909155517f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19d82015591517f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19e83015591517f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19f90910155815167ffffffffffffffff891681529081018690527f68e0867601a98978930107aee7f425665e61edd70ca594c68ca5da9e81f84c29910160405180910390a150505050505050565b600080610f5f611816565b610f6a906001614435565b60075460085491925090610f9090600160401b900467ffffffffffffffff166001614435565b67ffffffffffffffff168267ffffffffffffffff16111561066657600854600090600190610fcf90600160401b900467ffffffffffffffff168561445d565b610fd9919061445d565b67ffffffffffffffff1690508181604051602001611001929190918252602082015260400190565b6040516020818303038152906040528051906020012091505092915050565b6110286121c0565b611030612213565b6040805160c081018252600a548152600b546001600160a01b0381166020830152600160a01b900460ff1691810191909152600c546060820152600d546080820152600e5460a08201526006546007546000918291611090600f826143f7565b935061109d600e826143f7565b92508383106110b457826110b08161447e565b9350505b6110c78660200135838760400151612059565b6110e757604051633b5f43a360e01b8152600360048201526024016109f5565b6110f286601e61281f565b6110fb86612b31565b61110486612e3e565b6111178860200135838760400151612059565b61113757604051633b5f43a360e01b8152600260048201526024016109f5565b61114b886111468660026143b7565b61281f565b61115488612b31565b61115d88612e3e565b6111708760200135838760400151612059565b61119057604051633b5f43a360e01b8152600160048201526024016109f5565b61119f876111468560026143b7565b6111a887612b31565b6111b187612e3e565b61122784846111c08b80614497565b60008181106111d1576111d161441f565b602002919091013590506111e58b80614497565b60008181106111f6576111f661441f565b6020029190910135905061120a8b80614497565b600081811061121b5761121b61441f565b905060200201356130d2565b6112516112348780614497565b60008181106112455761124561441f565b9050602002013561315f565b60015460208601516040517f51cff8d90000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015261010090920416906351cff8d990602401600060405180830381600087803b1580156112ba57600080fd5b505af11580156112ce573d6000803e3d6000fd5b505050507f788e77979e6e6a8a6a5d2c19c58b1ff9671298f54c85ac6f6aa30379aed5861a8560405161130191906144e8565b60405180910390a17fbee3fc8a3523c1a65fa9308ce1f2b8fd90c24975b141b754603194597846e4dd60018054906101000a90046001600160a01b03166001600160a01b0316638a5e8e326040518163ffffffff1660e01b8152600401602060405180830381865afa15801561137b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139f9190614388565b6040519081526020015b60405180910390a15050505050505050565b60006113c5611e7d565b806114035750600854600160401b900467ffffffffffffffff166113e7611816565b67ffffffffffffffff161180156114035750611401611823565b155b15611415576114106117b2565b905090565b61141d611823565b1561142a57611410610f54565b611432610931565b80156114615750600854600160401b900467ffffffffffffffff16611455611816565b67ffffffffffffffff16145b15611498576040517f36b7884b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b90565b600481815481106114ab57600080fd5b6000918252602090912060059091020180546001820154600283015460038401546004909401549294506001600160a01b03821693600160a01b90920460ff169290919086565b60006114fc611823565b61151957604051633788c6c160e11b815260040160405180910390fd5b6000611523611816565b60085490915067ffffffffffffffff808316600160401b909204161461155c57604051636fbabc7760e01b815260040160405180910390fd5b60085467ffffffffffffffff600160801b90910481169082161161159357604051630c8d9eab60e31b815260040160405180910390fd5b6000806000806000806000806115a761319d565b905060006115b3613257565b600454919650945060005b8181101561178e57600481815481106115d9576115d961441f565b9060005260206000209060050201600401549450600481815481106116005761160061441f565b906000526020600020906005020160010160149054906101000a900460ff16801561164e5750600585815481106116395761163961441f565b90600052602060002090600502016004015487145b801561168c5750600585815481106116685761166861441f565b600091825260209091206001600590920201015460ff878116600160a01b90920416145b1561178657600585815481106116a4576116a461441f565b9060005260206000209060050201600301548b6116c19190614537565b9a5083836040516020016116d692919061456e565b60408051601f19818403018152919052805160209091012098506fffffffffffffffffffffffffffffffff808a169850611711906001614537565b600586815481106117245761172461441f565b90600052602060002090600502016003015461174091906143b7565b61174a8c8a6143b7565b101561177857600585815481106117635761176361441f565b90600052602060002090600502016000015499505b826117828161447e565b9350505b6001016115be565b505050959099149998505050505050505050565b600581815481106114ab57600080fd5b600080610f6a611816565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661180c57604051631d77d47760e21b815260040160405180910390fd5b611814613410565b565b600061141060984361440b565b60006118316002609861440b565b61183c6098436143f7565b106118475750600190565b50600090565b6118556121c0565b600061185f611816565b6003546040516397adedb560e01b81523360048201529192506000916001600160a01b03909116906397adedb590602401602060405180830381865afa1580156118ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118d19190614388565b90506118db611d8a565b60ff168560ff16101561191a576040517f83d9b7bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611922610931565b611958576040517fd1088db600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085467ffffffffffffffff8381169116146119a0576040517f842a9e0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085467ffffffffffffffff838116600160401b9092041614611a88576119c56113bb565b6006556119d460056000613ff6565b600880547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff16600160401b67ffffffffffffffff8516908102919091179091556006546040805192835260208301919091527ff0ae472da9c8da86bda4991a549c03a3cb328b5f360ea11a5b8814f32bb85176910160405180910390a1611a88600754604080516020810192909252449082015260600160408051601f198184030181529190528051602090910120600755565b6000611a9682878787611e0f565b90506000611aa48383613464565b9050600060048281548110611abb57611abb61441f565b60009182526020918290206040805160c081018252600593909302909101805480845260018201546001600160a01b03811695850195909552600160a01b90940460ff1615159183019190915260028101546060830152600381015460808301526004015460a0820152600654909250611b3691908a612059565b611b72576006546040517f14ebbbe40000000000000000000000000000000000000000000000000000000081526004016109f591815260200190565b806040015115611bae576040517fa89ac15100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160048381548110611bc357611bc361441f565b906000526020600020906005020160010160146101000a81548160ff02191690831515021790555060058054905060048381548110611c0457611c0461441f565b90600052602060002090600502016004018190555060056040518060c001604052808360000151815260200183602001516001600160a01b031681526020018a60ff168152602001836060015181526020018a6002611c639190614674565b8460600151611c7291906143b7565b815260209081018a90528254600181810185556000948552938290208351600590920201908155908201519281018054604084015160ff16600160a01b0274ffffffffffffffffffffffffffffffffffffffffff199091166001600160a01b0390951694909417939093179092556060808201516002808501919091556080830151600385015560a0909201516004909301929092558251918301517f13fc17fd71632266fe82092de6dd91a06b4fa68d8dc950492e5421cbed55a6a5928892909190611d40908d90614674565b8560600151611d4f91906143b7565b6040805167ffffffffffffffff909516855260208501939093529183015260608201526080810189905260ff8a1660a082015260c0016113a9565b6008546000908190611daf9067ffffffffffffffff600160801b82048116911661445d565b67ffffffffffffffff169050600060fe8211611dcb5781611dce565b60fe5b611dd9906001614683565b600b5490915060ff600160a01b9091048116908216811115611e0457611dff828261469c565b611e07565b60005b935050505090565b60408051602081018690527fff0000000000000000000000000000000000000000000000000000000000000060f886901b169181019190915260418101839052606181018290526000906081015b604051602081830303815290604052805190602001209050949350505050565b6000611e8b6004609861440b565b611e966098436143f7565b10156118475750600190565b600082815260208190526040902060010154611ebd81612096565b61092c8383612141565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611f1657604051637bfa4b9f60e01b815260040160405180910390fd5b600880547fffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b60ff958616027fffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffff1617600160c81b93851693909302929092177fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff16600160d01b9190931602919091179055565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611ffd57604051637bfa4b9f60e01b815260040160405180910390fd5b600955565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661205157604051631d77d47760e21b815260040160405180910390fd5b61181461350f565b60008160ff1660000361206e5750600161208f565b61207d60ff83166101006146b5565b6120889060026146d0565b8484181090505b9392505050565b6120a08133613548565b50565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a08576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556120fd3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1615610a08576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60015460ff16156118145760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016109f5565b600061221d611816565b9050612227611823565b61224457604051633788c6c160e11b815260040160405180910390fd5b60085467ffffffffffffffff828116600160401b909204161461227a57604051636fbabc7760e01b815260040160405180910390fd5b60085467ffffffffffffffff600160801b9091048116908216116122b157604051630c8d9eab60e31b815260040160405180910390fd5b600454604051818152600091829182918291829182917f6752c5e71c95fb93bc7137adeb115a33fa4e54e2683e33d3f90c2bb1c4b6c2a59060200160405180910390a16005546040519081527f4c03de6a759749c0c9387b7014634dc5c6af610e1366023d90751c783a998f8d9060200160405180910390a1612332613257565b6040805183815260ff831660208201529295509093507f34e8eda4cd857cd2865becf58a47748f31415f4a382cbb2cc0c64b9a27c717be910160405180910390a1600061237d61319d565b905060005b828110156127595760006004828154811061239f5761239f61441f565b600091825260208083206040805160c08101825260059485029092018054835260018101546001600160a01b03811694840194909452600160a01b90930460ff16151590820152600282015460608201526003820154608082015260049091015460a0820181905282549194509291908390811061241f5761241f61441f565b60009182526020918290206040805160c0810182526005939093029091018054835260018101546001600160a01b03811694840194909452600160a01b90930460ff1682820152600283015460608301526003830154608083015260049092015460a082015290840151909150801561249b57508060a0015188145b80156124b05750806040015160ff168760ff16145b156125a55760808101516124c4908d614537565b9b50848b6040516020016124d992919061456e565b60408051601f19818403018152919052805160209091012099506fffffffffffffffffffffffffffffffff808b169950612514906001614537565b816080015161252391906143b7565b61252d8d8b6143b7565b1015612597578051600a556020810151600b8054604084015160ff16600160a01b0274ffffffffffffffffffffffffffffffffffffffffff199091166001600160a01b03909316929092179190911790556060810151600c556080810151600d5560a0810151600e555b8a6125a18161447e565b9b50505b826040015180156125ce57508060a00151881415806125ce5750806040015160ff168760ff1614155b80156125ef5750600854600160d01b900460ff166125ed6064446143f7565b105b1561269b5760035460208201516001600160a01b039091169063d009b2d6906126198a6002614674565b60085461263290609890600160c01b900460ff166143b7565b61263c91906143b7565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561268257600080fd5b505af1158015612696573d6000803e3d6000fd5b505050505b826040015161274b5760035460208401516001600160a01b039091169063d009b2d6906126c98a6002614674565b6008546126e290609890600160c81b900460ff166143b7565b6126ec91906143b7565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561273257600080fd5b505af1158015612746573d6000803e3d6000fd5b505050505b836001019350505050612382565b506002546040517fffb98fe300000000000000000000000000000000000000000000000000000000815261ffff891660048201526001600160a01b039091169063ffb98fe390602401600060405180830381600087803b1580156127bc57600080fd5b505af11580156127d0573d6000803e3d6000fd5b50506008805467ffffffffffffffff909c16600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff909c169b909b17909a5550505050505050505050565b600754600090612831906080906143f7565b9050600061289461284560a0860186614497565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050505060608601358461288c60a0890160808a016146e0565b6006546135bb565b60408051858152602081018390529192507f94e252069a85aa79db21f5bd8ca4e14dd3a3927aa492711017a2c8ddad95af00910160405180910390a161291c6128dd8580614497565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505050602086013585610400613733565b600e54146129475760405163755f0a2560e01b815260016004820152602481018290526044016109f5565b61295460a0850185614497565b60008181106129655761296561441f565b9050602002013584806040019061297c9190614497565b600081811061298d5761298d61441f565b90506020020135146129bc5760405163755f0a2560e01b815260026004820152602481018290526044016109f5565b6000806129cc60e0870187614497565b9050116129dd578460200135612a12565b6129ea60e0860186614497565b60008181106129fb576129fb61441f565b9050602002810190612a0d91906146fb565b606001355b9050612a70612a246040870187614497565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505050606087013585612a6b60a08a0160808b016146e0565b613733565b8114612a995760405163755f0a2560e01b815260036004820152602481018390526044016109f5565b6000612aa860e0870187614497565b90501115612ae05760408051602080880135908201529081018390526060016040516020818303038152906040528051906020012091505b81612aeb8680614497565b6000818110612afc57612afc61441f565b9050602002013514612b2a5760405163755f0a2560e01b8152600481810152602481018390526044016109f5565b5050505050565b6001546000908190819061010090046001600160a01b031663c81e25ab612b5b60c08701876146fb565b602001356040518263ffffffff1660e01b8152600401612b7d91815260200190565b60c060405180830381865afa158015612b9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbe919061471b565b509396509194509250506001600160a01b0384169050612c1e57612be560c08501856146fb565b602001356040517f2396d34e0000000000000000000000000000000000000000000000000000000081526004016109f591815260200190565b6000612c41612c3060c08701876146fb565b6114989060608101906040016146e0565b90506000612c4f84846138a1565b9050808263ffffffff1610612ca457612c6b60c08701876146fb565b602001356040517f1362e4a00000000000000000000000000000000000000000000000000000000081526004016109f591815260200190565b6000612cd3612cb660c08901896146fb565b612cc79060608101906040016146e0565b60201c63ffffffff1690565b90506000612ce58860200135866138bc565b63ffffffff16905067ffffffffffffffff82168114612d4457612d0b60c08901896146fb565b602001356040517f6dd6a24f0000000000000000000000000000000000000000000000000000000081526004016109f591815260200190565b612dea87612d5560c08b018b6146fb565b612d5f9080614793565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050505060208b0135612da560c08d018d6146fb565b60200135612db660c08e018e6146fb565b612dc79060608101906040016146e0565b612dd460c08f018f6146fb565b612de59060808101906060016146e0565b6138e3565b612e3457612dfb60c08901896146fb565b602001356040517fdb12fb9d0000000000000000000000000000000000000000000000000000000081526004016109f591815260200190565b5050505050505050565b612e4b60e0820182614497565b9050600003612e575750565b612f78612e6760e0830183614497565b6000818110612e7857612e7861441f565b9050602002810190612e8a91906146fb565b612e989060208101906147da565b612ea560e0840184614497565b6000818110612eb657612eb661441f565b9050602002810190612ec891906146fb565b612ed6906020810190614793565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612f189250505060e0850185614497565b6000818110612f2957612f2961441f565b9050602002810190612f3b91906146fb565b60400135612f4c60e0860186614497565b6000818110612f5d57612f5d61441f565b9050602002810190612f6f91906146fb565b6060013561397a565b612fe557612f8960e0820182614497565b6000818110612f9a57612f9a61441f565b9050602002810190612fac91906146fb565b606001356040517fd740df610000000000000000000000000000000000000000000000000000000081526004016109f591815260200190565b6020810135613064612ffa60e0840184614497565b600081811061300b5761300b61441f565b905060200281019061301d91906146fb565b6040013561302e60e0850185614497565b600081811061303f5761303f61441f565b905060200281019061305191906146fb565b61305f9060208101906147da565b613a0d565b146120a05761307660e0820182614497565b60008181106130875761308761441f565b905060200281019061309991906146fb565b606001356040517f82f2469d0000000000000000000000000000000000000000000000000000000081526004016109f591815260200190565b8385101561311f578183106130fa57604051633d386eb360e11b815260040160405180910390fd5b80821061311a57604051633588c6d360e11b815260040160405180910390fd5b612b2a565b82821061313f57604051633d386eb360e11b815260040160405180910390fd5b808310612b2a57604051633588c6d360e11b815260040160405180910390fd5b60095481106120a0576040517fb6052cdf000000000000000000000000000000000000000000000000000000008152600481018290526024016109f5565b60606131a7611823565b6131c457604051633788c6c160e11b815260040160405180910390fd5b60006131ce611816565b60085490915067ffffffffffffffff808316600160401b909204161461320757604051636fbabc7760e01b815260040160405180910390fd5b6007546040516020016132429181527f3100000000000000000000000000000000000000000000000000000000000000602082015260210190565b60405160208183030381529060405291505090565b600080600080600080600080600061326d613a5b565b60045490915060005b818110156133ff57600481815481106132915761329161441f565b906000526020600020906005020160010160149054906101000a900460ff16156133f757600481815481106132c8576132c861441f565b9060005260206000209060050201600401549350600584815481106132ef576132ef61441f565b9060005260206000209060050201600301548961330c9190614537565b9850828160405160200161332192919061456e565b60408051601f19818403018152919052805160209091012097506fffffffffffffffffffffffffffffffff808916975061335c906001614537565b6005858154811061336f5761336f61441f565b90600052602060002090600502016003015461338b91906143b7565b6133958a896143b7565b10156133f757600584815481106133ae576133ae61441f565b9060005260206000209060050201600401549550600584815481106133d5576133d561441f565b906000526020600020906005020160010160149054906101000a900460ff1694505b600101613276565b509399929850919650505050505050565b6134186121c0565b6001805460ff1916811790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258335b6040516001600160a01b03909116815260200160405180910390a1565b6000805b6004548110156134dc5783600482815481106134865761348661441f565b9060005260206000209060050201600001541480156134c85750600481815481106134b3576134b361441f565b90600052602060002090600502016003015483145b156134d4579050610666565b600101613468565b506040517fd950091500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613517613ae4565b6001805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33613447565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a085761357981613b36565b613584836020613b48565b6040516020016135959291906147f7565b60408051601f198184030181529082905262461bcd60e51b82526109f591600401614878565b6000806135ca87878786613d0d565b9050826136cf856000808267ffffffffffffffff1690506008817eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff16901b600882901c7eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff161790506010817dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff16901b601082901c7dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff161790506020817bffffffff00000000ffffffff00000000ffffffff00000000ffffffff16901b602082901c7bffffffff00000000ffffffff00000000ffffffff00000000ffffffff1617905080915050919050565b826040516020016137119392919092835260c09190911b77ffffffffffffffffffffffffffffffffffffffffffffffff19166020830152602882015260480190565b6040516020818303038152906040528051906020012091505095945050505050565b600080613741868686613d83565b9050613845836000808267ffffffffffffffff1690506008817eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff16901b600882901c7eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff161790506010817dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff16901b601082901c7dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff161790506020817bffffffff00000000ffffffff00000000ffffffff00000000ffffffff16901b602082901c7bffffffff00000000ffffffff00000000ffffffff00000000ffffffff1617905080915050919050565b8160405160200161388092919060c09290921b77ffffffffffffffffffffffffffffffffffffffffffffffff19168252600882015260280190565b60405160208183030381529060405280519060200120915050949350505050565b60006138ad828461469c565b60ff166001901b905092915050565b600060e083901c6138ce83602061469c565b60ff168163ffffffff16901c91505092915050565b6000806138f286868686613deb565b9050600061394d826040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b9050886001600160a01b0316613963828a613e36565b6001600160a01b0316149998505050505050505050565b6000806139878484613eb5565b905060006139e2826040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b9050866001600160a01b03166139f88288613e36565b6001600160a01b031614979650505050505050565b60008282604051602001613a3d92919091825260601b6bffffffffffffffffffffffff1916602082015260340190565b60405160208183030381529060405280519060200120905092915050565b6060613a65611823565b613a8257604051633788c6c160e11b815260040160405180910390fd5b6000613a8c611816565b60085490915067ffffffffffffffff808316600160401b9092041614613ac557604051636fbabc7760e01b815260040160405180910390fd5b600754604051602001613242918152600360fc1b602082015260210190565b60015460ff166118145760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016109f5565b60606106666001600160a01b03831660145b60606000613b578360026143b7565b613b62906002614537565b67ffffffffffffffff811115613b7a57613b7a6148ab565b6040519080825280601f01601f191660200182016040528015613ba4576020820181803683370190505b509050600360fc1b81600081518110613bbf57613bbf61441f565b60200101906001600160f81b031916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110613c0a57613c0a61441f565b60200101906001600160f81b031916908160001a9053506000613c2e8460026143b7565b613c39906001614537565b90505b6001811115613cbe577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110613c7a57613c7a61441f565b1a60f81b828281518110613c9057613c9061441f565b60200101906001600160f81b031916908160001a90535060049490941c93613cb7816148c1565b9050613c3c565b50831561208f5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109f5565b8260005b8551811015613d7a576000613d276002866143f7565b15613d33576000613d36565b60015b9050613d5d83888481518110613d4e57613d4e61441f565b60200260200101518387613ed1565b9250600185901c9450508080613d729061447e565b915050613d11565b50949350505050565b8160005b8451811015613de3576000613d9d6002856143f7565b6000149050613dc683878481518110613db857613db861441f565b602002602001015183613f31565b9250600184901c9350508080613ddb9061447e565b915050613d87565b509392505050565b604080516020810186905290810184905277ffffffffffffffffffffffffffffffffffffffffffffffff1960c084811b8216606084015283901b166068820152600090607001611e5d565b600080600080613e4585613f98565b6040805160008152602081018083528b905260ff8316918101919091526060810184905260808101839052929550909350915060019060a0016020604051602081039080840390855afa158015613ea0573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b6040805160208101849052908101829052600090606001613a3d565b60008215613f11576040805160208101849052908101869052606081018590526080016040516020818303038152906040528051906020012090506107f2565b604080516020810184905290810185905260608101869052608001611e5d565b60008115613f6a57604080516020810186905290810184905260600160405160208183030381529060405280519060200120905061208f565b5050604080516020808201939093528082019390935280518084038201815260609093019052815191012090565b60008060008351604114613fd8576040517f4be6321b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505060208101516040820151606090920151909260009190911a90565b50805460008255600502906000526020600020908101906120a091905b8082111561405b57600080825560018201805474ffffffffffffffffffffffffffffffffffffffffff1916905560028201819055600382018190556004820155600501614013565b5090565b60006020828403121561407157600080fd5b81356001600160e01b03198116811461208f57600080fd5b6001600160a01b03811681146120a057600080fd5b60ff811681146120a057600080fd5b600080604083850312156140c057600080fd5b82356140cb81614089565b915060208301356140db8161409e565b809150509250929050565b6000602082840312156140f857600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b818110156141825761416f838551805182526001600160a01b03602082015116602083015260ff6040820151166040830152606081015160608301526080810151608083015260a081015160a08301525050565b9284019260c0929092019160010161411b565b50909695505050505050565b600080604083850312156141a157600080fd5b8235915060208301356140db81614089565b803567ffffffffffffffff811681146141cb57600080fd5b919050565b600080604083850312156141e357600080fd5b823591506141f3602084016141b3565b90509250929050565b6000610100828403121561420f57600080fd5b50919050565b60008060006060848603121561422a57600080fd5b833567ffffffffffffffff8082111561424257600080fd5b61424e878388016141fc565b9450602086013591508082111561426457600080fd5b614270878388016141fc565b9350604086013591508082111561428657600080fd5b50614293868287016141fc565b9150509250925092565b6000806000606084860312156142b257600080fd5b83356142bd8161409e565b95602085013595506040909401359392505050565b600080600080608085870312156142e857600080fd5b8435935060208501356142fa8161409e565b93969395505050506040820135916060013590565b60008060006060848603121561432457600080fd5b833561432f8161409e565b9250602084013561433f8161409e565b9150604084013561434f8161409e565b809150509250925092565b60008060006060848603121561436f57600080fd5b8335925060208401359150604084013561434f8161409e565b60006020828403121561439a57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610666576106666143a1565b81810381811115610666576106666143a1565b634e487b7160e01b600052601260045260246000fd5b600082614406576144066143e1565b500690565b60008261441a5761441a6143e1565b500490565b634e487b7160e01b600052603260045260246000fd5b67ffffffffffffffff818116838216019080821115614456576144566143a1565b5092915050565b67ffffffffffffffff828116828216039080821115614456576144566143a1565b600060018201614490576144906143a1565b5060010190565b6000808335601e198436030181126144ae57600080fd5b83018035915067ffffffffffffffff8211156144c957600080fd5b6020019150600581901b36038213156144e157600080fd5b9250929050565b60c081016106668284805182526001600160a01b03602082015116602083015260ff6040820151166040830152606081015160608301526080810151608083015260a081015160a08301525050565b80820180821115610666576106666143a1565b60005b8381101561456557818101518382015260200161454d565b50506000910152565b6000835161458081846020880161454a565b9190910191825250602001919050565b600181815b808511156145cb5781600019048211156145b1576145b16143a1565b808516156145be57918102915b93841c9390800290614595565b509250929050565b6000826145e257506001610666565b816145ef57506000610666565b8160018114614605576002811461460f5761462b565b6001915050610666565b60ff841115614620576146206143a1565b50506001821b610666565b5060208310610133831016604e8410600b841016171561464e575081810a610666565b6146588383614590565b806000190482111561466c5761466c6143a1565b029392505050565b600061208f60ff8416836145d3565b60ff8181168382160190811115610666576106666143a1565b60ff8281168282160390811115610666576106666143a1565b61ffff828116828216039080821115614456576144566143a1565b600061208f61ffff8416836145d3565b6000602082840312156146f257600080fd5b61208f826141b3565b60008235607e1983360301811261471157600080fd5b9190910192915050565b60008060008060008060c0878903121561473457600080fd5b865161473f81614089565b60208801519096506147508161409e565b60408801519095506147618161409e565b6060880151909450801515811461477757600080fd5b809350506080870151915060a087015190509295509295509295565b6000808335601e198436030181126147aa57600080fd5b83018035915067ffffffffffffffff8211156147c557600080fd5b6020019150368190038213156144e157600080fd5b6000602082840312156147ec57600080fd5b813561208f81614089565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161482f81601785016020880161454a565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000601791840191820152835161486c81602884016020880161454a565b01602801949350505050565b602081526000825180602084015261489781604085016020870161454a565b601f01601f19169190910160400192915050565b634e487b7160e01b600052604160045260246000fd5b6000816148d0576148d06143a1565b50600019019056fea26469706673582212200f9f0a55ccd6f0cb7269fe52233ea174faebf4c052751953813f1866c96736b964736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000be212ea1a4978a64e8f7636ae18305c38ca092bd00000000000000000000000045a1502382541cd610cc9068e88727426b69629300000000000000000000000086de783bf23bc13daef5a55ec531c198da8f10cf
-----Decoded View---------------
Arg [0] : staking (address): 0xBe212EA1A4978a64e8f7636Ae18305C38CA092Bd
Arg [1] : postageContract (address): 0x45a1502382541Cd610CC9068e88727426b696293
Arg [2] : oracleContract (address): 0x86DE783Bf23Bc13DaeF5A55ec531C198da8f10cF
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000be212ea1a4978a64e8f7636ae18305c38ca092bd
Arg [1] : 00000000000000000000000045a1502382541cd610cc9068e88727426b696293
Arg [2] : 00000000000000000000000086de783bf23bc13daef5a55ec531c198da8f10cf
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 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.