Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 8 internal transactions
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
6036337 | 158 days ago | Contract Creation | 0 ETH | |||
6036337 | 158 days ago | 0 ETH | ||||
6036336 | 158 days ago | Contract Creation | 0 ETH | |||
6036336 | 158 days ago | 0 ETH | ||||
6001786 | 160 days ago | Contract Creation | 0 ETH | |||
6001786 | 160 days ago | 0 ETH | ||||
6001771 | 160 days ago | Contract Creation | 0 ETH | |||
6001771 | 160 days ago | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
MessageProcessorFactory
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import { Params } from "./utilities/Params.sol"; import { DomainObjs } from "./utilities/DomainObjs.sol"; import { MessageProcessor } from "./MessageProcessor.sol"; import { IMessageProcessorFactory } from "./interfaces/IMPFactory.sol"; /// @title MessageProcessorFactory /// @notice A factory contract which deploys MessageProcessor contracts. contract MessageProcessorFactory is Params, DomainObjs, IMessageProcessorFactory { /// @inheritdoc IMessageProcessorFactory function deploy( address _verifier, address _vkRegistry, address _poll, address _owner, Mode _mode ) public returns (address messageProcessorAddr) { // deploy MessageProcessor for this Poll MessageProcessor messageProcessor = new MessageProcessor(_verifier, _vkRegistry, _poll, _owner, _mode); messageProcessorAddr = address(messageProcessor); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @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; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { SnarkConstants } from "./SnarkConstants.sol"; import { PoseidonT3 } from "./PoseidonT3.sol"; import { PoseidonT4 } from "./PoseidonT4.sol"; import { PoseidonT5 } from "./PoseidonT5.sol"; import { PoseidonT6 } from "./PoseidonT6.sol"; /// @notice A SHA256 hash function for any number of input elements, and Poseidon hash /// functions for 2, 3, 4, 5, and 12 input elements. contract Hasher is SnarkConstants { /// @notice Computes the SHA256 hash of an array of uint256 elements. /// @param array The array of uint256 elements. /// @return result The SHA256 hash of the array. function sha256Hash(uint256[] memory array) public pure returns (uint256 result) { result = uint256(sha256(abi.encodePacked(array))) % SNARK_SCALAR_FIELD; } /// @notice Computes the Poseidon hash of two uint256 elements. /// @param array An array of two uint256 elements. /// @return result The Poseidon hash of the two elements. function hash2(uint256[2] memory array) public pure returns (uint256 result) { result = PoseidonT3.poseidon(array); } /// @notice Computes the Poseidon hash of three uint256 elements. /// @param array An array of three uint256 elements. /// @return result The Poseidon hash of the three elements. function hash3(uint256[3] memory array) public pure returns (uint256 result) { result = PoseidonT4.poseidon(array); } /// @notice Computes the Poseidon hash of four uint256 elements. /// @param array An array of four uint256 elements. /// @return result The Poseidon hash of the four elements. function hash4(uint256[4] memory array) public pure returns (uint256 result) { result = PoseidonT5.poseidon(array); } /// @notice Computes the Poseidon hash of five uint256 elements. /// @param array An array of five uint256 elements. /// @return result The Poseidon hash of the five elements. function hash5(uint256[5] memory array) public pure returns (uint256 result) { result = PoseidonT6.poseidon(array); } /// @notice Computes the Poseidon hash of two uint256 elements. /// @param left the first element to hash. /// @param right the second element to hash. /// @return result The Poseidon hash of the two elements. function hashLeftRight(uint256 left, uint256 right) public pure returns (uint256 result) { uint256[2] memory input; input[0] = left; input[1] = right; result = hash2(input); } }
// SPDX-License-Identifier: MIT // Copyright 2017 Christian Reitwiessner // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // 2019 OKIMS pragma solidity ^0.8.20; /// @title Pairing /// @notice A library implementing the alt_bn128 elliptic curve operations. library Pairing { uint256 public constant PRIME_Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; struct G1Point { uint256 x; uint256 y; } // Encoding of field elements is: X[0] * z + X[1] struct G2Point { uint256[2] x; uint256[2] y; } /// @notice custom errors error PairingAddFailed(); error PairingMulFailed(); error PairingOpcodeFailed(); /// @notice The negation of p, i.e. p.plus(p.negate()) should be zero. function negate(G1Point memory p) internal pure returns (G1Point memory) { // The prime q in the base field F_q for G1 if (p.x == 0 && p.y == 0) { return G1Point(0, 0); } else { return G1Point(p.x, PRIME_Q - (p.y % PRIME_Q)); } } /// @notice r Returns the sum of two points of G1. function plus(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) { uint256[4] memory input; input[0] = p1.x; input[1] = p1.y; input[2] = p2.x; input[3] = p2.y; bool success; // solhint-disable-next-line no-inline-assembly assembly { success := staticcall(sub(gas(), 2000), 6, input, 0xc0, r, 0x60) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } if (!success) { revert PairingAddFailed(); } } /// @notice r Return the product of a point on G1 and a scalar, i.e. /// p == p.scalarMul(1) and p.plus(p) == p.scalarMul(2) for all /// points p. function scalarMul(G1Point memory p, uint256 s) internal view returns (G1Point memory r) { uint256[3] memory input; input[0] = p.x; input[1] = p.y; input[2] = s; bool success; // solhint-disable-next-line no-inline-assembly assembly { success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } if (!success) { revert PairingMulFailed(); } } /// @return isValid The result of computing the pairing check /// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1 /// For example, /// pairing([P1(), P1().negate()], [P2(), P2()]) should return true. function pairing( G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2, G1Point memory c1, G2Point memory c2, G1Point memory d1, G2Point memory d2 ) internal view returns (bool isValid) { G1Point[4] memory p1; p1[0] = a1; p1[1] = b1; p1[2] = c1; p1[3] = d1; G2Point[4] memory p2; p2[0] = a2; p2[1] = b2; p2[2] = c2; p2[3] = d2; uint256 inputSize = 24; uint256[] memory input = new uint256[](inputSize); for (uint8 i = 0; i < 4; ) { uint8 j = i * 6; input[j + 0] = p1[i].x; input[j + 1] = p1[i].y; input[j + 2] = p2[i].x[0]; input[j + 3] = p2[i].x[1]; input[j + 4] = p2[i].y[0]; input[j + 5] = p2[i].y[1]; unchecked { i++; } } uint256[1] memory out; bool success; // solhint-disable-next-line no-inline-assembly assembly { success := staticcall(sub(gas(), 2000), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } if (!success) { revert PairingOpcodeFailed(); } isValid = out[0] != 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /// @notice A library which provides functions for computing Pedersen hashes. library PoseidonT3 { // solhint-disable-next-line no-empty-blocks function poseidon(uint256[2] memory input) public pure returns (uint256) {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /// @notice A library which provides functions for computing Pedersen hashes. library PoseidonT4 { // solhint-disable-next-line no-empty-blocks function poseidon(uint256[3] memory input) public pure returns (uint256) {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /// @notice A library which provides functions for computing Pedersen hashes. library PoseidonT5 { // solhint-disable-next-line no-empty-blocks function poseidon(uint256[4] memory input) public pure returns (uint256) {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /// @notice A library which provides functions for computing Pedersen hashes. library PoseidonT6 { // solhint-disable-next-line no-empty-blocks function poseidon(uint256[5] memory input) public pure returns (uint256) {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { Pairing } from "./Pairing.sol"; /// @title SnarkCommon /// @notice a Contract which holds a struct /// representing a Groth16 verifying key contract SnarkCommon { /// @notice a struct representing a Groth16 verifying key struct VerifyingKey { Pairing.G1Point alpha1; Pairing.G2Point beta2; Pairing.G2Point gamma2; Pairing.G2Point delta2; Pairing.G1Point[] ic; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /// @title SnarkConstants /// @notice This contract contains constants related to the SNARK /// components of MACI. contract SnarkConstants { /// @notice The scalar field uint256 internal constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617; /// @notice The public key here is the first Pedersen base /// point from iden3's circomlib implementation of the Pedersen hash. /// Since it is generated using a hash-to-curve function, we are /// confident that no-one knows the private key associated with this /// public key. See: /// https://github.com/iden3/circomlib/blob/d5ed1c3ce4ca137a6b3ca48bec4ac12c1b38957a/src/pedersen_printbases.js /// Its hash should equal /// 6769006970205099520508948723718471724660867171122235270773600567925038008762. uint256 internal constant PAD_PUBKEY_X = 10457101036533406547632367118273992217979173478358440826365724437999023779287; uint256 internal constant PAD_PUBKEY_Y = 19824078218392094440610104313265183977899662750282163392862422243483260492317; /// @notice The Keccack256 hash of 'Maci' uint256 internal constant NOTHING_UP_MY_SLEEVE = 8370432830353022751713833565135785980866757267633941821328460903436894336785; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /// @title IMACI /// @notice MACI interface interface IMACI { /// @notice Get the depth of the state tree /// @return The depth of the state tree function stateTreeDepth() external view returns (uint8); /// @notice Return the main root of the StateAq contract /// @return The Merkle root function getStateTreeRoot() external view returns (uint256); /// @notice Get the number of signups /// @return numsignUps The number of signups function numSignUps() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; /// @title IMessageProcessor /// @notice MessageProcessor interface interface IMessageProcessor { /// @notice Get the result of whether there are unprocessed messages left /// @return Whether there are unprocessed messages left function processingComplete() external view returns (bool); /// @notice Get the commitment to the state and ballot roots /// @return The commitment to the state and ballot roots function sbCommitment() external view returns (uint256); /// @notice Get public circuit inputs. /// @param _currentMessageBatchIndex The current processed batch index /// @param _newSbCommitment The new state root and ballot root commitment /// after all messages are processed /// @return publicInputs public circuit inputs function getPublicCircuitInputs( uint256 _currentMessageBatchIndex, uint256 _newSbCommitment ) external view returns (uint256[] memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import { DomainObjs } from "../utilities/DomainObjs.sol"; /// @title IMessageProcessorFactory /// @notice MessageProcessorFactory interface interface IMessageProcessorFactory { /// @notice Deploy a new MessageProcessor contract and return the address. /// @param _verifier Verifier contract /// @param _vkRegistry VkRegistry contract /// @param _poll Poll contract /// @param _owner Owner of the MessageProcessor contract /// @param _mode Voting mode /// @return The deployed MessageProcessor contract function deploy( address _verifier, address _vkRegistry, address _poll, address _owner, DomainObjs.Mode _mode ) external returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import { DomainObjs } from "../utilities/DomainObjs.sol"; import { IMACI } from "./IMACI.sol"; import { AccQueue } from "../trees/AccQueue.sol"; /// @title IPoll /// @notice Poll interface interface IPoll { /// @notice The number of messages which have been processed and the number of signups /// @return numSignups The number of signups /// @return numMsgs The number of messages sent by voters function numSignUpsAndMessages() external view returns (uint256 numSignups, uint256 numMsgs); /// @notice Allows anyone to publish a message (an encrypted command and signature). /// This function also enqueues the message. /// @param _message The message to publish /// @param _encPubKey An ephemeral public key which can be combined with the /// coordinator's private key to generate an ECDH shared key with which /// to encrypt the message. function publishMessage(DomainObjs.Message memory _message, DomainObjs.PubKey calldata _encPubKey) external; /// @notice The second step of merging the MACI state AccQueue. This allows the /// ProcessMessages circuit to access the latest state tree and ballots via /// currentSbCommitment. function mergeMaciState() external; /// @notice The first step in merging the message AccQueue so that the /// ProcessMessages circuit can access the message root. /// @param _numSrQueueOps The number of subroot queue operations to perform function mergeMessageAqSubRoots(uint256 _numSrQueueOps) external; /// @notice The second step in merging the message AccQueue so that the /// ProcessMessages circuit can access the message root. function mergeMessageAq() external; /// @notice Returns the Poll's deploy time and duration /// @return _deployTime The deployment timestamp /// @return _duration The duration of the poll function getDeployTimeAndDuration() external view returns (uint256 _deployTime, uint256 _duration); /// @notice Get the result of whether the MACI contract's stateAq has been merged by this contract /// @return Whether the MACI contract's stateAq has been merged by this contract function stateMerged() external view returns (bool); /// @notice Get the depths of the merkle trees /// @return intStateTreeDepth The depth of the state tree /// @return messageTreeSubDepth The subdepth of the message tree /// @return messageTreeDepth The depth of the message tree /// @return voteOptionTreeDepth The subdepth of the vote option tree function treeDepths() external view returns (uint8 intStateTreeDepth, uint8 messageTreeSubDepth, uint8 messageTreeDepth, uint8 voteOptionTreeDepth); /// @notice Get the external contracts /// @return maci The IMACI contract /// @return messageAq The AccQueue contract function extContracts() external view returns (IMACI maci, AccQueue messageAq); /// @notice Get the hash of coordinator's public key /// @return _coordinatorPubKeyHash the hash of coordinator's public key function coordinatorPubKeyHash() external view returns (uint256 _coordinatorPubKeyHash); /// @notice Get the commitment to the state leaves and the ballots. This is /// hash3(stateRoot, ballotRoot, salt). /// Its initial value should be /// hash(maciStateRootSnapshot, emptyBallotRoot, 0) /// Each successful invocation of processMessages() should use a different /// salt to update this value, so that an external observer cannot tell in /// the case that none of the messages are valid. /// @return The commitment to the state leaves and the ballots function currentSbCommitment() external view returns (uint256); /// @notice Get the dynamic depth of the state tree at the time of poll /// finalization (based on the number of leaves inserted) function actualStateTreeDepth() external view returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import { SnarkCommon } from "../crypto/SnarkCommon.sol"; /// @title IVerifier /// @notice an interface for a Groth16 verifier contract interface IVerifier { /// @notice Verify a zk-SNARK proof /// @param _proof The proof /// @param vk The verifying key /// @param inputs The public inputs to the circuit /// @return Whether the proof is valid given the verifying key and public /// input. Note that this function only supports one public input. /// Refer to the Semaphore source code for a verifier that supports /// multiple public inputs. function verify( uint256[8] memory _proof, SnarkCommon.VerifyingKey memory vk, uint256[] memory inputs ) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import { SnarkCommon } from "../crypto/SnarkCommon.sol"; import { DomainObjs } from "../utilities/DomainObjs.sol"; /// @title IVkRegistry /// @notice VkRegistry interface interface IVkRegistry { /// @notice Get the tally verifying key /// @param _stateTreeDepth The state tree depth /// @param _intStateTreeDepth The intermediate state tree depth /// @param _voteOptionTreeDepth The vote option tree depth /// @param _mode QV or Non-QV /// @return The verifying key function getTallyVk( uint256 _stateTreeDepth, uint256 _intStateTreeDepth, uint256 _voteOptionTreeDepth, DomainObjs.Mode _mode ) external view returns (SnarkCommon.VerifyingKey memory); /// @notice Get the process verifying key /// @param _stateTreeDepth The state tree depth /// @param _messageTreeDepth The message tree depth /// @param _voteOptionTreeDepth The vote option tree depth /// @param _messageBatchSize The message batch size /// @param _mode QV or Non-QV /// @return The verifying key function getProcessVk( uint256 _stateTreeDepth, uint256 _messageTreeDepth, uint256 _voteOptionTreeDepth, uint256 _messageBatchSize, DomainObjs.Mode _mode ) external view returns (SnarkCommon.VerifyingKey memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { AccQueue } from "./trees/AccQueue.sol"; import { IMACI } from "./interfaces/IMACI.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { IPoll } from "./interfaces/IPoll.sol"; import { SnarkCommon } from "./crypto/SnarkCommon.sol"; import { Hasher } from "./crypto/Hasher.sol"; import { IVerifier } from "./interfaces/IVerifier.sol"; import { IVkRegistry } from "./interfaces/IVkRegistry.sol"; import { IMessageProcessor } from "./interfaces/IMessageProcessor.sol"; import { CommonUtilities } from "./utilities/CommonUtilities.sol"; import { DomainObjs } from "./utilities/DomainObjs.sol"; /// @title MessageProcessor /// @dev MessageProcessor is used to process messages published by signup users. /// It will process message by batch due to large size of messages. /// After it finishes processing, the sbCommitment will be used for Tally and Subsidy contracts. contract MessageProcessor is Ownable, SnarkCommon, Hasher, CommonUtilities, IMessageProcessor, DomainObjs { /// @notice custom errors error NoMoreMessages(); error StateNotMerged(); error MessageAqNotMerged(); error InvalidProcessMessageProof(); error MaxVoteOptionsTooLarge(); error NumSignUpsTooLarge(); error CurrentMessageBatchIndexTooLarge(); error BatchEndIndexTooLarge(); // the number of children per node in the merkle trees uint256 internal constant TREE_ARITY = 5; /// @inheritdoc IMessageProcessor bool public processingComplete; /// @notice The number of batches processed uint256 public numBatchesProcessed; /// @notice The current message batch index. When the coordinator runs /// processMessages(), this action relates to messages /// currentMessageBatchIndex to currentMessageBatchIndex + messageBatchSize. uint256 public currentMessageBatchIndex; /// @inheritdoc IMessageProcessor uint256 public sbCommitment; IPoll public immutable poll; IVerifier public immutable verifier; IVkRegistry public immutable vkRegistry; Mode public immutable mode; /// @notice Create a new instance /// @param _verifier The Verifier contract address /// @param _vkRegistry The VkRegistry contract address /// @param _poll The Poll contract address /// @param _mpOwner The owner of the MessageProcessor contract /// @param _mode Voting mode constructor( address _verifier, address _vkRegistry, address _poll, address _mpOwner, Mode _mode ) payable Ownable(_mpOwner) { verifier = IVerifier(_verifier); vkRegistry = IVkRegistry(_vkRegistry); poll = IPoll(_poll); mode = _mode; } /// @notice Update the Poll's currentSbCommitment if the proof is valid. /// @param _newSbCommitment The new state root and ballot root commitment /// after all messages are processed /// @param _proof The zk-SNARK proof function processMessages(uint256 _newSbCommitment, uint256[8] calldata _proof) external onlyOwner { // ensure the voting period is over _votingPeriodOver(poll); // There must be unprocessed messages if (processingComplete) { revert NoMoreMessages(); } // The state AccQueue must be merged if (!poll.stateMerged()) { revert StateNotMerged(); } // Retrieve stored vals (, uint8 messageTreeSubDepth, uint8 messageTreeDepth, ) = poll.treeDepths(); // calculate the message batch size from the message tree subdepth uint256 messageBatchSize = TREE_ARITY ** messageTreeSubDepth; (, AccQueue messageAq) = poll.extContracts(); // Require that the message queue has been merged uint256 messageRoot = messageAq.getMainRoot(messageTreeDepth); if (messageRoot == 0) { revert MessageAqNotMerged(); } // Copy the state and ballot commitment and set the batch index if this // is the first batch to process if (numBatchesProcessed == 0) { uint256 currentSbCommitment = poll.currentSbCommitment(); sbCommitment = currentSbCommitment; (, uint256 numMessages) = poll.numSignUpsAndMessages(); uint256 r = numMessages % messageBatchSize; currentMessageBatchIndex = numMessages; if (currentMessageBatchIndex > 0) { if (r == 0) { currentMessageBatchIndex -= messageBatchSize; } else { currentMessageBatchIndex -= r; } } } if (!verifyProcessProof(currentMessageBatchIndex, _newSbCommitment, _proof)) { revert InvalidProcessMessageProof(); } { (, uint256 numMessages) = poll.numSignUpsAndMessages(); // Decrease the message batch start index to ensure that each // message batch is processed in order if (currentMessageBatchIndex > 0) { currentMessageBatchIndex -= messageBatchSize; } updateMessageProcessingData( _newSbCommitment, currentMessageBatchIndex, numMessages <= messageBatchSize * (numBatchesProcessed + 1) ); } } /// @inheritdoc IMessageProcessor function getPublicCircuitInputs( uint256 _currentMessageBatchIndex, uint256 _newSbCommitment ) public view override returns (uint256[] memory publicInputs) { (, uint8 messageTreeSubDepth, uint8 messageTreeDepth, ) = poll.treeDepths(); (, AccQueue messageAq) = poll.extContracts(); uint256 coordinatorPubKeyHash = poll.coordinatorPubKeyHash(); uint256 messageBatchSize = TREE_ARITY ** messageTreeSubDepth; (uint256 numSignUps, uint256 numMessages) = poll.numSignUpsAndMessages(); (uint256 deployTime, uint256 duration) = poll.getDeployTimeAndDuration(); uint256 batchEndIndex = _currentMessageBatchIndex + messageBatchSize; if (batchEndIndex > numMessages) { batchEndIndex = numMessages; } publicInputs = new uint256[](9); publicInputs[0] = numSignUps; publicInputs[1] = deployTime + duration; publicInputs[2] = messageAq.getMainRoot(messageTreeDepth); publicInputs[3] = poll.actualStateTreeDepth(); publicInputs[4] = batchEndIndex; publicInputs[5] = _currentMessageBatchIndex; publicInputs[6] = coordinatorPubKeyHash; publicInputs[7] = (sbCommitment == 0 ? poll.currentSbCommitment() : sbCommitment); publicInputs[8] = _newSbCommitment; } /// @notice Verify the proof for processMessage /// @dev used to update the sbCommitment /// @param _currentMessageBatchIndex The current message batch index /// @param _newSbCommitment The new state root and ballot root commitment /// after all messages are processed /// @param _proof The zk-SNARK proof /// @return isValid Whether the proof is valid function verifyProcessProof( uint256 _currentMessageBatchIndex, uint256 _newSbCommitment, uint256[8] calldata _proof ) public view returns (bool isValid) { // get the tree depths (, uint8 messageTreeSubDepth, uint8 messageTreeDepth, uint8 voteOptionTreeDepth) = poll.treeDepths(); (IMACI maci, ) = poll.extContracts(); uint256[] memory publicCircuitInputs = getPublicCircuitInputs(_currentMessageBatchIndex, _newSbCommitment); // Get the verifying key from the VkRegistry VerifyingKey memory vk = vkRegistry.getProcessVk( maci.stateTreeDepth(), messageTreeDepth, voteOptionTreeDepth, TREE_ARITY ** messageTreeSubDepth, mode ); isValid = verifier.verify(_proof, vk, publicCircuitInputs); } /// @notice update message processing state variables /// @param _newSbCommitment sbCommitment to be updated /// @param _currentMessageBatchIndex currentMessageBatchIndex to be updated /// @param _processingComplete update flag that indicate processing is finished or not function updateMessageProcessingData( uint256 _newSbCommitment, uint256 _currentMessageBatchIndex, bool _processingComplete ) internal { sbCommitment = _newSbCommitment; processingComplete = _processingComplete; currentMessageBatchIndex = _currentMessageBatchIndex; numBatchesProcessed++; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { Hasher } from "../crypto/Hasher.sol"; /// @title AccQueue /// @notice This contract defines a Merkle tree where each leaf insertion only updates a /// subtree. To obtain the main tree root, the contract owner must merge the /// subtrees together. Merging subtrees requires at least 2 operations: /// mergeSubRoots(), and merge(). To get around the gas limit, /// the mergeSubRoots() can be performed in multiple transactions. abstract contract AccQueue is Ownable(msg.sender), Hasher { // The maximum tree depth uint256 public constant MAX_DEPTH = 32; /// @notice A Queue is a 2D array of Merkle roots and indices which represents nodes /// in a Merkle tree while it is progressively updated. struct Queue { /// @notice IMPORTANT: the following declares an array of b elements of type T: T[b] /// And the following declares an array of b elements of type T[a]: T[a][b] /// As such, the following declares an array of MAX_DEPTH+1 arrays of /// uint256[4] arrays, **not the other way round**: uint256[4][MAX_DEPTH + 1] levels; uint256[MAX_DEPTH + 1] indices; } // The depth of each subtree uint256 internal immutable subDepth; // The number of elements per hash operation. Should be either 2 (for // binary trees) or 5 (quinary trees). The limit is 5 because that is the // maximum supported number of inputs for the EVM implementation of the // Poseidon hash function uint256 internal immutable hashLength; // hashLength ** subDepth uint256 internal immutable subTreeCapacity; // True hashLength == 2, false if hashLength == 5 bool internal isBinary; // The index of the current subtree. e.g. the first subtree has index 0, the // second has 1, and so on uint256 internal currentSubtreeIndex; // Tracks the current subtree. Queue internal leafQueue; // Tracks the smallest tree of subroots Queue internal subRootQueue; // Subtree roots mapping(uint256 => uint256) internal subRoots; // Merged roots uint256[MAX_DEPTH + 1] internal mainRoots; // Whether the subtrees have been merged bool public subTreesMerged; // Whether entire merkle tree has been merged bool public treeMerged; // The root of the shortest possible tree which fits all current subtree // roots uint256 internal smallSRTroot; // Tracks the next subroot to queue uint256 internal nextSubRootIndex; // The number of leaves inserted across all subtrees so far uint256 public numLeaves; /// @notice custom errors error SubDepthCannotBeZero(); error SubdepthTooLarge(uint256 _subDepth, uint256 max); error InvalidHashLength(); error DepthCannotBeZero(); error SubTreesAlreadyMerged(); error NothingToMerge(); error SubTreesNotMerged(); error DepthTooLarge(uint256 _depth, uint256 max); error DepthTooSmall(uint256 _depth, uint256 min); error InvalidIndex(uint256 _index); error InvalidLevel(); /// @notice Create a new AccQueue /// @param _subDepth The depth of each subtree. /// @param _hashLength The number of leaves per node (2 or 5). constructor(uint256 _subDepth, uint256 _hashLength) payable { /// validation if (_subDepth == 0) revert SubDepthCannotBeZero(); if (_subDepth > MAX_DEPTH) revert SubdepthTooLarge(_subDepth, MAX_DEPTH); if (_hashLength != 2 && _hashLength != 5) revert InvalidHashLength(); isBinary = _hashLength == 2; subDepth = _subDepth; hashLength = _hashLength; subTreeCapacity = _hashLength ** _subDepth; } /// @notice Hash the contents of the specified level and the specified leaf. /// This is a virtual function as the hash function which the overriding /// contract uses will be either hashLeftRight or hash5, which require /// different input array lengths. /// @param _level The level to hash. /// @param _leaf The leaf include with the level. /// @return _hash The hash of the level and leaf. // solhint-disable-next-line no-empty-blocks function hashLevel(uint256 _level, uint256 _leaf) internal virtual returns (uint256 _hash) {} /// @notice Hash the contents of the specified level and the specified leaf. /// This is a virtual function as the hash function which the overriding /// contract uses will be either hashLeftRight or hash5, which require /// different input array lengths. /// @param _level The level to hash. /// @param _leaf The leaf include with the level. /// @return _hash The hash of the level and leaf. // solhint-disable-next-line no-empty-blocks function hashLevelLeaf(uint256 _level, uint256 _leaf) public view virtual returns (uint256 _hash) {} /// @notice Returns the zero leaf at a specified level. /// This is a virtual function as the hash function which the overriding /// contract uses will be either hashLeftRight or hash5, which will produce /// different zero values (e.g. hashLeftRight(0, 0) vs /// hash5([0, 0, 0, 0, 0]). Moreover, the zero value may be a /// nothing-up-my-sleeve value. /// @param _level The level at which to return the zero leaf. /// @return zero The zero leaf at the specified level. // solhint-disable-next-line no-empty-blocks function getZero(uint256 _level) internal virtual returns (uint256 zero) {} /// @notice Add a leaf to the queue for the current subtree. /// @param _leaf The leaf to add. /// @return leafIndex The index of the leaf in the queue. function enqueue(uint256 _leaf) public onlyOwner returns (uint256 leafIndex) { leafIndex = numLeaves; // Recursively queue the leaf _enqueue(_leaf, 0); // Update the leaf counter numLeaves = leafIndex + 1; // Now that a new leaf has been added, mainRoots and smallSRTroot are // obsolete delete mainRoots; delete smallSRTroot; subTreesMerged = false; // If a subtree is full if (numLeaves % subTreeCapacity == 0) { // Store the subroot subRoots[currentSubtreeIndex] = leafQueue.levels[subDepth][0]; // Increment the index currentSubtreeIndex++; // Delete ancillary data delete leafQueue.levels[subDepth][0]; delete leafQueue.indices; } } /// @notice Updates the queue at a given level and hashes any subroots /// that need to be hashed. /// @param _leaf The leaf to add. /// @param _level The level at which to queue the leaf. function _enqueue(uint256 _leaf, uint256 _level) internal { if (_level > subDepth) { revert InvalidLevel(); } while (true) { uint256 n = leafQueue.indices[_level]; if (n != hashLength - 1) { // Just store the leaf leafQueue.levels[_level][n] = _leaf; if (_level != subDepth) { // Update the index leafQueue.indices[_level]++; } return; } // Hash the leaves to next level _leaf = hashLevel(_level, _leaf); // Reset the index for this level delete leafQueue.indices[_level]; // Queue the hash of the leaves into to the next level _level++; } } /// @notice Fill any empty leaves of the current subtree with zeros and store the /// resulting subroot. function fill() public onlyOwner { if (numLeaves % subTreeCapacity == 0) { // If the subtree is completely empty, then the subroot is a // precalculated zero value subRoots[currentSubtreeIndex] = getZero(subDepth); } else { // Otherwise, fill the rest of the subtree with zeros _fill(0); // Store the subroot subRoots[currentSubtreeIndex] = leafQueue.levels[subDepth][0]; // Reset the subtree data delete leafQueue.levels; // Reset the merged roots delete mainRoots; } // Increment the subtree index uint256 curr = currentSubtreeIndex + 1; currentSubtreeIndex = curr; // Update the number of leaves numLeaves = curr * subTreeCapacity; // Reset the subroot tree root now that it is obsolete delete smallSRTroot; subTreesMerged = false; } /// @notice A function that queues zeros to the specified level, hashes, /// the level, and enqueues the hash to the next level. /// @param _level The level at which to queue zeros. // solhint-disable-next-line no-empty-blocks function _fill(uint256 _level) internal virtual {} /// Insert a subtree. Used for batch enqueues. function insertSubTree(uint256 _subRoot) public onlyOwner { subRoots[currentSubtreeIndex] = _subRoot; // Increment the subtree index currentSubtreeIndex++; // Update the number of leaves numLeaves += subTreeCapacity; // Reset the subroot tree root now that it is obsolete delete smallSRTroot; subTreesMerged = false; } /// @notice Calculate the lowest possible height of a tree with /// all the subroots merged together. /// @return depth The lowest possible height of a tree with all the function calcMinHeight() public view returns (uint256 depth) { depth = 1; while (true) { if (hashLength ** depth >= currentSubtreeIndex) { break; } depth++; } } /// @notice Merge all subtrees to form the shortest possible tree. /// This function can be called either once to merge all subtrees in a /// single transaction, or multiple times to do the same in multiple /// transactions. /// @param _numSrQueueOps The number of times this function will call /// queueSubRoot(), up to the maximum number of times /// necessary. If it is set to 0, it will call /// queueSubRoot() as many times as is necessary. Set /// this to a low number and call this function /// multiple times if there are many subroots to /// merge, or a single transaction could run out of /// gas. function mergeSubRoots(uint256 _numSrQueueOps) public onlyOwner { // This function can only be called once unless a new subtree is created if (subTreesMerged) revert SubTreesAlreadyMerged(); // There must be subtrees to merge if (numLeaves == 0) revert NothingToMerge(); // Fill any empty leaves in the current subtree with zeros only if the // current subtree is not full if (numLeaves % subTreeCapacity != 0) { fill(); } // If there is only 1 subtree, use its root if (currentSubtreeIndex == 1) { smallSRTroot = getSubRoot(0); subTreesMerged = true; return; } uint256 depth = calcMinHeight(); uint256 queueOpsPerformed = 0; for (uint256 i = nextSubRootIndex; i < currentSubtreeIndex; i++) { if (_numSrQueueOps != 0 && queueOpsPerformed == _numSrQueueOps) { // If the limit is not 0, stop if the limit has been reached return; } // Queue the next subroot queueSubRoot(getSubRoot(nextSubRootIndex), 0, depth); // Increment the next subroot counter nextSubRootIndex++; // Increment the ops counter queueOpsPerformed++; } // The height of the tree of subroots uint256 m = hashLength ** depth; // Queue zeroes to fill out the SRT if (nextSubRootIndex == currentSubtreeIndex) { uint256 z = getZero(subDepth); for (uint256 i = currentSubtreeIndex; i < m; i++) { queueSubRoot(z, 0, depth); } } // Store the smallest main root smallSRTroot = subRootQueue.levels[depth][0]; subTreesMerged = true; } /// @notice Queues a subroot into the subroot tree. /// @param _leaf The value to queue. /// @param _level The level at which to queue _leaf. /// @param _maxDepth The depth of the tree. function queueSubRoot(uint256 _leaf, uint256 _level, uint256 _maxDepth) internal { if (_level > _maxDepth) { return; } uint256 n = subRootQueue.indices[_level]; if (n != hashLength - 1) { // Just store the leaf subRootQueue.levels[_level][n] = _leaf; subRootQueue.indices[_level]++; } else { // Hash the elements in this level and queue it in the next level uint256 hashed; if (isBinary) { uint256[2] memory inputs; inputs[0] = subRootQueue.levels[_level][0]; inputs[1] = _leaf; hashed = hash2(inputs); } else { uint256[5] memory inputs; for (uint8 i = 0; i < n; i++) { inputs[i] = subRootQueue.levels[_level][i]; } inputs[n] = _leaf; hashed = hash5(inputs); } // TODO: change recursion to a while loop // Recurse delete subRootQueue.indices[_level]; queueSubRoot(hashed, _level + 1, _maxDepth); } } /// @notice Merge all subtrees to form a main tree with a desired depth. /// @param _depth The depth of the main tree. It must fit all the leaves or /// this function will revert. /// @return root The root of the main tree. function merge(uint256 _depth) public onlyOwner returns (uint256 root) { // The tree depth must be more than 0 if (_depth == 0) revert DepthCannotBeZero(); // Ensure that the subtrees have been merged if (!subTreesMerged) revert SubTreesNotMerged(); // Check the depth if (_depth > MAX_DEPTH) revert DepthTooLarge(_depth, MAX_DEPTH); // Calculate the SRT depth uint256 srtDepth = subDepth; while (true) { if (hashLength ** srtDepth >= numLeaves) { break; } srtDepth++; } if (_depth < srtDepth) revert DepthTooSmall(_depth, srtDepth); // If the depth is the same as the SRT depth, just use the SRT root if (_depth == srtDepth) { mainRoots[_depth] = smallSRTroot; treeMerged = true; return smallSRTroot; } else { root = smallSRTroot; // Calculate the main root for (uint256 i = srtDepth; i < _depth; i++) { uint256 z = getZero(i); if (isBinary) { uint256[2] memory inputs; inputs[0] = root; inputs[1] = z; root = hash2(inputs); } else { uint256[5] memory inputs; inputs[0] = root; inputs[1] = z; inputs[2] = z; inputs[3] = z; inputs[4] = z; root = hash5(inputs); } } mainRoots[_depth] = root; treeMerged = true; } } /// @notice Returns the subroot at the specified index. Reverts if the index refers /// to a subtree which has not been filled yet. /// @param _index The subroot index. /// @return subRoot The subroot at the specified index. function getSubRoot(uint256 _index) public view returns (uint256 subRoot) { if (currentSubtreeIndex <= _index) revert InvalidIndex(_index); subRoot = subRoots[_index]; } /// @notice Returns the subroot tree (SRT) root. Its value must first be computed /// using mergeSubRoots. /// @return smallSubTreeRoot The SRT root. function getSmallSRTroot() public view returns (uint256 smallSubTreeRoot) { if (!subTreesMerged) revert SubTreesNotMerged(); smallSubTreeRoot = smallSRTroot; } /// @notice Return the merged Merkle root of all the leaves at a desired depth. /// @dev merge() or merged(_depth) must be called first. /// @param _depth The depth of the main tree. It must first be computed /// using mergeSubRoots() and merge(). /// @return mainRoot The root of the main tree. function getMainRoot(uint256 _depth) public view returns (uint256 mainRoot) { if (hashLength ** _depth < numLeaves) revert DepthTooSmall(_depth, numLeaves); mainRoot = mainRoots[_depth]; } /// @notice Get the next subroot index and the current subtree index. function getSrIndices() public view returns (uint256 next, uint256 current) { next = nextSubRootIndex; current = currentSubtreeIndex; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { IPoll } from "../interfaces/IPoll.sol"; /// @title CommonUtilities /// @notice A contract that holds common utilities /// which are to be used by multiple contracts /// namely Tally and MessageProcessor contract CommonUtilities { error VotingPeriodNotPassed(); /// @notice common function for MessageProcessor, and Tally /// @param _poll the poll to be checked function _votingPeriodOver(IPoll _poll) internal view { (uint256 deployTime, uint256 duration) = _poll.getDeployTimeAndDuration(); // Require that the voting period is over uint256 secondsPassed = block.timestamp - deployTime; if (secondsPassed <= duration) { revert VotingPeriodNotPassed(); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /// @title DomainObjs /// @notice An utility contract that holds /// a number of domain objects and functions contract DomainObjs { /// @notice the length of a MACI message uint8 public constant MESSAGE_DATA_LENGTH = 10; /// @notice voting modes enum Mode { QV, NON_QV } /// @title Message /// @notice this struct represents a MACI message /// @dev msgType: 1 for vote message struct Message { uint256[MESSAGE_DATA_LENGTH] data; } /// @title PubKey /// @notice A MACI public key struct PubKey { uint256 x; uint256 y; } /// @title StateLeaf /// @notice A MACI state leaf /// @dev used to represent a user's state /// in the state Merkle tree struct StateLeaf { PubKey pubKey; uint256 voiceCreditBalance; uint256 timestamp; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { IMACI } from "../interfaces/IMACI.sol"; import { AccQueue } from "../trees/AccQueue.sol"; /// @title Params /// @notice This contracts contains a number of structures /// which are to be passed as parameters to Poll contracts. /// This way we can reduce the number of parameters /// and avoid a stack too deep error during compilation. contract Params { /// @notice A struct holding the depths of the merkle trees struct TreeDepths { uint8 intStateTreeDepth; uint8 messageTreeSubDepth; uint8 messageTreeDepth; uint8 voteOptionTreeDepth; } /// @notice A struct holding the external contracts /// that are to be passed to a Poll contract on /// deployment struct ExtContracts { IMACI maci; AccQueue messageAq; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": { "contracts/crypto/PoseidonT3.sol": { "PoseidonT3": "0x88c2c6a7535463962a34757fe63cc4f296381aba" }, "contracts/crypto/PoseidonT4.sol": { "PoseidonT4": "0xf8e637e5c9ec3a8d8fa8843a6df833348e1f1e66" }, "contracts/crypto/PoseidonT5.sol": { "PoseidonT5": "0x0a0d66bafda8c8838281084d9c3d68dd9a6fc274" }, "contracts/crypto/PoseidonT6.sol": { "PoseidonT6": "0xd2f6c828606ad8e985008cd825012f269b50cd58" } } }
[{"inputs":[],"name":"MESSAGE_DATA_LENGTH","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_verifier","type":"address"},{"internalType":"address","name":"_vkRegistry","type":"address"},{"internalType":"address","name":"_poll","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"enum DomainObjs.Mode","name":"_mode","type":"uint8"}],"name":"deploy","outputs":[{"internalType":"address","name":"messageProcessorAddr","type":"address"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50612455806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063363448731461003b578063683f3dc31461006b575b600080fd5b61004e6100493660046100f8565b610085565b6040516001600160a01b0390911681526020015b60405180910390f35b610073600a81565b60405160ff9091168152602001610062565b6000808686868686604051610099906100cf565b6100a7959493929190610165565b604051809103906000f0801580156100c3573d6000803e3d6000fd5b50979650505050505050565b612264806101bc83390190565b80356001600160a01b03811681146100f357600080fd5b919050565b600080600080600060a0868803121561011057600080fd5b610119866100dc565b9450610127602087016100dc565b9350610135604087016100dc565b9250610143606087016100dc565b915060808601356002811061015757600080fd5b809150509295509295909350565b6001600160a01b038681168252858116602083015284811660408301528316606082015260a08101600283106101ab57634e487b7160e01b600052602160045260246000fd5b826080830152969550505050505056fe6101006040526040516200226438038062002264833981016040819052620000279162000124565b816001600160a01b0381166200005757604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200006281620000b7565b506001600160a01b0380861660a05284811660c05283166080528060018111156200009157620000916200019b565b60e0816001811115620000a857620000a86200019b565b815250505050505050620001b1565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200011f57600080fd5b919050565b600080600080600060a086880312156200013d57600080fd5b620001488662000107565b9450620001586020870162000107565b9350620001686040870162000107565b9250620001786060870162000107565b91506080860151600281106200018d57600080fd5b809150509295509295909350565b634e487b7160e01b600052602160045260246000fd5b60805160a05160c05160e051611ff462000270600039600081816101cc0152610ac201526000818161016a0152610a240152600081816102000152610b600152600081816102ef0152818161035a015281816103e40152818161046a01528181610500015281816105880152818161071b0152818161082e015281816109050152818161099001528181610dbd01528181610e0e01528181610eb001528181610f4b0152818161106d015281816110fa01526112080152611ff46000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c8063683f3dc3116100b85780639cfced971161007c5780639cfced97146102d7578063a1175279146102ea578063b1a263d314610311578063bea140b314610324578063d13181b814610337578063f2fde38b1461034057600080fd5b8063683f3dc314610285578063715018a61461029f5780637a38d18f146102a95780638763d0c4146102b25780638da5cb5b146102c657600080fd5b80633d6528a1116100ff5780633d6528a1146102225780633dfb88b21461023957806358bfc3791461024c5780635bb939951461025f57806362a361bb1461027257600080fd5b8063023650801461013c57806313fb89321461016557806324fab879146101a4578063295a5212146101c75780632b7ac3f3146101fb575b600080fd5b61014f61014a3660046114cd565b610353565b60405161015c919061152a565b60405180910390f35b61018c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161015c565b6101b76101b2366004611556565b6108fd565b604051901515815260200161015c565b6101ee7f000000000000000000000000000000000000000000000000000000000000000081565b60405161015c91906115af565b61018c7f000000000000000000000000000000000000000000000000000000000000000081565b61022b60025481565b60405190815260200161015c565b61022b610247366004611650565b610be8565b61022b61025a3660046116f2565b610c69565b61022b61026d3660046114cd565b610d03565b61022b610280366004611788565b610d28565b61028d600a81565b60405160ff909116815260200161015c565b6102a7610d62565b005b61022b60015481565b6000546101b790600160a01b900460ff1681565b6000546001600160a01b031661018c565b61022b6102e53660046117e8565b610d76565b61018c7f000000000000000000000000000000000000000000000000000000000000000081565b6102a761031f366004611823565b610db0565b61022b610332366004611851565b6112df565b61022b60035481565b6102a761034e3660046118bf565b611319565b60606000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ac98e5df6040518163ffffffff1660e01b8152600401608060405180830381865afa1580156103b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103da91906118f2565b50925092505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bc14ee2b6040518163ffffffff1660e01b81526004016040805180830381865afa15801561043f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104639190611946565b91505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638aa0ba926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ea9190611980565b905060006104f9856005611a93565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634f367f0f6040518163ffffffff1660e01b81526004016040805180830381865afa15801561055b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061057f9190611aa2565b915091506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634909229f6040518163ffffffff1660e01b81526004016040805180830381865afa1580156105e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106079190611aa2565b90925090506000610618868e611ac6565b9050838111156106255750825b6040805160098082526101408201909252906020820161012080368337019050509a50848b60008151811061065c5761065c611ad9565b60209081029190910101526106718284611ac6565b8b60018151811061068457610684611ad9565b6020908102919091010152604051631b9b8aa760e01b815260ff8a1660048201526001600160a01b03891690631b9b8aa790602401602060405180830381865afa1580156106d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106fa9190611980565b8b60028151811061070d5761070d611ad9565b6020026020010181815250507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637028bb0e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610777573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079b9190611aef565b60ff168b6003815181106107b1576107b1611ad9565b602002602001018181525050808b6004815181106107d1576107d1611ad9565b6020026020010181815250508c8b6005815181106107f1576107f1611ad9565b602002602001018181525050868b60068151811061081157610811611ad9565b60209081029190910101526003541561082c576003546108ae565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c17268d96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561088a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae9190611980565b8b6007815181106108c1576108c1611ad9565b6020026020010181815250508b8b6008815181106108e1576108e1611ad9565b6020026020010181815250505050505050505050505092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ac98e5df6040518163ffffffff1660e01b8152600401608060405180830381865afa158015610961573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098591906118f2565b9350935093505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bc14ee2b6040518163ffffffff1660e01b81526004016040805180830381865afa1580156109eb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0f9190611946565b5090506000610a1e8989610353565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d88ff4f5846001600160a01b031663652c76e46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab39190611aef565b8787610ac08b6005611a93565b7f00000000000000000000000000000000000000000000000000000000000000006040518663ffffffff1660e01b8152600401610b01959493929190611b0a565b600060405180830381865afa158015610b1e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b469190810190611bf7565b60405163352a4d1560e01b81529091506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063352a4d1590610b99908b9085908790600401611d55565b602060405180830381865afa158015610bb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bda9190611e29565b9a9950505050505050505050565b60405163248f667760e01b8152600090730a0d66bafda8c8838281084d9c3d68dd9a6fc2749063248f667790610c22908590600401611e4b565b602060405180830381865af4158015610c3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c639190611980565b92915050565b60007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051602001610c9f9190611e7c565b60408051601f1981840301815290829052610cb991611eb2565b602060405180830381855afa158015610cd6573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610cf99190611980565b610c639190611ee1565b6000610d0d6114af565b83815260208101839052610d2081610d28565b949350505050565b6040516314d2f97b60e11b81526000907388c2c6a7535463962a34757fe63cc4f296381aba906329a5f2f690610c22908590600401611f03565b610d6a61135c565b610d746000611389565b565b604051630926f44b60e31b815260009073d2f6c828606ad8e985008cd825012f269b50cd5890634937a25890610c22908590600401611f2b565b610db861135c565b610de17f00000000000000000000000000000000000000000000000000000000000000006113d9565b600054600160a01b900460ff1615610e0c5760405163a7f0397560e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e33b13a06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8e9190611e29565b610eab5760405163e5fe9e1560e01b815260040160405180910390fd5b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ac98e5df6040518163ffffffff1660e01b8152600401608060405180830381865afa158015610f0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3091906118f2565b5092509250506000826005610f459190611a93565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bc14ee2b6040518163ffffffff1660e01b81526004016040805180830381865afa158015610fa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fca9190611946565b604051631b9b8aa760e01b815260ff86166004820152909250600091506001600160a01b03831690631b9b8aa790602401602060405180830381865afa158015611018573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103c9190611980565b90508060000361105f5760405163c0b868a560e01b815260040160405180910390fd5b6001546000036111d75760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c17268d96040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ed9190611980565b90508060038190555060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634f367f0f6040518163ffffffff1660e01b81526004016040805180830381865afa158015611155573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111799190611aa2565b9150600090506111898683611ee1565b6002839055905081156111d357806000036111bb5785600260008282546111b09190611f53565b909155506111d39050565b80600260008282546111cd9190611f53565b90915550505b5050505b6111e460025488886108fd565b6112045760405160016268f24f60e01b0319815260040160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634f367f0f6040518163ffffffff1660e01b81526004016040805180830381865afa158015611263573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112879190611aa2565b915050600060025411156112ad5783600260008282546112a79190611f53565b90915550505b6112d58860025460015460016112c39190611ac6565b6112cd9088611f66565b841115611476565b5050505050505050565b6040516304b98e1d60e31b815260009073f8e637e5c9ec3a8d8fa8843a6df833348e1f1e66906325cc70e890610c22908590600401611f7d565b61132161135c565b6001600160a01b03811661135057604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b61135981611389565b50565b6000546001600160a01b03163314610d745760405163118cdaa760e01b8152336004820152602401611347565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080826001600160a01b0316634909229f6040518163ffffffff1660e01b81526004016040805180830381865afa158015611419573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143d9190611aa2565b9092509050600061144e8342611f53565b905081811161147057604051635c3017c560e11b815260040160405180910390fd5b50505050565b60038390556000805460ff60a01b1916600160a01b83151502178155600283905560018054916114a583611fa5565b9190505550505050565b60405180604001604052806002906020820280368337509192915050565b600080604083850312156114e057600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b8381101561151f57815187529582019590820190600101611503565b509495945050505050565b60208152600061153d60208301846114ef565b9392505050565b806101008101831015610c6357600080fd5b6000806000610140848603121561156c57600080fd5b83359250602084013591506115848560408601611544565b90509250925092565b600281106115ab57634e487b7160e01b600052602160045260246000fd5b9052565b60208101610c63828461158d565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156115f6576115f66115bd565b60405290565b60405160a0810167ffffffffffffffff811182821017156115f6576115f66115bd565b604051601f8201601f1916810167ffffffffffffffff81118282101715611648576116486115bd565b604052919050565b60006080828403121561166257600080fd5b82601f83011261167157600080fd5b6040516080810181811067ffffffffffffffff82111715611694576116946115bd565b6040528060808401858111156116a957600080fd5b845b818110156116c35780358352602092830192016116ab565b509195945050505050565b600067ffffffffffffffff8211156116e8576116e86115bd565b5060051b60200190565b6000602080838503121561170557600080fd5b823567ffffffffffffffff81111561171c57600080fd5b8301601f8101851361172d57600080fd5b803561174061173b826116ce565b61161f565b81815260059190911b8201830190838101908783111561175f57600080fd5b928401925b8284101561177d57833582529284019290840190611764565b979650505050505050565b60006040828403121561179a57600080fd5b82601f8301126117a957600080fd5b6117b16115d3565b8060408401858111156117c357600080fd5b845b818110156117dd5780358452602093840193016117c5565b509095945050505050565b600060a082840312156117fa57600080fd5b82601f83011261180957600080fd5b6118116115fc565b8060a08401858111156117c357600080fd5b600080610120838503121561183757600080fd5b823591506118488460208501611544565b90509250929050565b60006060828403121561186357600080fd5b82601f83011261187257600080fd5b6040516060810181811067ffffffffffffffff82111715611895576118956115bd565b6040528060608401858111156116a957600080fd5b6001600160a01b038116811461135957600080fd5b6000602082840312156118d157600080fd5b813561153d816118aa565b805160ff811681146118ed57600080fd5b919050565b6000806000806080858703121561190857600080fd5b611911856118dc565b935061191f602086016118dc565b925061192d604086016118dc565b915061193b606086016118dc565b905092959194509250565b6000806040838503121561195957600080fd5b8251611964816118aa565b6020840151909250611975816118aa565b809150509250929050565b60006020828403121561199257600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600181815b808511156119ea5781600019048211156119d0576119d0611999565b808516156119dd57918102915b93841c93908002906119b4565b509250929050565b600082611a0157506001610c63565b81611a0e57506000610c63565b8160018114611a245760028114611a2e57611a4a565b6001915050610c63565b60ff841115611a3f57611a3f611999565b50506001821b610c63565b5060208310610133831016604e8410600b8410161715611a6d575081810a610c63565b611a7783836119af565b8060001904821115611a8b57611a8b611999565b029392505050565b600061153d60ff8416836119f2565b60008060408385031215611ab557600080fd5b505080516020909101519092909150565b80820180821115610c6357610c63611999565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611b0157600080fd5b61153d826118dc565b60ff86811682528581166020830152841660408201526060810183905260a08101611b38608083018461158d565b9695505050505050565b600060408284031215611b5457600080fd5b611b5c6115d3565b9050815181526020820151602082015292915050565b600082601f830112611b8357600080fd5b611b8b6115d3565b806040840185811115611b9d57600080fd5b845b818110156117dd578051845260209384019301611b9f565b600060808284031215611bc957600080fd5b611bd16115d3565b9050611bdd8383611b72565b8152611bec8360408401611b72565b602082015292915050565b60006020808385031215611c0a57600080fd5b825167ffffffffffffffff80821115611c2257600080fd5b908401906101e08287031215611c3757600080fd5b611c3f6115fc565b611c498784611b42565b81526040611c5988828601611bb7565b85830152611c6a8860c08601611bb7565b81830152611c7c886101408601611bb7565b60608301526101c084015183811115611c9457600080fd5b80850194505087601f850112611ca957600080fd5b83519250611cb961173b846116ce565b83815260069390931b84018501928581019089851115611cd857600080fd5b948601945b84861015611cfe57611cef8a87611b42565b82529482019490860190611cdd565b60808401525090979650505050505050565b8060005b6002811015611470578151845260209384019390910190600101611d14565b611d3e828251611d10565b6020810151611d506040840182611d10565b505050565b6000610140610100808785378181850152506103208301611d83828501875180518252602090810151910152565b6020915081860151611d99610180860182611d33565b50604080870151611dae610200870182611d33565b506060870151611dc2610280870182611d33565b5060808701516101e06103008701528051928390528301916000906103408701905b80831015611e1557611e0182865180518252602090810151910152565b938501936001929092019190830190611de4565b50868103610120880152610bda81896114ef565b600060208284031215611e3b57600080fd5b8151801515811461153d57600080fd5b60808101818360005b6004811015611e73578151835260209283019290910190600101611e54565b50505092915050565b815160009082906020808601845b83811015611ea657815185529382019390820190600101611e8a565b50929695505050505050565b6000825160005b81811015611ed35760208186018101518583015201611eb9565b506000920191825250919050565b600082611efe57634e487b7160e01b600052601260045260246000fd5b500690565b60408101818360005b6002811015611e73578151835260209283019290910190600101611f0c565b60a08101818360005b6005811015611e73578151835260209283019290910190600101611f34565b81810381811115610c6357610c63611999565b8082028115828204841417610c6357610c63611999565b60608101818360005b6003811015611e73578151835260209283019290910190600101611f86565b600060018201611fb757611fb7611999565b506001019056fea26469706673582212205431a276c14fca8e4226f4ebbf769fa289bd826bb9e16fac2bac60fd4a2fbf2a64736f6c63430008140033a26469706673582212206484fc599df835f97ba2cea4fdf350f1ccfce49d3bec03c15c4fe629995840e464736f6c63430008140033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063363448731461003b578063683f3dc31461006b575b600080fd5b61004e6100493660046100f8565b610085565b6040516001600160a01b0390911681526020015b60405180910390f35b610073600a81565b60405160ff9091168152602001610062565b6000808686868686604051610099906100cf565b6100a7959493929190610165565b604051809103906000f0801580156100c3573d6000803e3d6000fd5b50979650505050505050565b612264806101bc83390190565b80356001600160a01b03811681146100f357600080fd5b919050565b600080600080600060a0868803121561011057600080fd5b610119866100dc565b9450610127602087016100dc565b9350610135604087016100dc565b9250610143606087016100dc565b915060808601356002811061015757600080fd5b809150509295509295909350565b6001600160a01b038681168252858116602083015284811660408301528316606082015260a08101600283106101ab57634e487b7160e01b600052602160045260246000fd5b826080830152969550505050505056fe6101006040526040516200226438038062002264833981016040819052620000279162000124565b816001600160a01b0381166200005757604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200006281620000b7565b506001600160a01b0380861660a05284811660c05283166080528060018111156200009157620000916200019b565b60e0816001811115620000a857620000a86200019b565b815250505050505050620001b1565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200011f57600080fd5b919050565b600080600080600060a086880312156200013d57600080fd5b620001488662000107565b9450620001586020870162000107565b9350620001686040870162000107565b9250620001786060870162000107565b91506080860151600281106200018d57600080fd5b809150509295509295909350565b634e487b7160e01b600052602160045260246000fd5b60805160a05160c05160e051611ff462000270600039600081816101cc0152610ac201526000818161016a0152610a240152600081816102000152610b600152600081816102ef0152818161035a015281816103e40152818161046a01528181610500015281816105880152818161071b0152818161082e015281816109050152818161099001528181610dbd01528181610e0e01528181610eb001528181610f4b0152818161106d015281816110fa01526112080152611ff46000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c8063683f3dc3116100b85780639cfced971161007c5780639cfced97146102d7578063a1175279146102ea578063b1a263d314610311578063bea140b314610324578063d13181b814610337578063f2fde38b1461034057600080fd5b8063683f3dc314610285578063715018a61461029f5780637a38d18f146102a95780638763d0c4146102b25780638da5cb5b146102c657600080fd5b80633d6528a1116100ff5780633d6528a1146102225780633dfb88b21461023957806358bfc3791461024c5780635bb939951461025f57806362a361bb1461027257600080fd5b8063023650801461013c57806313fb89321461016557806324fab879146101a4578063295a5212146101c75780632b7ac3f3146101fb575b600080fd5b61014f61014a3660046114cd565b610353565b60405161015c919061152a565b60405180910390f35b61018c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161015c565b6101b76101b2366004611556565b6108fd565b604051901515815260200161015c565b6101ee7f000000000000000000000000000000000000000000000000000000000000000081565b60405161015c91906115af565b61018c7f000000000000000000000000000000000000000000000000000000000000000081565b61022b60025481565b60405190815260200161015c565b61022b610247366004611650565b610be8565b61022b61025a3660046116f2565b610c69565b61022b61026d3660046114cd565b610d03565b61022b610280366004611788565b610d28565b61028d600a81565b60405160ff909116815260200161015c565b6102a7610d62565b005b61022b60015481565b6000546101b790600160a01b900460ff1681565b6000546001600160a01b031661018c565b61022b6102e53660046117e8565b610d76565b61018c7f000000000000000000000000000000000000000000000000000000000000000081565b6102a761031f366004611823565b610db0565b61022b610332366004611851565b6112df565b61022b60035481565b6102a761034e3660046118bf565b611319565b60606000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ac98e5df6040518163ffffffff1660e01b8152600401608060405180830381865afa1580156103b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103da91906118f2565b50925092505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bc14ee2b6040518163ffffffff1660e01b81526004016040805180830381865afa15801561043f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104639190611946565b91505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638aa0ba926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ea9190611980565b905060006104f9856005611a93565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634f367f0f6040518163ffffffff1660e01b81526004016040805180830381865afa15801561055b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061057f9190611aa2565b915091506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634909229f6040518163ffffffff1660e01b81526004016040805180830381865afa1580156105e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106079190611aa2565b90925090506000610618868e611ac6565b9050838111156106255750825b6040805160098082526101408201909252906020820161012080368337019050509a50848b60008151811061065c5761065c611ad9565b60209081029190910101526106718284611ac6565b8b60018151811061068457610684611ad9565b6020908102919091010152604051631b9b8aa760e01b815260ff8a1660048201526001600160a01b03891690631b9b8aa790602401602060405180830381865afa1580156106d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106fa9190611980565b8b60028151811061070d5761070d611ad9565b6020026020010181815250507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637028bb0e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610777573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079b9190611aef565b60ff168b6003815181106107b1576107b1611ad9565b602002602001018181525050808b6004815181106107d1576107d1611ad9565b6020026020010181815250508c8b6005815181106107f1576107f1611ad9565b602002602001018181525050868b60068151811061081157610811611ad9565b60209081029190910101526003541561082c576003546108ae565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c17268d96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561088a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae9190611980565b8b6007815181106108c1576108c1611ad9565b6020026020010181815250508b8b6008815181106108e1576108e1611ad9565b6020026020010181815250505050505050505050505092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ac98e5df6040518163ffffffff1660e01b8152600401608060405180830381865afa158015610961573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098591906118f2565b9350935093505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bc14ee2b6040518163ffffffff1660e01b81526004016040805180830381865afa1580156109eb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0f9190611946565b5090506000610a1e8989610353565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d88ff4f5846001600160a01b031663652c76e46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab39190611aef565b8787610ac08b6005611a93565b7f00000000000000000000000000000000000000000000000000000000000000006040518663ffffffff1660e01b8152600401610b01959493929190611b0a565b600060405180830381865afa158015610b1e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b469190810190611bf7565b60405163352a4d1560e01b81529091506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063352a4d1590610b99908b9085908790600401611d55565b602060405180830381865afa158015610bb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bda9190611e29565b9a9950505050505050505050565b60405163248f667760e01b8152600090730a0d66bafda8c8838281084d9c3d68dd9a6fc2749063248f667790610c22908590600401611e4b565b602060405180830381865af4158015610c3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c639190611980565b92915050565b60007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051602001610c9f9190611e7c565b60408051601f1981840301815290829052610cb991611eb2565b602060405180830381855afa158015610cd6573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610cf99190611980565b610c639190611ee1565b6000610d0d6114af565b83815260208101839052610d2081610d28565b949350505050565b6040516314d2f97b60e11b81526000907388c2c6a7535463962a34757fe63cc4f296381aba906329a5f2f690610c22908590600401611f03565b610d6a61135c565b610d746000611389565b565b604051630926f44b60e31b815260009073d2f6c828606ad8e985008cd825012f269b50cd5890634937a25890610c22908590600401611f2b565b610db861135c565b610de17f00000000000000000000000000000000000000000000000000000000000000006113d9565b600054600160a01b900460ff1615610e0c5760405163a7f0397560e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e33b13a06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8e9190611e29565b610eab5760405163e5fe9e1560e01b815260040160405180910390fd5b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ac98e5df6040518163ffffffff1660e01b8152600401608060405180830381865afa158015610f0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3091906118f2565b5092509250506000826005610f459190611a93565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bc14ee2b6040518163ffffffff1660e01b81526004016040805180830381865afa158015610fa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fca9190611946565b604051631b9b8aa760e01b815260ff86166004820152909250600091506001600160a01b03831690631b9b8aa790602401602060405180830381865afa158015611018573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103c9190611980565b90508060000361105f5760405163c0b868a560e01b815260040160405180910390fd5b6001546000036111d75760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c17268d96040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ed9190611980565b90508060038190555060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634f367f0f6040518163ffffffff1660e01b81526004016040805180830381865afa158015611155573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111799190611aa2565b9150600090506111898683611ee1565b6002839055905081156111d357806000036111bb5785600260008282546111b09190611f53565b909155506111d39050565b80600260008282546111cd9190611f53565b90915550505b5050505b6111e460025488886108fd565b6112045760405160016268f24f60e01b0319815260040160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634f367f0f6040518163ffffffff1660e01b81526004016040805180830381865afa158015611263573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112879190611aa2565b915050600060025411156112ad5783600260008282546112a79190611f53565b90915550505b6112d58860025460015460016112c39190611ac6565b6112cd9088611f66565b841115611476565b5050505050505050565b6040516304b98e1d60e31b815260009073f8e637e5c9ec3a8d8fa8843a6df833348e1f1e66906325cc70e890610c22908590600401611f7d565b61132161135c565b6001600160a01b03811661135057604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b61135981611389565b50565b6000546001600160a01b03163314610d745760405163118cdaa760e01b8152336004820152602401611347565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080826001600160a01b0316634909229f6040518163ffffffff1660e01b81526004016040805180830381865afa158015611419573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143d9190611aa2565b9092509050600061144e8342611f53565b905081811161147057604051635c3017c560e11b815260040160405180910390fd5b50505050565b60038390556000805460ff60a01b1916600160a01b83151502178155600283905560018054916114a583611fa5565b9190505550505050565b60405180604001604052806002906020820280368337509192915050565b600080604083850312156114e057600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b8381101561151f57815187529582019590820190600101611503565b509495945050505050565b60208152600061153d60208301846114ef565b9392505050565b806101008101831015610c6357600080fd5b6000806000610140848603121561156c57600080fd5b83359250602084013591506115848560408601611544565b90509250925092565b600281106115ab57634e487b7160e01b600052602160045260246000fd5b9052565b60208101610c63828461158d565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156115f6576115f66115bd565b60405290565b60405160a0810167ffffffffffffffff811182821017156115f6576115f66115bd565b604051601f8201601f1916810167ffffffffffffffff81118282101715611648576116486115bd565b604052919050565b60006080828403121561166257600080fd5b82601f83011261167157600080fd5b6040516080810181811067ffffffffffffffff82111715611694576116946115bd565b6040528060808401858111156116a957600080fd5b845b818110156116c35780358352602092830192016116ab565b509195945050505050565b600067ffffffffffffffff8211156116e8576116e86115bd565b5060051b60200190565b6000602080838503121561170557600080fd5b823567ffffffffffffffff81111561171c57600080fd5b8301601f8101851361172d57600080fd5b803561174061173b826116ce565b61161f565b81815260059190911b8201830190838101908783111561175f57600080fd5b928401925b8284101561177d57833582529284019290840190611764565b979650505050505050565b60006040828403121561179a57600080fd5b82601f8301126117a957600080fd5b6117b16115d3565b8060408401858111156117c357600080fd5b845b818110156117dd5780358452602093840193016117c5565b509095945050505050565b600060a082840312156117fa57600080fd5b82601f83011261180957600080fd5b6118116115fc565b8060a08401858111156117c357600080fd5b600080610120838503121561183757600080fd5b823591506118488460208501611544565b90509250929050565b60006060828403121561186357600080fd5b82601f83011261187257600080fd5b6040516060810181811067ffffffffffffffff82111715611895576118956115bd565b6040528060608401858111156116a957600080fd5b6001600160a01b038116811461135957600080fd5b6000602082840312156118d157600080fd5b813561153d816118aa565b805160ff811681146118ed57600080fd5b919050565b6000806000806080858703121561190857600080fd5b611911856118dc565b935061191f602086016118dc565b925061192d604086016118dc565b915061193b606086016118dc565b905092959194509250565b6000806040838503121561195957600080fd5b8251611964816118aa565b6020840151909250611975816118aa565b809150509250929050565b60006020828403121561199257600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600181815b808511156119ea5781600019048211156119d0576119d0611999565b808516156119dd57918102915b93841c93908002906119b4565b509250929050565b600082611a0157506001610c63565b81611a0e57506000610c63565b8160018114611a245760028114611a2e57611a4a565b6001915050610c63565b60ff841115611a3f57611a3f611999565b50506001821b610c63565b5060208310610133831016604e8410600b8410161715611a6d575081810a610c63565b611a7783836119af565b8060001904821115611a8b57611a8b611999565b029392505050565b600061153d60ff8416836119f2565b60008060408385031215611ab557600080fd5b505080516020909101519092909150565b80820180821115610c6357610c63611999565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611b0157600080fd5b61153d826118dc565b60ff86811682528581166020830152841660408201526060810183905260a08101611b38608083018461158d565b9695505050505050565b600060408284031215611b5457600080fd5b611b5c6115d3565b9050815181526020820151602082015292915050565b600082601f830112611b8357600080fd5b611b8b6115d3565b806040840185811115611b9d57600080fd5b845b818110156117dd578051845260209384019301611b9f565b600060808284031215611bc957600080fd5b611bd16115d3565b9050611bdd8383611b72565b8152611bec8360408401611b72565b602082015292915050565b60006020808385031215611c0a57600080fd5b825167ffffffffffffffff80821115611c2257600080fd5b908401906101e08287031215611c3757600080fd5b611c3f6115fc565b611c498784611b42565b81526040611c5988828601611bb7565b85830152611c6a8860c08601611bb7565b81830152611c7c886101408601611bb7565b60608301526101c084015183811115611c9457600080fd5b80850194505087601f850112611ca957600080fd5b83519250611cb961173b846116ce565b83815260069390931b84018501928581019089851115611cd857600080fd5b948601945b84861015611cfe57611cef8a87611b42565b82529482019490860190611cdd565b60808401525090979650505050505050565b8060005b6002811015611470578151845260209384019390910190600101611d14565b611d3e828251611d10565b6020810151611d506040840182611d10565b505050565b6000610140610100808785378181850152506103208301611d83828501875180518252602090810151910152565b6020915081860151611d99610180860182611d33565b50604080870151611dae610200870182611d33565b506060870151611dc2610280870182611d33565b5060808701516101e06103008701528051928390528301916000906103408701905b80831015611e1557611e0182865180518252602090810151910152565b938501936001929092019190830190611de4565b50868103610120880152610bda81896114ef565b600060208284031215611e3b57600080fd5b8151801515811461153d57600080fd5b60808101818360005b6004811015611e73578151835260209283019290910190600101611e54565b50505092915050565b815160009082906020808601845b83811015611ea657815185529382019390820190600101611e8a565b50929695505050505050565b6000825160005b81811015611ed35760208186018101518583015201611eb9565b506000920191825250919050565b600082611efe57634e487b7160e01b600052601260045260246000fd5b500690565b60408101818360005b6002811015611e73578151835260209283019290910190600101611f0c565b60a08101818360005b6005811015611e73578151835260209283019290910190600101611f34565b81810381811115610c6357610c63611999565b8082028115828204841417610c6357610c63611999565b60608101818360005b6003811015611e73578151835260209283019290910190600101611f86565b600060018201611fb757611fb7611999565b506001019056fea26469706673582212205431a276c14fca8e4226f4ebbf769fa289bd826bb9e16fac2bac60fd4a2fbf2a64736f6c63430008140033a26469706673582212206484fc599df835f97ba2cea4fdf350f1ccfce49d3bec03c15c4fe629995840e464736f6c63430008140033
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.