Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 25 from a total of 3,530 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
Amount
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Claim | 7043219 | 462 days ago | IN | 0 ETH | 0.00125417 | ||||
| Reveal | 7043114 | 462 days ago | IN | 0 ETH | 0.00071752 | ||||
| Reveal | 7043113 | 462 days ago | IN | 0 ETH | 0.00075562 | ||||
| Reveal | 7043112 | 462 days ago | IN | 0 ETH | 0.00038986 | ||||
| Commit | 7043075 | 462 days ago | IN | 0 ETH | 0.00042269 | ||||
| Commit | 7043074 | 462 days ago | IN | 0 ETH | 0.00040812 | ||||
| Commit | 7043073 | 462 days ago | IN | 0 ETH | 0.00021974 | ||||
| Claim | 7043066 | 462 days ago | IN | 0 ETH | 0.00101681 | ||||
| Reveal | 7042962 | 462 days ago | IN | 0 ETH | 0.00051857 | ||||
| Commit | 7042925 | 462 days ago | IN | 0 ETH | 0.00048035 | ||||
| Claim | 7042914 | 462 days ago | IN | 0 ETH | 0.00201529 | ||||
| Reveal | 7042812 | 462 days ago | IN | 0 ETH | 0.00147922 | ||||
| Reveal | 7042812 | 462 days ago | IN | 0 ETH | 0.00146462 | ||||
| Reveal | 7042807 | 462 days ago | IN | 0 ETH | 0.00096653 | ||||
| Commit | 7042774 | 462 days ago | IN | 0 ETH | 0.00125286 | ||||
| Commit | 7042774 | 462 days ago | IN | 0 ETH | 0.00123402 | ||||
| Commit | 7042774 | 462 days ago | IN | 0 ETH | 0.00088309 | ||||
| Claim | 7042763 | 462 days ago | IN | 0 ETH | 0.00421734 | ||||
| Reveal | 7042656 | 462 days ago | IN | 0 ETH | 0.00317612 | ||||
| Reveal | 7042655 | 462 days ago | IN | 0 ETH | 0.00319408 | ||||
| Reveal | 7042655 | 462 days ago | IN | 0 ETH | 0.00201445 | ||||
| Commit | 7042620 | 462 days ago | IN | 0 ETH | 0.00307603 | ||||
| Commit | 7042619 | 462 days ago | IN | 0 ETH | 0.00291156 | ||||
| Commit | 7042619 | 462 days ago | IN | 0 ETH | 0.00208342 | ||||
| Claim | 7042611 | 462 days ago | IN | 0 ETH | 0.00645346 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
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 returns (bool);
}
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 heightOfAddress(address _owner) external view returns (uint8);
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;
uint8 height;
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, uint8 height);
/**
* @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 Output external call status
*/
event PriceAdjustmentSkipped(uint16 redundancyCount);
/**
* @dev Withdraw not successful in claim
*/
event WithdrawFailed(address owner);
/**
* @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);
uint8 _height = Stakes.heightOfAddress(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,
height: _height,
stake: _stake,
obfuscatedHash: _obfuscatedHash,
revealIndex: 0
})
);
emit Committed(_roundNumber, _overlay, _height);
}
/**
* @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];
uint8 depthResponsibility = _depth - revealedCommit.height;
// Check that commit is in proximity of the current anchor
if (!inProximity(revealedCommit.overlay, currentRevealRoundAnchor, depthResponsibility)) {
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 ** depthResponsibility),
hash: _hash
})
);
emit Revealed(
cr,
revealedCommit.overlay,
revealedCommit.stake,
revealedCommit.stake * uint256(2 ** depthResponsibility),
_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]);
// Do the check if the withdraw was success
(bool success, ) = address(PostageContract).call(
abi.encodeWithSignature("withdraw(address)", winnerSelected.owner)
);
if (!success) {
emit WithdrawFailed(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;
}
}
bool success = OracleContract.adjustPrice(uint16(redundancyCount));
if (!success) {
emit PriceAdjustmentSkipped(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);
uint8 _depthResponsibility = _depth - Stakes.heightOfAddress(_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(), _depthResponsibility);
}
// ----------------------------- 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 setPrice(uint256 _price) 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 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 ABI
API[{"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"},{"indexed":false,"internalType":"uint8","name":"height","type":"uint8"}],"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":"uint16","name":"redundancyCount","type":"uint16"}],"name":"PriceAdjustmentSkipped","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":"address","name":"owner","type":"address"}],"name":"WithdrawFailed","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":"uint8","name":"height","type":"uint8"},{"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
60806040526008805462ffffff60c01b19166264020160c01b1790557dba1914b54e0348a1028d1a103a95ed55c4004b9d332400000000000000006009553480156200004a57600080fd5b5060405162004e1538038062004e158339810160408190526200006d916200019d565b60018054600380546001600160a01b03199081166001600160a01b03888116919091179092556001600160a81b0319909216610100868316021790925560028054909116918316919091179055620000c7600033620000d0565b505050620001e7565b620000dc8282620000e0565b5050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16620000dc576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556200013c3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b80516001600160a01b03811681146200019857600080fd5b919050565b600080600060608486031215620001b357600080fd5b620001be8462000180565b9250620001ce6020850162000180565b9150620001de6040850162000180565b90509250925092565b614c1e80620001f76000396000f3fe608060405234801561001057600080fd5b50600436106102775760003560e01c806377c75d1011610160578063b6cd5822116100d8578063dfbf53ae1161008c578063f69ee1d111610071578063f69ee1d1146105df578063f7b188a5146105f2578063fb00f2f3146105fa57600080fd5b8063dfbf53ae1461059c578063f4e6fcca146105cc57600080fd5b8063ce987745116100bd578063ce9877451461056e578063d1e8b63d14610581578063d547741f1461058957600080fd5b8063b6cd582214610541578063c46b40291461055457600080fd5b80638456cb591161012f5780638d8b6428116101145780638d8b6428146104fa57806391d1485414610502578063a217fddf1461053957600080fd5b80638456cb59146104ea5780638a19c8bc146104f257600080fd5b806377c75d10146104645780637fe019c61461047757806382b39b1b1461049257806383220626146104e257600080fd5b80635c975abb116101f357806364c34a85116101c257806369da9114116101a757806369da9114146103de5780636f94aaf2146103f157806372286cba1461040c57600080fd5b806364c34a85146103a957806369bfac01146103b157600080fd5b80635c975abb146103705780635d4844ea1461037b57806362fd29ae1461038e57806363f5cf7c1461039657600080fd5b80632a4e62491161024a5780632f3906da1161022f5780632f3906da1461034257806336568abe1461034a5780635838d6731461035d57600080fd5b80632a4e6249146103185780632f2ff15d1461032d57600080fd5b806301ffc9a71461027c5780631736d472146102a457806318350096146102b7578063248a9ca3146102e7575b600080fd5b61028f61028a36600461431f565b61060d565b60405190151581526020015b60405180910390f35b61028f6102b236600461436d565b610676565b6001546102cf9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161029b565b61030a6102f53660046143a6565b60009081526020819052604090206001015490565b60405190815260200161029b565b610320610883565b60405161029b91906143bf565b61034061033b36600461444e565b610990565b005b61028f6109ba565b61034061035836600461444e565b610a04565b61034061036b366004614490565b610a95565b60015460ff1661028f565b6003546102cf906001600160a01b031681565b61030a611032565b6103406103a43660046144d5565b6110fe565b61030a611533565b6008546103c59067ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161029b565b6002546102cf906001600160a01b031681565b6008546103c590600160801b900467ffffffffffffffff1681565b61041f61041a3660046143a6565b611613565b604080519788526001600160a01b0390961660208801529315159486019490945260ff9091166060850152608084015260a083019190915260c082015260e00161029b565b61028f6104723660046143a6565b611671565b6008546103c590600160401b900467ffffffffffffffff1681565b6104a56104a03660046143a6565b611921565b604080519687526001600160a01b03909516602087015260ff909316938501939093526060840152608083019190915260a082015260c00161029b565b61030a611978565b610340611983565b6103c56119dc565b61028f6119e9565b61028f61051036600461444e565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b61030a600081565b61034061054f36600461455d565b611a13565b61055c611f6d565b60405160ff909116815260200161029b565b61030a61057c366004614592565b611ff2565b61028f612061565b61034061059736600461444e565b612086565b600a54600b54600c54600d54600e546104a594936001600160a01b03811693600160a01b90910460ff1692909186565b6103406105da3660046145cf565b6120ab565b6103406105ed3660046143a6565b612192565b6103406121e6565b61028f61060836600461461a565b61223d565b60006001600160e01b031982167f7965db0b00000000000000000000000000000000000000000000000000000000148061067057507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b60035460405163d1052d1f60e01b81526001600160a01b038481166004830152600092839291169063d1052d1f90602401602060405180830381865afa1580156106c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e89190614648565b600354604051631d54805360e01b81526001600160a01b03878116600483015292935060009290911690631d54805390602401602060405180830381865afa158015610738573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075c9190614661565b6107669085614694565b90506107706109ba565b156107a7576040517fe2586bcc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816000036107c7576040516273e5c360e31b815260040160405180910390fd5b6107d3609860026146ad565b6107dd90436146c4565b82106107fc57604051630a0744c560e01b815260040160405180910390fd5b6003546040516397adedb560e01b81526001600160a01b03878116600483015261087a9216906397adedb590602401602060405180830381865afa158015610848573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086c9190614648565b610874611533565b8361223d565b95945050505050565b606061088d6119e9565b6108aa57604051633788c6c160e11b815260040160405180910390fd5b60006108b46119dc565b60085490915067ffffffffffffffff808316600160401b90920416146108ed57604051636fbabc7760e01b815260040160405180910390fd5b6005805480602002602001604051908101604052809291908181526020016000905b828210156109865760008481526020908190206040805160c08101825260058602909201805483526001808201546001600160a01b03811685870152600160a01b900460ff169284019290925260028101546060840152600381015460808401526004015460a0830152908352909201910161090f565b5050505091505090565b6000828152602081905260409020600101546109ab8161227a565b6109b58383612287565b505050565b6000806109c86098436146ed565b90506109d660046098614701565b81101580156109ef57506109ec60026098614701565b81105b156109fc57600191505090565b600091505090565b6001600160a01b0381163314610a875760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b610a918282612325565b5050565b610a9d6123a4565b6000610aa76119dc565b6003546040516397adedb560e01b81523360048201529192506000916001600160a01b03909116906397adedb590602401602060405180830381865afa158015610af5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b199190614648565b6003546040517f830a053e0000000000000000000000000000000000000000000000000000000081523360048201529192506000916001600160a01b039091169063830a053e90602401602060405180830381865afa158015610b80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba49190614648565b60035460405163d1052d1f60e01b81523360048201529192506000916001600160a01b039091169063d1052d1f90602401602060405180830381865afa158015610bf2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c169190614648565b600354604051631d54805360e01b81523360048201529192506000916001600160a01b0390911690631d54805390602401602060405180830381865afa158015610c64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c889190614661565b9050610c92612061565b610cc8576040517fdc816a8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001610cd660046098614701565b610ce091906146c4565b610ceb6098436146ed565b03610d22576040517f5baef6b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8567ffffffffffffffff168567ffffffffffffffff161115610d70576040517f50ff7c0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8567ffffffffffffffff168567ffffffffffffffff161015610dbe576040517f7a0c0fd600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81600003610dde576040516273e5c360e31b815260040160405180910390fd5b610dea609860026146ad565b610df490436146c4565b8210610e1357604051630a0744c560e01b815260040160405180910390fd5b60085467ffffffffffffffff868116911614610e5357610e356004600061423d565b6008805467ffffffffffffffff191667ffffffffffffffff87161790555b60045460005b81811015610ec6578560048281548110610e7557610e75614715565b90600052602060002090600502016000015403610ebe576040517fbfec555800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600101610e59565b5060046040518060e00160405280878152602001336001600160a01b031681526020016000151581526020018460ff1681526020018681526020018a8152602001600081525090806001815401808255809150506001900390600052602060002090600502016000909190919091506000820151816000015560208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160146101000a81548160ff02191690831515021790555060608201518160010160156101000a81548160ff021916908360ff1602179055506080820151816002015560a0820151816003015560c0820151816004015550507faadc88121471799d39ee2bbe1dd30a4ab57510e2a33bd6e537de5fafd2daa8868786846040516110209392919067ffffffffffffffff939093168352602083019190915260ff16604082015260600190565b60405180910390a15050505050505050565b60008061103d6119dc565b61104890600161472b565b6007546008549192509061106e90600160401b900467ffffffffffffffff16600161472b565b67ffffffffffffffff168267ffffffffffffffff161115610670576008546000906001906110ad90600160401b900467ffffffffffffffff1685614753565b6110b79190614753565b67ffffffffffffffff16905081816040516020016110df929190918252602082015260400190565b6040516020818303038152906040528051906020012091505092915050565b6111066123a4565b61110e6123f7565b6040805160c081018252600a548152600b546001600160a01b0381166020830152600160a01b900460ff1691810191909152600c546060820152600d546080820152600e5460a0820152600654600754600091829161116e600f826146ed565b935061117b600e826146ed565b9250838310611192578261118e81614774565b9350505b6111a5866020013583876040015161223d565b6111c557604051633b5f43a360e01b815260036004820152602401610a7e565b6111d086601e612a66565b6111d986612d78565b6111e286613085565b6111f5886020013583876040015161223d565b61121557604051633b5f43a360e01b815260026004820152602401610a7e565b611229886112248660026146ad565b612a66565b61123288612d78565b61123b88613085565b61124e876020013583876040015161223d565b61126e57604051633b5f43a360e01b815260016004820152602401610a7e565b61127d876112248560026146ad565b61128687612d78565b61128f87613085565b611305848461129e8b8061478d565b60008181106112af576112af614715565b602002919091013590506112c38b8061478d565b60008181106112d4576112d4614715565b602002919091013590506112e88b8061478d565b60008181106112f9576112f9614715565b90506020020135613319565b61132f611312878061478d565b600081811061132357611323614715565b905060200201356133a6565b60015460208601516040516001600160a01b03918216602482015260009261010090049091169060440160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f51cff8d900000000000000000000000000000000000000000000000000000000179052516113bc9190614802565b6000604051808303816000865af19150503d80600081146113f9576040519150601f19603f3d011682016040523d82523d6000602084013e6113fe565b606091505b5050905080611449576020808701516040516001600160a01b0390911681527f7ae187a0c04cf55b655ca83fa11d37854c882bf1fdcb588469b414731bb0e05a910160405180910390a15b7f788e77979e6e6a8a6a5d2c19c58b1ff9671298f54c85ac6f6aa30379aed5861a86604051611478919061481e565b60405180910390a17fbee3fc8a3523c1a65fa9308ce1f2b8fd90c24975b141b754603194597846e4dd60018054906101000a90046001600160a01b03166001600160a01b0316638a5e8e326040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115169190614648565b6040519081526020015b60405180910390a1505050505050505050565b600061153d612061565b8061157b5750600854600160401b900467ffffffffffffffff1661155f6119dc565b67ffffffffffffffff1611801561157b57506115796119e9565b155b1561158d57611588611978565b905090565b6115956119e9565b156115a257611588611032565b6115aa6109ba565b80156115d95750600854600160401b900467ffffffffffffffff166115cd6119dc565b67ffffffffffffffff16145b15611610576040517f36b7884b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b90565b6004818154811061162357600080fd5b6000918252602090912060059091020180546001820154600283015460038401546004909401549294506001600160a01b0382169360ff600160a01b8404811694600160a81b909404169287565b600061167b6119e9565b61169857604051633788c6c160e11b815260040160405180910390fd5b60006116a26119dc565b60085490915067ffffffffffffffff808316600160401b90920416146116db57604051636fbabc7760e01b815260040160405180910390fd5b60085467ffffffffffffffff600160801b90910481169082161161171257604051630c8d9eab60e31b815260040160405180910390fd5b6000806000806000806000806117266133e4565b9050600061173261349e565b600454919650945060005b8181101561190d576004818154811061175857611758614715565b90600052602060002090600502016004015494506004818154811061177f5761177f614715565b906000526020600020906005020160010160149054906101000a900460ff1680156117cd5750600585815481106117b8576117b8614715565b90600052602060002090600502016004015487145b801561180b5750600585815481106117e7576117e7614715565b600091825260209091206001600590920201015460ff878116600160a01b90920416145b15611905576005858154811061182357611823614715565b9060005260206000209060050201600301548b611840919061486d565b9a508383604051602001611855929190614880565b60408051601f19818403018152919052805160209091012098506fffffffffffffffffffffffffffffffff808a16985061189090600161486d565b600586815481106118a3576118a3614715565b9060005260206000209060050201600301546118bf91906146ad565b6118c98c8a6146ad565b10156118f757600585815481106118e2576118e2614715565b90600052602060002090600502016000015499505b8261190181614774565b9350505b60010161173d565b505050959099149998505050505050505050565b6005818154811061193157600080fd5b6000918252602090912060059091020180546001820154600283015460038401546004909401549294506001600160a01b03821693600160a01b90920460ff169290919086565b6000806110486119dc565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166119d257604051631d77d47760e21b815260040160405180910390fd5b6119da613657565b565b6000611588609843614701565b60006119f760026098614701565b611a026098436146ed565b10611a0d5750600190565b50600090565b611a1b6123a4565b6000611a256119dc565b6003546040516397adedb560e01b81523360048201529192506000916001600160a01b03909116906397adedb590602401602060405180830381865afa158015611a73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a979190614648565b9050611aa1611f6d565b60ff168560ff161015611ae0576040517f83d9b7bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ae86109ba565b611b1e576040517fd1088db600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085467ffffffffffffffff838116911614611b66576040517f842a9e0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085467ffffffffffffffff838116600160401b9092041614611c4e57611b8b611533565b600655611b9a6005600061425e565b600880547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff16600160401b67ffffffffffffffff8516908102919091179091556006546040805192835260208301919091527ff0ae472da9c8da86bda4991a549c03a3cb328b5f360ea11a5b8814f32bb85176910160405180910390a1611c4e600754604080516020810192909252449082015260600160408051601f198184030181529190528051602090910120600755565b6000611c5c82878787611ff2565b90506000611c6a83836136ab565b9050600060048281548110611c8157611c81614715565b600091825260208083206040805160e08101825260059094029091018054845260018101546001600160a01b0381169385019390935260ff600160a01b84048116151592850192909252600160a81b909204166060830181905260028201546080840152600382015460a084015260049091015460c0830152909250611d07908a614694565b9050611d1a82600001516006548361223d565b611d56576006546040517f14ebbbe4000000000000000000000000000000000000000000000000000000008152600401610a7e91815260200190565b816040015115611d92576040517fa89ac15100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160048481548110611da757611da7614715565b906000526020600020906005020160010160146101000a81548160ff02191690831515021790555060058054905060048481548110611de857611de8614715565b90600052602060002090600502016004018190555060056040518060c001604052808460000151815260200184602001516001600160a01b031681526020018b60ff16815260200184608001518152602001836002611e479190614986565b8560800151611e5691906146ad565b815260209081018b90528254600181810185556000948552938290208351600590920201908155908201519281018054604084015160ff16600160a01b0274ffffffffffffffffffffffffffffffffffffffffff199091166001600160a01b0390951694909417939093179092556060810151600280840191909155608080830151600385015560a0909201516004909301929092558351908401517f13fc17fd71632266fe82092de6dd91a06b4fa68d8dc950492e5421cbed55a6a59289929190611f23908690614986565b8660800151611f3291906146ad565b6040805167ffffffffffffffff90951685526020850193909352918301526060820152608081018a905260ff8b1660a082015260c001611520565b6008546000908190611f929067ffffffffffffffff600160801b820481169116614753565b67ffffffffffffffff169050600060fe8211611fae5781611fb1565b60fe5b611fbc906001614995565b600b5490915060ff600160a01b9091048116908216811115611fe757611fe28282614694565b611fea565b60005b935050505090565b60408051602081018690527fff0000000000000000000000000000000000000000000000000000000000000060f886901b169181019190915260418101839052606181018290526000906081015b6040516020818303038152906040528051906020012090505b949350505050565b600061206f60046098614701565b61207a6098436146ed565b1015611a0d5750600190565b6000828152602081905260409020600101546120a18161227a565b6109b58383612325565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166120fa57604051637bfa4b9f60e01b815260040160405180910390fd5b600880547fffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b60ff958616027fffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffff1617600160c81b93851693909302929092177fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff16600160d01b9190931602919091179055565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166121e157604051637bfa4b9f60e01b815260040160405180910390fd5b600955565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661223557604051631d77d47760e21b815260040160405180910390fd5b6119da613756565b60008160ff1660000361225257506001612273565b61226160ff83166101006149ae565b61226c9060026149c9565b8484181090505b9392505050565b612284813361378f565b50565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a91576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556122e13390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1615610a91576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60015460ff16156119da5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610a7e565b60006124016119dc565b905061240b6119e9565b61242857604051633788c6c160e11b815260040160405180910390fd5b60085467ffffffffffffffff828116600160401b909204161461245e57604051636fbabc7760e01b815260040160405180910390fd5b60085467ffffffffffffffff600160801b90910481169082161161249557604051630c8d9eab60e31b815260040160405180910390fd5b600454604051818152600091829182918291829182917f6752c5e71c95fb93bc7137adeb115a33fa4e54e2683e33d3f90c2bb1c4b6c2a59060200160405180910390a16005546040519081527f4c03de6a759749c0c9387b7014634dc5c6af610e1366023d90751c783a998f8d9060200160405180910390a161251661349e565b6040805183815260ff831660208201529295509093507f34e8eda4cd857cd2865becf58a47748f31415f4a382cbb2cc0c64b9a27c717be910160405180910390a160006125616133e4565b905060005b8281101561294e5760006004828154811061258357612583614715565b600091825260208083206040805160e08101825260059485029092018054835260018101546001600160a01b0381169484019490945260ff600160a01b85048116151592840192909252600160a81b90930416606082015260028201546080820152600382015460a082015260049091015460c0820181905282549194509291908390811061261457612614614715565b60009182526020918290206040805160c0810182526005939093029091018054835260018101546001600160a01b03811694840194909452600160a01b90930460ff1682820152600283015460608301526003830154608083015260049092015460a082015290840151909150801561269057508060a0015188145b80156126a55750806040015160ff168760ff16145b1561279a5760808101516126b9908d61486d565b9b50848b6040516020016126ce929190614880565b60408051601f19818403018152919052805160209091012099506fffffffffffffffffffffffffffffffff808b16995061270990600161486d565b816080015161271891906146ad565b6127228d8b6146ad565b101561278c578051600a556020810151600b8054604084015160ff16600160a01b0274ffffffffffffffffffffffffffffffffffffffffff199091166001600160a01b03909316929092179190911790556060810151600c556080810151600d5560a0810151600e555b8a61279681614774565b9b50505b826040015180156127c357508060a00151881415806127c35750806040015160ff168760ff1614155b80156127e45750600854600160d01b900460ff166127e26064446146ed565b105b156128905760035460208201516001600160a01b039091169063d009b2d69061280e8a6002614986565b60085461282790609890600160c01b900460ff166146ad565b61283191906146ad565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561287757600080fd5b505af115801561288b573d6000803e3d6000fd5b505050505b82604001516129405760035460208401516001600160a01b039091169063d009b2d6906128be8a6002614986565b6008546128d790609890600160c81b900460ff166146ad565b6128e191906146ad565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561292757600080fd5b505af115801561293b573d6000803e3d6000fd5b505050505b836001019350505050612566565b506002546040517fffb98fe300000000000000000000000000000000000000000000000000000000815261ffff891660048201526000916001600160a01b03169063ffb98fe3906024016020604051808303816000875af11580156129b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129db91906149e9565b905080612a1a5760405161ffff891681527f20378e5d379eabfa30444ecc5eb2b87d0d77bdbf5a58d80d008673b0ca6421419060200160405180910390a15b50506008805467ffffffffffffffff909916600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff9099169890981790975550505050505050565b600754600090612a78906080906146ed565b90506000612adb612a8c60a086018661478d565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505050606086013584612ad360a0890160808a01614a04565b600654613802565b60408051858152602081018390529192507f94e252069a85aa79db21f5bd8ca4e14dd3a3927aa492711017a2c8ddad95af00910160405180910390a1612b63612b24858061478d565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050505060208601358561040061397a565b600e5414612b8e5760405163755f0a2560e01b81526001600482015260248101829052604401610a7e565b612b9b60a085018561478d565b6000818110612bac57612bac614715565b90506020020135848060400190612bc3919061478d565b6000818110612bd457612bd4614715565b9050602002013514612c035760405163755f0a2560e01b81526002600482015260248101829052604401610a7e565b600080612c1360e087018761478d565b905011612c24578460200135612c59565b612c3160e086018661478d565b6000818110612c4257612c42614715565b9050602002810190612c549190614a1f565b606001355b9050612cb7612c6b604087018761478d565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505050606087013585612cb260a08a0160808b01614a04565b61397a565b8114612ce05760405163755f0a2560e01b81526003600482015260248101839052604401610a7e565b6000612cef60e087018761478d565b90501115612d275760408051602080880135908201529081018390526060016040516020818303038152906040528051906020012091505b81612d32868061478d565b6000818110612d4357612d43614715565b9050602002013514612d715760405163755f0a2560e01b815260048181015260248101839052604401610a7e565b5050505050565b6001546000908190819061010090046001600160a01b031663c81e25ab612da260c0870187614a1f565b602001356040518263ffffffff1660e01b8152600401612dc491815260200190565b60c060405180830381865afa158015612de1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e059190614a35565b509396509194509250506001600160a01b0384169050612e6557612e2c60c0850185614a1f565b602001356040517f2396d34e000000000000000000000000000000000000000000000000000000008152600401610a7e91815260200190565b6000612e88612e7760c0870187614a1f565b611610906060810190604001614a04565b90506000612e968484613ae8565b9050808263ffffffff1610612eeb57612eb260c0870187614a1f565b602001356040517f1362e4a0000000000000000000000000000000000000000000000000000000008152600401610a7e91815260200190565b6000612f1a612efd60c0890189614a1f565b612f0e906060810190604001614a04565b60201c63ffffffff1690565b90506000612f2c886020013586613b03565b63ffffffff16905067ffffffffffffffff82168114612f8b57612f5260c0890189614a1f565b602001356040517f6dd6a24f000000000000000000000000000000000000000000000000000000008152600401610a7e91815260200190565b61303187612f9c60c08b018b614a1f565b612fa69080614aa3565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050505060208b0135612fec60c08d018d614a1f565b60200135612ffd60c08e018e614a1f565b61300e906060810190604001614a04565b61301b60c08f018f614a1f565b61302c906080810190606001614a04565b613b2a565b61307b5761304260c0890189614a1f565b602001356040517fdb12fb9d000000000000000000000000000000000000000000000000000000008152600401610a7e91815260200190565b5050505050505050565b61309260e082018261478d565b905060000361309e5750565b6131bf6130ae60e083018361478d565b60008181106130bf576130bf614715565b90506020028101906130d19190614a1f565b6130df906020810190614aea565b6130ec60e084018461478d565b60008181106130fd576130fd614715565b905060200281019061310f9190614a1f565b61311d906020810190614aa3565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061315f9250505060e085018561478d565b600081811061317057613170614715565b90506020028101906131829190614a1f565b6040013561319360e086018661478d565b60008181106131a4576131a4614715565b90506020028101906131b69190614a1f565b60600135613bc1565b61322c576131d060e082018261478d565b60008181106131e1576131e1614715565b90506020028101906131f39190614a1f565b606001356040517fd740df61000000000000000000000000000000000000000000000000000000008152600401610a7e91815260200190565b60208101356132ab61324160e084018461478d565b600081811061325257613252614715565b90506020028101906132649190614a1f565b6040013561327560e085018561478d565b600081811061328657613286614715565b90506020028101906132989190614a1f565b6132a6906020810190614aea565b613c54565b14612284576132bd60e082018261478d565b60008181106132ce576132ce614715565b90506020028101906132e09190614a1f565b606001356040517f82f2469d000000000000000000000000000000000000000000000000000000008152600401610a7e91815260200190565b838510156133665781831061334157604051633d386eb360e11b815260040160405180910390fd5b80821061336157604051633588c6d360e11b815260040160405180910390fd5b612d71565b82821061338657604051633d386eb360e11b815260040160405180910390fd5b808310612d7157604051633588c6d360e11b815260040160405180910390fd5b6009548110612284576040517fb6052cdf00000000000000000000000000000000000000000000000000000000815260048101829052602401610a7e565b60606133ee6119e9565b61340b57604051633788c6c160e11b815260040160405180910390fd5b60006134156119dc565b60085490915067ffffffffffffffff808316600160401b909204161461344e57604051636fbabc7760e01b815260040160405180910390fd5b6007546040516020016134899181527f3100000000000000000000000000000000000000000000000000000000000000602082015260210190565b60405160208183030381529060405291505090565b60008060008060008060008060006134b4613ca2565b60045490915060005b8181101561364657600481815481106134d8576134d8614715565b906000526020600020906005020160010160149054906101000a900460ff161561363e576004818154811061350f5761350f614715565b90600052602060002090600502016004015493506005848154811061353657613536614715565b90600052602060002090600502016003015489613553919061486d565b98508281604051602001613568929190614880565b60408051601f19818403018152919052805160209091012097506fffffffffffffffffffffffffffffffff80891697506135a390600161486d565b600585815481106135b6576135b6614715565b9060005260206000209060050201600301546135d291906146ad565b6135dc8a896146ad565b101561363e57600584815481106135f5576135f5614715565b90600052602060002090600502016004015495506005848154811061361c5761361c614715565b906000526020600020906005020160010160149054906101000a900460ff1694505b6001016134bd565b509399929850919650505050505050565b61365f6123a4565b6001805460ff1916811790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258335b6040516001600160a01b03909116815260200160405180910390a1565b6000805b6004548110156137235783600482815481106136cd576136cd614715565b90600052602060002090600502016000015414801561370f5750600481815481106136fa576136fa614715565b90600052602060002090600502016003015483145b1561371b579050610670565b6001016136af565b506040517fd950091500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61375e613d2b565b6001805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa3361368e565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a91576137c081613d7d565b6137cb836020613d8f565b6040516020016137dc929190614b07565b60408051601f198184030181529082905262461bcd60e51b8252610a7e91600401614b88565b60008061381187878786613f54565b905082613916856000808267ffffffffffffffff1690506008817eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff16901b600882901c7eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff161790506010817dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff16901b601082901c7dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff161790506020817bffffffff00000000ffffffff00000000ffffffff00000000ffffffff16901b602082901c7bffffffff00000000ffffffff00000000ffffffff00000000ffffffff1617905080915050919050565b826040516020016139589392919092835260c09190911b77ffffffffffffffffffffffffffffffffffffffffffffffff19166020830152602882015260480190565b6040516020818303038152906040528051906020012091505095945050505050565b600080613988868686613fca565b9050613a8c836000808267ffffffffffffffff1690506008817eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff16901b600882901c7eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff161790506010817dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff16901b601082901c7dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff161790506020817bffffffff00000000ffffffff00000000ffffffff00000000ffffffff16901b602082901c7bffffffff00000000ffffffff00000000ffffffff00000000ffffffff1617905080915050919050565b81604051602001613ac792919060c09290921b77ffffffffffffffffffffffffffffffffffffffffffffffff19168252600882015260280190565b60405160208183030381529060405280519060200120915050949350505050565b6000613af48284614694565b60ff166001901b905092915050565b600060e083901c613b15836020614694565b60ff168163ffffffff16901c91505092915050565b600080613b3986868686614032565b90506000613b94826040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b9050886001600160a01b0316613baa828a61407d565b6001600160a01b0316149998505050505050505050565b600080613bce84846140fc565b90506000613c29826040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b9050866001600160a01b0316613c3f828861407d565b6001600160a01b031614979650505050505050565b60008282604051602001613c8492919091825260601b6bffffffffffffffffffffffff1916602082015260340190565b60405160208183030381529060405280519060200120905092915050565b6060613cac6119e9565b613cc957604051633788c6c160e11b815260040160405180910390fd5b6000613cd36119dc565b60085490915067ffffffffffffffff808316600160401b9092041614613d0c57604051636fbabc7760e01b815260040160405180910390fd5b600754604051602001613489918152600360fc1b602082015260210190565b60015460ff166119da5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610a7e565b60606106706001600160a01b03831660145b60606000613d9e8360026146ad565b613da990600261486d565b67ffffffffffffffff811115613dc157613dc1614bbb565b6040519080825280601f01601f191660200182016040528015613deb576020820181803683370190505b509050600360fc1b81600081518110613e0657613e06614715565b60200101906001600160f81b031916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110613e5157613e51614715565b60200101906001600160f81b031916908160001a9053506000613e758460026146ad565b613e8090600161486d565b90505b6001811115613f05577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110613ec157613ec1614715565b1a60f81b828281518110613ed757613ed7614715565b60200101906001600160f81b031916908160001a90535060049490941c93613efe81614bd1565b9050613e83565b5083156122735760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610a7e565b8260005b8551811015613fc1576000613f6e6002866146ed565b15613f7a576000613f7d565b60015b9050613fa483888481518110613f9557613f95614715565b60200260200101518387614118565b9250600185901c9450508080613fb990614774565b915050613f58565b50949350505050565b8160005b845181101561402a576000613fe46002856146ed565b600014905061400d83878481518110613fff57613fff614715565b602002602001015183614178565b9250600184901c935050808061402290614774565b915050613fce565b509392505050565b604080516020810186905290810184905277ffffffffffffffffffffffffffffffffffffffffffffffff1960c084811b8216606084015283901b166068820152600090607001612040565b60008060008061408c856141df565b6040805160008152602081018083528b905260ff8316918101919091526060810184905260808101839052929550909350915060019060a0016020604051602081039080840390855afa1580156140e7573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b6040805160208101849052908101829052600090606001613c84565b6000821561415857604080516020810184905290810186905260608101859052608001604051602081830303815290604052805190602001209050612059565b604080516020810184905290810185905260608101869052608001612040565b600081156141b1576040805160208101869052908101849052606001604051602081830303815290604052805190602001209050612273565b5050604080516020808201939093528082019390935280518084038201815260609093019052815191012090565b6000806000835160411461421f576040517f4be6321b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505060208101516040820151606090920151909260009190911a90565b5080546000825560050290600052602060002090810190612284919061427f565b508054600082556005029060005260206000209081019061228491906142d6565b5b808211156142d25760008082556001820180547fffffffffffffffffffff0000000000000000000000000000000000000000000016905560028201819055600382018190556004820155600501614280565b5090565b5b808211156142d257600080825560018201805474ffffffffffffffffffffffffffffffffffffffffff19169055600282018190556003820181905560048201556005016142d7565b60006020828403121561433157600080fd5b81356001600160e01b03198116811461227357600080fd5b6001600160a01b038116811461228457600080fd5b60ff8116811461228457600080fd5b6000806040838503121561438057600080fd5b823561438b81614349565b9150602083013561439b8161435e565b809150509250929050565b6000602082840312156143b857600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b818110156144425761442f838551805182526001600160a01b03602082015116602083015260ff6040820151166040830152606081015160608301526080810151608083015260a081015160a08301525050565b9284019260c092909201916001016143db565b50909695505050505050565b6000806040838503121561446157600080fd5b82359150602083013561439b81614349565b803567ffffffffffffffff8116811461448b57600080fd5b919050565b600080604083850312156144a357600080fd5b823591506144b360208401614473565b90509250929050565b600061010082840312156144cf57600080fd5b50919050565b6000806000606084860312156144ea57600080fd5b833567ffffffffffffffff8082111561450257600080fd5b61450e878388016144bc565b9450602086013591508082111561452457600080fd5b614530878388016144bc565b9350604086013591508082111561454657600080fd5b50614553868287016144bc565b9150509250925092565b60008060006060848603121561457257600080fd5b833561457d8161435e565b95602085013595506040909401359392505050565b600080600080608085870312156145a857600080fd5b8435935060208501356145ba8161435e565b93969395505050506040820135916060013590565b6000806000606084860312156145e457600080fd5b83356145ef8161435e565b925060208401356145ff8161435e565b9150604084013561460f8161435e565b809150509250925092565b60008060006060848603121561462f57600080fd5b8335925060208401359150604084013561460f8161435e565b60006020828403121561465a57600080fd5b5051919050565b60006020828403121561467357600080fd5b81516122738161435e565b634e487b7160e01b600052601160045260246000fd5b60ff82811682821603908111156106705761067061467e565b80820281158282048414176106705761067061467e565b818103818111156106705761067061467e565b634e487b7160e01b600052601260045260246000fd5b6000826146fc576146fc6146d7565b500690565b600082614710576147106146d7565b500490565b634e487b7160e01b600052603260045260246000fd5b67ffffffffffffffff81811683821601908082111561474c5761474c61467e565b5092915050565b67ffffffffffffffff82811682821603908082111561474c5761474c61467e565b6000600182016147865761478661467e565b5060010190565b6000808335601e198436030181126147a457600080fd5b83018035915067ffffffffffffffff8211156147bf57600080fd5b6020019150600581901b36038213156147d757600080fd5b9250929050565b60005b838110156147f95781810151838201526020016147e1565b50506000910152565b600082516148148184602087016147de565b9190910192915050565b60c081016106708284805182526001600160a01b03602082015116602083015260ff6040820151166040830152606081015160608301526080810151608083015260a081015160a08301525050565b808201808211156106705761067061467e565b600083516148928184602088016147de565b9190910191825250602001919050565b600181815b808511156148dd5781600019048211156148c3576148c361467e565b808516156148d057918102915b93841c93908002906148a7565b509250929050565b6000826148f457506001610670565b8161490157506000610670565b816001811461491757600281146149215761493d565b6001915050610670565b60ff8411156149325761493261467e565b50506001821b610670565b5060208310610133831016604e8410600b8410161715614960575081810a610670565b61496a83836148a2565b806000190482111561497e5761497e61467e565b029392505050565b600061227360ff8416836148e5565b60ff81811683821601908111156106705761067061467e565b61ffff82811682821603908082111561474c5761474c61467e565b600061227361ffff8416836148e5565b8051801515811461448b57600080fd5b6000602082840312156149fb57600080fd5b612273826149d9565b600060208284031215614a1657600080fd5b61227382614473565b60008235607e1983360301811261481457600080fd5b60008060008060008060c08789031215614a4e57600080fd5b8651614a5981614349565b6020880151909650614a6a8161435e565b6040880151909550614a7b8161435e565b9350614a89606088016149d9565b92506080870151915060a087015190509295509295509295565b6000808335601e19843603018112614aba57600080fd5b83018035915067ffffffffffffffff821115614ad557600080fd5b6020019150368190038213156147d757600080fd5b600060208284031215614afc57600080fd5b813561227381614349565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351614b3f8160178501602088016147de565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351614b7c8160288401602088016147de565b01602801949350505050565b6020815260008251806020840152614ba78160408501602087016147de565b601f01601f19169190910160400192915050565b634e487b7160e01b600052604160045260246000fd5b600081614be057614be061467e565b50600019019056fea2646970667358221220e6d529c753301d40b88db1b0768955eec9895788418077bb895e8f7739fb1b6964736f6c634300081300330000000000000000000000002e9873b73376d20c54e4990b317ceaa7f2ab87c3000000000000000000000000cdfdc3752caaa826fe62531e0000c40546ec56a600000000000000000000000047b134d38ab0a89d561cf393fc370f2099ae0c4b
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102775760003560e01c806377c75d1011610160578063b6cd5822116100d8578063dfbf53ae1161008c578063f69ee1d111610071578063f69ee1d1146105df578063f7b188a5146105f2578063fb00f2f3146105fa57600080fd5b8063dfbf53ae1461059c578063f4e6fcca146105cc57600080fd5b8063ce987745116100bd578063ce9877451461056e578063d1e8b63d14610581578063d547741f1461058957600080fd5b8063b6cd582214610541578063c46b40291461055457600080fd5b80638456cb591161012f5780638d8b6428116101145780638d8b6428146104fa57806391d1485414610502578063a217fddf1461053957600080fd5b80638456cb59146104ea5780638a19c8bc146104f257600080fd5b806377c75d10146104645780637fe019c61461047757806382b39b1b1461049257806383220626146104e257600080fd5b80635c975abb116101f357806364c34a85116101c257806369da9114116101a757806369da9114146103de5780636f94aaf2146103f157806372286cba1461040c57600080fd5b806364c34a85146103a957806369bfac01146103b157600080fd5b80635c975abb146103705780635d4844ea1461037b57806362fd29ae1461038e57806363f5cf7c1461039657600080fd5b80632a4e62491161024a5780632f3906da1161022f5780632f3906da1461034257806336568abe1461034a5780635838d6731461035d57600080fd5b80632a4e6249146103185780632f2ff15d1461032d57600080fd5b806301ffc9a71461027c5780631736d472146102a457806318350096146102b7578063248a9ca3146102e7575b600080fd5b61028f61028a36600461431f565b61060d565b60405190151581526020015b60405180910390f35b61028f6102b236600461436d565b610676565b6001546102cf9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161029b565b61030a6102f53660046143a6565b60009081526020819052604090206001015490565b60405190815260200161029b565b610320610883565b60405161029b91906143bf565b61034061033b36600461444e565b610990565b005b61028f6109ba565b61034061035836600461444e565b610a04565b61034061036b366004614490565b610a95565b60015460ff1661028f565b6003546102cf906001600160a01b031681565b61030a611032565b6103406103a43660046144d5565b6110fe565b61030a611533565b6008546103c59067ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161029b565b6002546102cf906001600160a01b031681565b6008546103c590600160801b900467ffffffffffffffff1681565b61041f61041a3660046143a6565b611613565b604080519788526001600160a01b0390961660208801529315159486019490945260ff9091166060850152608084015260a083019190915260c082015260e00161029b565b61028f6104723660046143a6565b611671565b6008546103c590600160401b900467ffffffffffffffff1681565b6104a56104a03660046143a6565b611921565b604080519687526001600160a01b03909516602087015260ff909316938501939093526060840152608083019190915260a082015260c00161029b565b61030a611978565b610340611983565b6103c56119dc565b61028f6119e9565b61028f61051036600461444e565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b61030a600081565b61034061054f36600461455d565b611a13565b61055c611f6d565b60405160ff909116815260200161029b565b61030a61057c366004614592565b611ff2565b61028f612061565b61034061059736600461444e565b612086565b600a54600b54600c54600d54600e546104a594936001600160a01b03811693600160a01b90910460ff1692909186565b6103406105da3660046145cf565b6120ab565b6103406105ed3660046143a6565b612192565b6103406121e6565b61028f61060836600461461a565b61223d565b60006001600160e01b031982167f7965db0b00000000000000000000000000000000000000000000000000000000148061067057507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b60035460405163d1052d1f60e01b81526001600160a01b038481166004830152600092839291169063d1052d1f90602401602060405180830381865afa1580156106c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e89190614648565b600354604051631d54805360e01b81526001600160a01b03878116600483015292935060009290911690631d54805390602401602060405180830381865afa158015610738573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075c9190614661565b6107669085614694565b90506107706109ba565b156107a7576040517fe2586bcc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816000036107c7576040516273e5c360e31b815260040160405180910390fd5b6107d3609860026146ad565b6107dd90436146c4565b82106107fc57604051630a0744c560e01b815260040160405180910390fd5b6003546040516397adedb560e01b81526001600160a01b03878116600483015261087a9216906397adedb590602401602060405180830381865afa158015610848573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086c9190614648565b610874611533565b8361223d565b95945050505050565b606061088d6119e9565b6108aa57604051633788c6c160e11b815260040160405180910390fd5b60006108b46119dc565b60085490915067ffffffffffffffff808316600160401b90920416146108ed57604051636fbabc7760e01b815260040160405180910390fd5b6005805480602002602001604051908101604052809291908181526020016000905b828210156109865760008481526020908190206040805160c08101825260058602909201805483526001808201546001600160a01b03811685870152600160a01b900460ff169284019290925260028101546060840152600381015460808401526004015460a0830152908352909201910161090f565b5050505091505090565b6000828152602081905260409020600101546109ab8161227a565b6109b58383612287565b505050565b6000806109c86098436146ed565b90506109d660046098614701565b81101580156109ef57506109ec60026098614701565b81105b156109fc57600191505090565b600091505090565b6001600160a01b0381163314610a875760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b610a918282612325565b5050565b610a9d6123a4565b6000610aa76119dc565b6003546040516397adedb560e01b81523360048201529192506000916001600160a01b03909116906397adedb590602401602060405180830381865afa158015610af5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b199190614648565b6003546040517f830a053e0000000000000000000000000000000000000000000000000000000081523360048201529192506000916001600160a01b039091169063830a053e90602401602060405180830381865afa158015610b80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba49190614648565b60035460405163d1052d1f60e01b81523360048201529192506000916001600160a01b039091169063d1052d1f90602401602060405180830381865afa158015610bf2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c169190614648565b600354604051631d54805360e01b81523360048201529192506000916001600160a01b0390911690631d54805390602401602060405180830381865afa158015610c64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c889190614661565b9050610c92612061565b610cc8576040517fdc816a8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001610cd660046098614701565b610ce091906146c4565b610ceb6098436146ed565b03610d22576040517f5baef6b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8567ffffffffffffffff168567ffffffffffffffff161115610d70576040517f50ff7c0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8567ffffffffffffffff168567ffffffffffffffff161015610dbe576040517f7a0c0fd600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81600003610dde576040516273e5c360e31b815260040160405180910390fd5b610dea609860026146ad565b610df490436146c4565b8210610e1357604051630a0744c560e01b815260040160405180910390fd5b60085467ffffffffffffffff868116911614610e5357610e356004600061423d565b6008805467ffffffffffffffff191667ffffffffffffffff87161790555b60045460005b81811015610ec6578560048281548110610e7557610e75614715565b90600052602060002090600502016000015403610ebe576040517fbfec555800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600101610e59565b5060046040518060e00160405280878152602001336001600160a01b031681526020016000151581526020018460ff1681526020018681526020018a8152602001600081525090806001815401808255809150506001900390600052602060002090600502016000909190919091506000820151816000015560208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160146101000a81548160ff02191690831515021790555060608201518160010160156101000a81548160ff021916908360ff1602179055506080820151816002015560a0820151816003015560c0820151816004015550507faadc88121471799d39ee2bbe1dd30a4ab57510e2a33bd6e537de5fafd2daa8868786846040516110209392919067ffffffffffffffff939093168352602083019190915260ff16604082015260600190565b60405180910390a15050505050505050565b60008061103d6119dc565b61104890600161472b565b6007546008549192509061106e90600160401b900467ffffffffffffffff16600161472b565b67ffffffffffffffff168267ffffffffffffffff161115610670576008546000906001906110ad90600160401b900467ffffffffffffffff1685614753565b6110b79190614753565b67ffffffffffffffff16905081816040516020016110df929190918252602082015260400190565b6040516020818303038152906040528051906020012091505092915050565b6111066123a4565b61110e6123f7565b6040805160c081018252600a548152600b546001600160a01b0381166020830152600160a01b900460ff1691810191909152600c546060820152600d546080820152600e5460a0820152600654600754600091829161116e600f826146ed565b935061117b600e826146ed565b9250838310611192578261118e81614774565b9350505b6111a5866020013583876040015161223d565b6111c557604051633b5f43a360e01b815260036004820152602401610a7e565b6111d086601e612a66565b6111d986612d78565b6111e286613085565b6111f5886020013583876040015161223d565b61121557604051633b5f43a360e01b815260026004820152602401610a7e565b611229886112248660026146ad565b612a66565b61123288612d78565b61123b88613085565b61124e876020013583876040015161223d565b61126e57604051633b5f43a360e01b815260016004820152602401610a7e565b61127d876112248560026146ad565b61128687612d78565b61128f87613085565b611305848461129e8b8061478d565b60008181106112af576112af614715565b602002919091013590506112c38b8061478d565b60008181106112d4576112d4614715565b602002919091013590506112e88b8061478d565b60008181106112f9576112f9614715565b90506020020135613319565b61132f611312878061478d565b600081811061132357611323614715565b905060200201356133a6565b60015460208601516040516001600160a01b03918216602482015260009261010090049091169060440160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f51cff8d900000000000000000000000000000000000000000000000000000000179052516113bc9190614802565b6000604051808303816000865af19150503d80600081146113f9576040519150601f19603f3d011682016040523d82523d6000602084013e6113fe565b606091505b5050905080611449576020808701516040516001600160a01b0390911681527f7ae187a0c04cf55b655ca83fa11d37854c882bf1fdcb588469b414731bb0e05a910160405180910390a15b7f788e77979e6e6a8a6a5d2c19c58b1ff9671298f54c85ac6f6aa30379aed5861a86604051611478919061481e565b60405180910390a17fbee3fc8a3523c1a65fa9308ce1f2b8fd90c24975b141b754603194597846e4dd60018054906101000a90046001600160a01b03166001600160a01b0316638a5e8e326040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115169190614648565b6040519081526020015b60405180910390a1505050505050505050565b600061153d612061565b8061157b5750600854600160401b900467ffffffffffffffff1661155f6119dc565b67ffffffffffffffff1611801561157b57506115796119e9565b155b1561158d57611588611978565b905090565b6115956119e9565b156115a257611588611032565b6115aa6109ba565b80156115d95750600854600160401b900467ffffffffffffffff166115cd6119dc565b67ffffffffffffffff16145b15611610576040517f36b7884b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b90565b6004818154811061162357600080fd5b6000918252602090912060059091020180546001820154600283015460038401546004909401549294506001600160a01b0382169360ff600160a01b8404811694600160a81b909404169287565b600061167b6119e9565b61169857604051633788c6c160e11b815260040160405180910390fd5b60006116a26119dc565b60085490915067ffffffffffffffff808316600160401b90920416146116db57604051636fbabc7760e01b815260040160405180910390fd5b60085467ffffffffffffffff600160801b90910481169082161161171257604051630c8d9eab60e31b815260040160405180910390fd5b6000806000806000806000806117266133e4565b9050600061173261349e565b600454919650945060005b8181101561190d576004818154811061175857611758614715565b90600052602060002090600502016004015494506004818154811061177f5761177f614715565b906000526020600020906005020160010160149054906101000a900460ff1680156117cd5750600585815481106117b8576117b8614715565b90600052602060002090600502016004015487145b801561180b5750600585815481106117e7576117e7614715565b600091825260209091206001600590920201015460ff878116600160a01b90920416145b15611905576005858154811061182357611823614715565b9060005260206000209060050201600301548b611840919061486d565b9a508383604051602001611855929190614880565b60408051601f19818403018152919052805160209091012098506fffffffffffffffffffffffffffffffff808a16985061189090600161486d565b600586815481106118a3576118a3614715565b9060005260206000209060050201600301546118bf91906146ad565b6118c98c8a6146ad565b10156118f757600585815481106118e2576118e2614715565b90600052602060002090600502016000015499505b8261190181614774565b9350505b60010161173d565b505050959099149998505050505050505050565b6005818154811061193157600080fd5b6000918252602090912060059091020180546001820154600283015460038401546004909401549294506001600160a01b03821693600160a01b90920460ff169290919086565b6000806110486119dc565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166119d257604051631d77d47760e21b815260040160405180910390fd5b6119da613657565b565b6000611588609843614701565b60006119f760026098614701565b611a026098436146ed565b10611a0d5750600190565b50600090565b611a1b6123a4565b6000611a256119dc565b6003546040516397adedb560e01b81523360048201529192506000916001600160a01b03909116906397adedb590602401602060405180830381865afa158015611a73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a979190614648565b9050611aa1611f6d565b60ff168560ff161015611ae0576040517f83d9b7bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ae86109ba565b611b1e576040517fd1088db600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085467ffffffffffffffff838116911614611b66576040517f842a9e0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085467ffffffffffffffff838116600160401b9092041614611c4e57611b8b611533565b600655611b9a6005600061425e565b600880547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff16600160401b67ffffffffffffffff8516908102919091179091556006546040805192835260208301919091527ff0ae472da9c8da86bda4991a549c03a3cb328b5f360ea11a5b8814f32bb85176910160405180910390a1611c4e600754604080516020810192909252449082015260600160408051601f198184030181529190528051602090910120600755565b6000611c5c82878787611ff2565b90506000611c6a83836136ab565b9050600060048281548110611c8157611c81614715565b600091825260208083206040805160e08101825260059094029091018054845260018101546001600160a01b0381169385019390935260ff600160a01b84048116151592850192909252600160a81b909204166060830181905260028201546080840152600382015460a084015260049091015460c0830152909250611d07908a614694565b9050611d1a82600001516006548361223d565b611d56576006546040517f14ebbbe4000000000000000000000000000000000000000000000000000000008152600401610a7e91815260200190565b816040015115611d92576040517fa89ac15100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160048481548110611da757611da7614715565b906000526020600020906005020160010160146101000a81548160ff02191690831515021790555060058054905060048481548110611de857611de8614715565b90600052602060002090600502016004018190555060056040518060c001604052808460000151815260200184602001516001600160a01b031681526020018b60ff16815260200184608001518152602001836002611e479190614986565b8560800151611e5691906146ad565b815260209081018b90528254600181810185556000948552938290208351600590920201908155908201519281018054604084015160ff16600160a01b0274ffffffffffffffffffffffffffffffffffffffffff199091166001600160a01b0390951694909417939093179092556060810151600280840191909155608080830151600385015560a0909201516004909301929092558351908401517f13fc17fd71632266fe82092de6dd91a06b4fa68d8dc950492e5421cbed55a6a59289929190611f23908690614986565b8660800151611f3291906146ad565b6040805167ffffffffffffffff90951685526020850193909352918301526060820152608081018a905260ff8b1660a082015260c001611520565b6008546000908190611f929067ffffffffffffffff600160801b820481169116614753565b67ffffffffffffffff169050600060fe8211611fae5781611fb1565b60fe5b611fbc906001614995565b600b5490915060ff600160a01b9091048116908216811115611fe757611fe28282614694565b611fea565b60005b935050505090565b60408051602081018690527fff0000000000000000000000000000000000000000000000000000000000000060f886901b169181019190915260418101839052606181018290526000906081015b6040516020818303038152906040528051906020012090505b949350505050565b600061206f60046098614701565b61207a6098436146ed565b1015611a0d5750600190565b6000828152602081905260409020600101546120a18161227a565b6109b58383612325565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166120fa57604051637bfa4b9f60e01b815260040160405180910390fd5b600880547fffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b60ff958616027fffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffff1617600160c81b93851693909302929092177fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff16600160d01b9190931602919091179055565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166121e157604051637bfa4b9f60e01b815260040160405180910390fd5b600955565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661223557604051631d77d47760e21b815260040160405180910390fd5b6119da613756565b60008160ff1660000361225257506001612273565b61226160ff83166101006149ae565b61226c9060026149c9565b8484181090505b9392505050565b612284813361378f565b50565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a91576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556122e13390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1615610a91576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60015460ff16156119da5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610a7e565b60006124016119dc565b905061240b6119e9565b61242857604051633788c6c160e11b815260040160405180910390fd5b60085467ffffffffffffffff828116600160401b909204161461245e57604051636fbabc7760e01b815260040160405180910390fd5b60085467ffffffffffffffff600160801b90910481169082161161249557604051630c8d9eab60e31b815260040160405180910390fd5b600454604051818152600091829182918291829182917f6752c5e71c95fb93bc7137adeb115a33fa4e54e2683e33d3f90c2bb1c4b6c2a59060200160405180910390a16005546040519081527f4c03de6a759749c0c9387b7014634dc5c6af610e1366023d90751c783a998f8d9060200160405180910390a161251661349e565b6040805183815260ff831660208201529295509093507f34e8eda4cd857cd2865becf58a47748f31415f4a382cbb2cc0c64b9a27c717be910160405180910390a160006125616133e4565b905060005b8281101561294e5760006004828154811061258357612583614715565b600091825260208083206040805160e08101825260059485029092018054835260018101546001600160a01b0381169484019490945260ff600160a01b85048116151592840192909252600160a81b90930416606082015260028201546080820152600382015460a082015260049091015460c0820181905282549194509291908390811061261457612614614715565b60009182526020918290206040805160c0810182526005939093029091018054835260018101546001600160a01b03811694840194909452600160a01b90930460ff1682820152600283015460608301526003830154608083015260049092015460a082015290840151909150801561269057508060a0015188145b80156126a55750806040015160ff168760ff16145b1561279a5760808101516126b9908d61486d565b9b50848b6040516020016126ce929190614880565b60408051601f19818403018152919052805160209091012099506fffffffffffffffffffffffffffffffff808b16995061270990600161486d565b816080015161271891906146ad565b6127228d8b6146ad565b101561278c578051600a556020810151600b8054604084015160ff16600160a01b0274ffffffffffffffffffffffffffffffffffffffffff199091166001600160a01b03909316929092179190911790556060810151600c556080810151600d5560a0810151600e555b8a61279681614774565b9b50505b826040015180156127c357508060a00151881415806127c35750806040015160ff168760ff1614155b80156127e45750600854600160d01b900460ff166127e26064446146ed565b105b156128905760035460208201516001600160a01b039091169063d009b2d69061280e8a6002614986565b60085461282790609890600160c01b900460ff166146ad565b61283191906146ad565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561287757600080fd5b505af115801561288b573d6000803e3d6000fd5b505050505b82604001516129405760035460208401516001600160a01b039091169063d009b2d6906128be8a6002614986565b6008546128d790609890600160c81b900460ff166146ad565b6128e191906146ad565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561292757600080fd5b505af115801561293b573d6000803e3d6000fd5b505050505b836001019350505050612566565b506002546040517fffb98fe300000000000000000000000000000000000000000000000000000000815261ffff891660048201526000916001600160a01b03169063ffb98fe3906024016020604051808303816000875af11580156129b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129db91906149e9565b905080612a1a5760405161ffff891681527f20378e5d379eabfa30444ecc5eb2b87d0d77bdbf5a58d80d008673b0ca6421419060200160405180910390a15b50506008805467ffffffffffffffff909916600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff9099169890981790975550505050505050565b600754600090612a78906080906146ed565b90506000612adb612a8c60a086018661478d565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505050606086013584612ad360a0890160808a01614a04565b600654613802565b60408051858152602081018390529192507f94e252069a85aa79db21f5bd8ca4e14dd3a3927aa492711017a2c8ddad95af00910160405180910390a1612b63612b24858061478d565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050505060208601358561040061397a565b600e5414612b8e5760405163755f0a2560e01b81526001600482015260248101829052604401610a7e565b612b9b60a085018561478d565b6000818110612bac57612bac614715565b90506020020135848060400190612bc3919061478d565b6000818110612bd457612bd4614715565b9050602002013514612c035760405163755f0a2560e01b81526002600482015260248101829052604401610a7e565b600080612c1360e087018761478d565b905011612c24578460200135612c59565b612c3160e086018661478d565b6000818110612c4257612c42614715565b9050602002810190612c549190614a1f565b606001355b9050612cb7612c6b604087018761478d565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505050606087013585612cb260a08a0160808b01614a04565b61397a565b8114612ce05760405163755f0a2560e01b81526003600482015260248101839052604401610a7e565b6000612cef60e087018761478d565b90501115612d275760408051602080880135908201529081018390526060016040516020818303038152906040528051906020012091505b81612d32868061478d565b6000818110612d4357612d43614715565b9050602002013514612d715760405163755f0a2560e01b815260048181015260248101839052604401610a7e565b5050505050565b6001546000908190819061010090046001600160a01b031663c81e25ab612da260c0870187614a1f565b602001356040518263ffffffff1660e01b8152600401612dc491815260200190565b60c060405180830381865afa158015612de1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e059190614a35565b509396509194509250506001600160a01b0384169050612e6557612e2c60c0850185614a1f565b602001356040517f2396d34e000000000000000000000000000000000000000000000000000000008152600401610a7e91815260200190565b6000612e88612e7760c0870187614a1f565b611610906060810190604001614a04565b90506000612e968484613ae8565b9050808263ffffffff1610612eeb57612eb260c0870187614a1f565b602001356040517f1362e4a0000000000000000000000000000000000000000000000000000000008152600401610a7e91815260200190565b6000612f1a612efd60c0890189614a1f565b612f0e906060810190604001614a04565b60201c63ffffffff1690565b90506000612f2c886020013586613b03565b63ffffffff16905067ffffffffffffffff82168114612f8b57612f5260c0890189614a1f565b602001356040517f6dd6a24f000000000000000000000000000000000000000000000000000000008152600401610a7e91815260200190565b61303187612f9c60c08b018b614a1f565b612fa69080614aa3565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050505060208b0135612fec60c08d018d614a1f565b60200135612ffd60c08e018e614a1f565b61300e906060810190604001614a04565b61301b60c08f018f614a1f565b61302c906080810190606001614a04565b613b2a565b61307b5761304260c0890189614a1f565b602001356040517fdb12fb9d000000000000000000000000000000000000000000000000000000008152600401610a7e91815260200190565b5050505050505050565b61309260e082018261478d565b905060000361309e5750565b6131bf6130ae60e083018361478d565b60008181106130bf576130bf614715565b90506020028101906130d19190614a1f565b6130df906020810190614aea565b6130ec60e084018461478d565b60008181106130fd576130fd614715565b905060200281019061310f9190614a1f565b61311d906020810190614aa3565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061315f9250505060e085018561478d565b600081811061317057613170614715565b90506020028101906131829190614a1f565b6040013561319360e086018661478d565b60008181106131a4576131a4614715565b90506020028101906131b69190614a1f565b60600135613bc1565b61322c576131d060e082018261478d565b60008181106131e1576131e1614715565b90506020028101906131f39190614a1f565b606001356040517fd740df61000000000000000000000000000000000000000000000000000000008152600401610a7e91815260200190565b60208101356132ab61324160e084018461478d565b600081811061325257613252614715565b90506020028101906132649190614a1f565b6040013561327560e085018561478d565b600081811061328657613286614715565b90506020028101906132989190614a1f565b6132a6906020810190614aea565b613c54565b14612284576132bd60e082018261478d565b60008181106132ce576132ce614715565b90506020028101906132e09190614a1f565b606001356040517f82f2469d000000000000000000000000000000000000000000000000000000008152600401610a7e91815260200190565b838510156133665781831061334157604051633d386eb360e11b815260040160405180910390fd5b80821061336157604051633588c6d360e11b815260040160405180910390fd5b612d71565b82821061338657604051633d386eb360e11b815260040160405180910390fd5b808310612d7157604051633588c6d360e11b815260040160405180910390fd5b6009548110612284576040517fb6052cdf00000000000000000000000000000000000000000000000000000000815260048101829052602401610a7e565b60606133ee6119e9565b61340b57604051633788c6c160e11b815260040160405180910390fd5b60006134156119dc565b60085490915067ffffffffffffffff808316600160401b909204161461344e57604051636fbabc7760e01b815260040160405180910390fd5b6007546040516020016134899181527f3100000000000000000000000000000000000000000000000000000000000000602082015260210190565b60405160208183030381529060405291505090565b60008060008060008060008060006134b4613ca2565b60045490915060005b8181101561364657600481815481106134d8576134d8614715565b906000526020600020906005020160010160149054906101000a900460ff161561363e576004818154811061350f5761350f614715565b90600052602060002090600502016004015493506005848154811061353657613536614715565b90600052602060002090600502016003015489613553919061486d565b98508281604051602001613568929190614880565b60408051601f19818403018152919052805160209091012097506fffffffffffffffffffffffffffffffff80891697506135a390600161486d565b600585815481106135b6576135b6614715565b9060005260206000209060050201600301546135d291906146ad565b6135dc8a896146ad565b101561363e57600584815481106135f5576135f5614715565b90600052602060002090600502016004015495506005848154811061361c5761361c614715565b906000526020600020906005020160010160149054906101000a900460ff1694505b6001016134bd565b509399929850919650505050505050565b61365f6123a4565b6001805460ff1916811790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258335b6040516001600160a01b03909116815260200160405180910390a1565b6000805b6004548110156137235783600482815481106136cd576136cd614715565b90600052602060002090600502016000015414801561370f5750600481815481106136fa576136fa614715565b90600052602060002090600502016003015483145b1561371b579050610670565b6001016136af565b506040517fd950091500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61375e613d2b565b6001805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa3361368e565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a91576137c081613d7d565b6137cb836020613d8f565b6040516020016137dc929190614b07565b60408051601f198184030181529082905262461bcd60e51b8252610a7e91600401614b88565b60008061381187878786613f54565b905082613916856000808267ffffffffffffffff1690506008817eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff16901b600882901c7eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff161790506010817dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff16901b601082901c7dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff161790506020817bffffffff00000000ffffffff00000000ffffffff00000000ffffffff16901b602082901c7bffffffff00000000ffffffff00000000ffffffff00000000ffffffff1617905080915050919050565b826040516020016139589392919092835260c09190911b77ffffffffffffffffffffffffffffffffffffffffffffffff19166020830152602882015260480190565b6040516020818303038152906040528051906020012091505095945050505050565b600080613988868686613fca565b9050613a8c836000808267ffffffffffffffff1690506008817eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff16901b600882901c7eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff161790506010817dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff16901b601082901c7dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff161790506020817bffffffff00000000ffffffff00000000ffffffff00000000ffffffff16901b602082901c7bffffffff00000000ffffffff00000000ffffffff00000000ffffffff1617905080915050919050565b81604051602001613ac792919060c09290921b77ffffffffffffffffffffffffffffffffffffffffffffffff19168252600882015260280190565b60405160208183030381529060405280519060200120915050949350505050565b6000613af48284614694565b60ff166001901b905092915050565b600060e083901c613b15836020614694565b60ff168163ffffffff16901c91505092915050565b600080613b3986868686614032565b90506000613b94826040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b9050886001600160a01b0316613baa828a61407d565b6001600160a01b0316149998505050505050505050565b600080613bce84846140fc565b90506000613c29826040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b9050866001600160a01b0316613c3f828861407d565b6001600160a01b031614979650505050505050565b60008282604051602001613c8492919091825260601b6bffffffffffffffffffffffff1916602082015260340190565b60405160208183030381529060405280519060200120905092915050565b6060613cac6119e9565b613cc957604051633788c6c160e11b815260040160405180910390fd5b6000613cd36119dc565b60085490915067ffffffffffffffff808316600160401b9092041614613d0c57604051636fbabc7760e01b815260040160405180910390fd5b600754604051602001613489918152600360fc1b602082015260210190565b60015460ff166119da5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610a7e565b60606106706001600160a01b03831660145b60606000613d9e8360026146ad565b613da990600261486d565b67ffffffffffffffff811115613dc157613dc1614bbb565b6040519080825280601f01601f191660200182016040528015613deb576020820181803683370190505b509050600360fc1b81600081518110613e0657613e06614715565b60200101906001600160f81b031916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110613e5157613e51614715565b60200101906001600160f81b031916908160001a9053506000613e758460026146ad565b613e8090600161486d565b90505b6001811115613f05577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110613ec157613ec1614715565b1a60f81b828281518110613ed757613ed7614715565b60200101906001600160f81b031916908160001a90535060049490941c93613efe81614bd1565b9050613e83565b5083156122735760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610a7e565b8260005b8551811015613fc1576000613f6e6002866146ed565b15613f7a576000613f7d565b60015b9050613fa483888481518110613f9557613f95614715565b60200260200101518387614118565b9250600185901c9450508080613fb990614774565b915050613f58565b50949350505050565b8160005b845181101561402a576000613fe46002856146ed565b600014905061400d83878481518110613fff57613fff614715565b602002602001015183614178565b9250600184901c935050808061402290614774565b915050613fce565b509392505050565b604080516020810186905290810184905277ffffffffffffffffffffffffffffffffffffffffffffffff1960c084811b8216606084015283901b166068820152600090607001612040565b60008060008061408c856141df565b6040805160008152602081018083528b905260ff8316918101919091526060810184905260808101839052929550909350915060019060a0016020604051602081039080840390855afa1580156140e7573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b6040805160208101849052908101829052600090606001613c84565b6000821561415857604080516020810184905290810186905260608101859052608001604051602081830303815290604052805190602001209050612059565b604080516020810184905290810185905260608101869052608001612040565b600081156141b1576040805160208101869052908101849052606001604051602081830303815290604052805190602001209050612273565b5050604080516020808201939093528082019390935280518084038201815260609093019052815191012090565b6000806000835160411461421f576040517f4be6321b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505060208101516040820151606090920151909260009190911a90565b5080546000825560050290600052602060002090810190612284919061427f565b508054600082556005029060005260206000209081019061228491906142d6565b5b808211156142d25760008082556001820180547fffffffffffffffffffff0000000000000000000000000000000000000000000016905560028201819055600382018190556004820155600501614280565b5090565b5b808211156142d257600080825560018201805474ffffffffffffffffffffffffffffffffffffffffff19169055600282018190556003820181905560048201556005016142d7565b60006020828403121561433157600080fd5b81356001600160e01b03198116811461227357600080fd5b6001600160a01b038116811461228457600080fd5b60ff8116811461228457600080fd5b6000806040838503121561438057600080fd5b823561438b81614349565b9150602083013561439b8161435e565b809150509250929050565b6000602082840312156143b857600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b818110156144425761442f838551805182526001600160a01b03602082015116602083015260ff6040820151166040830152606081015160608301526080810151608083015260a081015160a08301525050565b9284019260c092909201916001016143db565b50909695505050505050565b6000806040838503121561446157600080fd5b82359150602083013561439b81614349565b803567ffffffffffffffff8116811461448b57600080fd5b919050565b600080604083850312156144a357600080fd5b823591506144b360208401614473565b90509250929050565b600061010082840312156144cf57600080fd5b50919050565b6000806000606084860312156144ea57600080fd5b833567ffffffffffffffff8082111561450257600080fd5b61450e878388016144bc565b9450602086013591508082111561452457600080fd5b614530878388016144bc565b9350604086013591508082111561454657600080fd5b50614553868287016144bc565b9150509250925092565b60008060006060848603121561457257600080fd5b833561457d8161435e565b95602085013595506040909401359392505050565b600080600080608085870312156145a857600080fd5b8435935060208501356145ba8161435e565b93969395505050506040820135916060013590565b6000806000606084860312156145e457600080fd5b83356145ef8161435e565b925060208401356145ff8161435e565b9150604084013561460f8161435e565b809150509250925092565b60008060006060848603121561462f57600080fd5b8335925060208401359150604084013561460f8161435e565b60006020828403121561465a57600080fd5b5051919050565b60006020828403121561467357600080fd5b81516122738161435e565b634e487b7160e01b600052601160045260246000fd5b60ff82811682821603908111156106705761067061467e565b80820281158282048414176106705761067061467e565b818103818111156106705761067061467e565b634e487b7160e01b600052601260045260246000fd5b6000826146fc576146fc6146d7565b500690565b600082614710576147106146d7565b500490565b634e487b7160e01b600052603260045260246000fd5b67ffffffffffffffff81811683821601908082111561474c5761474c61467e565b5092915050565b67ffffffffffffffff82811682821603908082111561474c5761474c61467e565b6000600182016147865761478661467e565b5060010190565b6000808335601e198436030181126147a457600080fd5b83018035915067ffffffffffffffff8211156147bf57600080fd5b6020019150600581901b36038213156147d757600080fd5b9250929050565b60005b838110156147f95781810151838201526020016147e1565b50506000910152565b600082516148148184602087016147de565b9190910192915050565b60c081016106708284805182526001600160a01b03602082015116602083015260ff6040820151166040830152606081015160608301526080810151608083015260a081015160a08301525050565b808201808211156106705761067061467e565b600083516148928184602088016147de565b9190910191825250602001919050565b600181815b808511156148dd5781600019048211156148c3576148c361467e565b808516156148d057918102915b93841c93908002906148a7565b509250929050565b6000826148f457506001610670565b8161490157506000610670565b816001811461491757600281146149215761493d565b6001915050610670565b60ff8411156149325761493261467e565b50506001821b610670565b5060208310610133831016604e8410600b8410161715614960575081810a610670565b61496a83836148a2565b806000190482111561497e5761497e61467e565b029392505050565b600061227360ff8416836148e5565b60ff81811683821601908111156106705761067061467e565b61ffff82811682821603908082111561474c5761474c61467e565b600061227361ffff8416836148e5565b8051801515811461448b57600080fd5b6000602082840312156149fb57600080fd5b612273826149d9565b600060208284031215614a1657600080fd5b61227382614473565b60008235607e1983360301811261481457600080fd5b60008060008060008060c08789031215614a4e57600080fd5b8651614a5981614349565b6020880151909650614a6a8161435e565b6040880151909550614a7b8161435e565b9350614a89606088016149d9565b92506080870151915060a087015190509295509295509295565b6000808335601e19843603018112614aba57600080fd5b83018035915067ffffffffffffffff821115614ad557600080fd5b6020019150368190038213156147d757600080fd5b600060208284031215614afc57600080fd5b813561227381614349565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351614b3f8160178501602088016147de565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351614b7c8160288401602088016147de565b01602801949350505050565b6020815260008251806020840152614ba78160408501602087016147de565b601f01601f19169190910160400192915050565b634e487b7160e01b600052604160045260246000fd5b600081614be057614be061467e565b50600019019056fea2646970667358221220e6d529c753301d40b88db1b0768955eec9895788418077bb895e8f7739fb1b6964736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002e9873b73376d20c54e4990b317ceaa7f2ab87c3000000000000000000000000cdfdc3752caaa826fe62531e0000c40546ec56a600000000000000000000000047b134d38ab0a89d561cf393fc370f2099ae0c4b
-----Decoded View---------------
Arg [0] : staking (address): 0x2e9873B73376d20C54E4990b317cEAA7F2ab87c3
Arg [1] : postageContract (address): 0xcdfdC3752caaA826fE62531E0000C40546eC56A6
Arg [2] : oracleContract (address): 0x47B134D38Ab0a89D561CF393fC370f2099AE0c4B
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000002e9873b73376d20c54e4990b317ceaa7f2ab87c3
Arg [1] : 000000000000000000000000cdfdc3752caaa826fe62531e0000c40546ec56a6
Arg [2] : 00000000000000000000000047b134d38ab0a89d561cf393fc370f2099ae0c4b
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.