Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Transfer | 5796275 | 2792 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ParameterizerFactory
Compiler Version
v0.4.24+commit.e67f0147
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2018-06-16
*/
pragma solidity ^0.4.20;
// File: attrstore/AttributeStore.sol
pragma solidity^0.4.11;
library AttributeStore {
struct Data {
mapping(bytes32 => uint) store;
}
function getAttribute(Data storage self, bytes32 _UUID, string _attrName)
public view returns (uint) {
bytes32 key = keccak256(_UUID, _attrName);
return self.store[key];
}
function setAttribute(Data storage self, bytes32 _UUID, string _attrName, uint _attrVal)
public {
bytes32 key = keccak256(_UUID, _attrName);
self.store[key] = _attrVal;
}
}
// File: dll/DLL.sol
pragma solidity^0.4.11;
library DLL {
uint constant NULL_NODE_ID = 0;
struct Node {
uint next;
uint prev;
}
struct Data {
mapping(uint => Node) dll;
}
function isEmpty(Data storage self) public view returns (bool) {
return getStart(self) == NULL_NODE_ID;
}
function contains(Data storage self, uint _curr) public view returns (bool) {
if (isEmpty(self) || _curr == NULL_NODE_ID) {
return false;
}
bool isSingleNode = (getStart(self) == _curr) && (getEnd(self) == _curr);
bool isNullNode = (getNext(self, _curr) == NULL_NODE_ID) && (getPrev(self, _curr) == NULL_NODE_ID);
return isSingleNode || !isNullNode;
}
function getNext(Data storage self, uint _curr) public view returns (uint) {
return self.dll[_curr].next;
}
function getPrev(Data storage self, uint _curr) public view returns (uint) {
return self.dll[_curr].prev;
}
function getStart(Data storage self) public view returns (uint) {
return getNext(self, NULL_NODE_ID);
}
function getEnd(Data storage self) public view returns (uint) {
return getPrev(self, NULL_NODE_ID);
}
/**
@dev Inserts a new node between _prev and _next. When inserting a node already existing in
the list it will be automatically removed from the old position.
@param _prev the node which _new will be inserted after
@param _curr the id of the new node being inserted
@param _next the node which _new will be inserted before
*/
function insert(Data storage self, uint _prev, uint _curr, uint _next) public {
require(_curr != NULL_NODE_ID);
remove(self, _curr);
require(_prev == NULL_NODE_ID || contains(self, _prev));
require(_next == NULL_NODE_ID || contains(self, _next));
require(getNext(self, _prev) == _next);
require(getPrev(self, _next) == _prev);
self.dll[_curr].prev = _prev;
self.dll[_curr].next = _next;
self.dll[_prev].next = _curr;
self.dll[_next].prev = _curr;
}
function remove(Data storage self, uint _curr) public {
if (!contains(self, _curr)) {
return;
}
uint next = getNext(self, _curr);
uint prev = getPrev(self, _curr);
self.dll[next].prev = prev;
self.dll[prev].next = next;
delete self.dll[_curr];
}
}
// File: tokens/eip20/EIP20Interface.sol
// Abstract contract for the full ERC 20 Token standard
// https://github.com/ethereum/EIPs/issues/20
pragma solidity ^0.4.8;
contract EIP20Interface {
/* This is a slight change to the ERC20 base standard.
function totalSupply() constant returns (uint256 supply);
is replaced with:
uint256 public totalSupply;
This automatically creates a getter function for the totalSupply.
This is moved to the base contract since public getter functions are not
currently recognised as an implementation of the matching abstract
function by the compiler.
*/
/// total amount of tokens
uint256 public totalSupply;
/// @param _owner The address from which the balance will be retrieved
/// @return The balance
function balanceOf(address _owner) public view returns (uint256 balance);
/// @notice send `_value` token to `_to` from `msg.sender`
/// @param _to The address of the recipient
/// @param _value The amount of token to be transferred
/// @return Whether the transfer was successful or not
function transfer(address _to, uint256 _value) public returns (bool success);
/// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
/// @param _from The address of the sender
/// @param _to The address of the recipient
/// @param _value The amount of token to be transferred
/// @return Whether the transfer was successful or not
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
/// @notice `msg.sender` approves `_spender` to spend `_value` tokens
/// @param _spender The address of the account able to transfer the tokens
/// @param _value The amount of tokens to be approved for transfer
/// @return Whether the approval was successful or not
function approve(address _spender, uint256 _value) public returns (bool success);
/// @param _owner The address of the account owning tokens
/// @param _spender The address of the account able to transfer the tokens
/// @return Amount of remaining tokens allowed to spent
function allowance(address _owner, address _spender) public view returns (uint256 remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
// File: zeppelin/math/SafeMath.sol
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
function mul(uint256 a, uint256 b) internal constant returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal constant returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint256 a, uint256 b) internal constant returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal constant returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
// File: plcr-revival/PLCRVoting.sol
/**
@title Partial-Lock-Commit-Reveal Voting scheme with ERC20 tokens
@author Team: Aspyn Palatnick, Cem Ozer, Yorke Rhodes
*/
contract PLCRVoting {
// ============
// EVENTS:
// ============
event _VoteCommitted(uint indexed pollID, uint numTokens, address indexed voter);
event _VoteRevealed(uint indexed pollID, uint numTokens, uint votesFor, uint votesAgainst, uint indexed choice, address indexed voter);
event _PollCreated(uint voteQuorum, uint commitEndDate, uint revealEndDate, uint indexed pollID, address indexed creator);
event _VotingRightsGranted(uint numTokens, address indexed voter);
event _VotingRightsWithdrawn(uint numTokens, address indexed voter);
event _TokensRescued(uint indexed pollID, address indexed voter);
// ============
// DATA STRUCTURES:
// ============
using AttributeStore for AttributeStore.Data;
using DLL for DLL.Data;
using SafeMath for uint;
struct Poll {
uint commitEndDate; /// expiration date of commit period for poll
uint revealEndDate; /// expiration date of reveal period for poll
uint voteQuorum; /// number of votes required for a proposal to pass
uint votesFor; /// tally of votes supporting proposal
uint votesAgainst; /// tally of votes countering proposal
mapping(address => bool) didCommit; /// indicates whether an address committed a vote for this poll
mapping(address => bool) didReveal; /// indicates whether an address revealed a vote for this poll
}
// ============
// STATE VARIABLES:
// ============
uint constant public INITIAL_POLL_NONCE = 0;
uint public pollNonce;
mapping(uint => Poll) public pollMap; // maps pollID to Poll struct
mapping(address => uint) public voteTokenBalance; // maps user's address to voteToken balance
mapping(address => DLL.Data) dllMap;
AttributeStore.Data store;
EIP20Interface public token;
/**
@dev Initializer. Can only be called once.
@param _token The address where the ERC20 token contract is deployed
*/
function init(address _token) public {
require(_token != 0 && address(token) == 0);
token = EIP20Interface(_token);
pollNonce = INITIAL_POLL_NONCE;
}
// ================
// TOKEN INTERFACE:
// ================
/**
@notice Loads _numTokens ERC20 tokens into the voting contract for one-to-one voting rights
@dev Assumes that msg.sender has approved voting contract to spend on their behalf
@param _numTokens The number of votingTokens desired in exchange for ERC20 tokens
*/
function requestVotingRights(uint _numTokens) public {
require(token.balanceOf(msg.sender) >= _numTokens);
voteTokenBalance[msg.sender] += _numTokens;
require(token.transferFrom(msg.sender, this, _numTokens));
emit _VotingRightsGranted(_numTokens, msg.sender);
}
/**
@notice Withdraw _numTokens ERC20 tokens from the voting contract, revoking these voting rights
@param _numTokens The number of ERC20 tokens desired in exchange for voting rights
*/
function withdrawVotingRights(uint _numTokens) external {
uint availableTokens = voteTokenBalance[msg.sender].sub(getLockedTokens(msg.sender));
require(availableTokens >= _numTokens);
voteTokenBalance[msg.sender] -= _numTokens;
require(token.transfer(msg.sender, _numTokens));
emit _VotingRightsWithdrawn(_numTokens, msg.sender);
}
/**
@dev Unlocks tokens locked in unrevealed vote where poll has ended
@param _pollID Integer identifier associated with the target poll
*/
function rescueTokens(uint _pollID) public {
require(isExpired(pollMap[_pollID].revealEndDate));
require(dllMap[msg.sender].contains(_pollID));
dllMap[msg.sender].remove(_pollID);
emit _TokensRescued(_pollID, msg.sender);
}
/**
@dev Unlocks tokens locked in unrevealed votes where polls have ended
@param _pollIDs Array of integer identifiers associated with the target polls
*/
function rescueTokensInMultiplePolls(uint[] _pollIDs) public {
// loop through arrays, rescuing tokens from all
for (uint i = 0; i < _pollIDs.length; i++) {
rescueTokens(_pollIDs[i]);
}
}
// =================
// VOTING INTERFACE:
// =================
/**
@notice Commits vote using hash of choice and secret salt to conceal vote until reveal
@param _pollID Integer identifier associated with target poll
@param _secretHash Commit keccak256 hash of voter's choice and salt (tightly packed in this order)
@param _numTokens The number of tokens to be committed towards the target poll
@param _prevPollID The ID of the poll that the user has voted the maximum number of tokens in which is still less than or equal to numTokens
*/
function commitVote(uint _pollID, bytes32 _secretHash, uint _numTokens, uint _prevPollID) public {
require(commitPeriodActive(_pollID));
// if msg.sender doesn't have enough voting rights,
// request for enough voting rights
if (voteTokenBalance[msg.sender] < _numTokens) {
uint remainder = _numTokens.sub(voteTokenBalance[msg.sender]);
requestVotingRights(remainder);
}
// make sure msg.sender has enough voting rights
require(voteTokenBalance[msg.sender] >= _numTokens);
// prevent user from committing to zero node placeholder
require(_pollID != 0);
// prevent user from committing a secretHash of 0
require(_secretHash != 0);
// Check if _prevPollID exists in the user's DLL or if _prevPollID is 0
require(_prevPollID == 0 || dllMap[msg.sender].contains(_prevPollID));
uint nextPollID = dllMap[msg.sender].getNext(_prevPollID);
// edge case: in-place update
if (nextPollID == _pollID) {
nextPollID = dllMap[msg.sender].getNext(_pollID);
}
require(validPosition(_prevPollID, nextPollID, msg.sender, _numTokens));
dllMap[msg.sender].insert(_prevPollID, _pollID, nextPollID);
bytes32 UUID = attrUUID(msg.sender, _pollID);
store.setAttribute(UUID, "numTokens", _numTokens);
store.setAttribute(UUID, "commitHash", uint(_secretHash));
pollMap[_pollID].didCommit[msg.sender] = true;
emit _VoteCommitted(_pollID, _numTokens, msg.sender);
}
/**
@notice Commits votes using hashes of choices and secret salts to conceal votes until reveal
@param _pollIDs Array of integer identifiers associated with target polls
@param _secretHashes Array of commit keccak256 hashes of voter's choices and salts (tightly packed in this order)
@param _numsTokens Array of numbers of tokens to be committed towards the target polls
@param _prevPollIDs Array of IDs of the polls that the user has voted the maximum number of tokens in which is still less than or equal to numTokens
*/
function commitVotes(uint[] _pollIDs, bytes32[] _secretHashes, uint[] _numsTokens, uint[] _prevPollIDs) external {
// make sure the array lengths are all the same
require(_pollIDs.length == _secretHashes.length);
require(_pollIDs.length == _numsTokens.length);
require(_pollIDs.length == _prevPollIDs.length);
// loop through arrays, committing each individual vote values
for (uint i = 0; i < _pollIDs.length; i++) {
commitVote(_pollIDs[i], _secretHashes[i], _numsTokens[i], _prevPollIDs[i]);
}
}
/**
@dev Compares previous and next poll's committed tokens for sorting purposes
@param _prevID Integer identifier associated with previous poll in sorted order
@param _nextID Integer identifier associated with next poll in sorted order
@param _voter Address of user to check DLL position for
@param _numTokens The number of tokens to be committed towards the poll (used for sorting)
@return valid Boolean indication of if the specified position maintains the sort
*/
function validPosition(uint _prevID, uint _nextID, address _voter, uint _numTokens) public constant returns (bool valid) {
bool prevValid = (_numTokens >= getNumTokens(_voter, _prevID));
// if next is zero node, _numTokens does not need to be greater
bool nextValid = (_numTokens <= getNumTokens(_voter, _nextID) || _nextID == 0);
return prevValid && nextValid;
}
/**
@notice Reveals vote with choice and secret salt used in generating commitHash to attribute committed tokens
@param _pollID Integer identifier associated with target poll
@param _voteOption Vote choice used to generate commitHash for associated poll
@param _salt Secret number used to generate commitHash for associated poll
*/
function revealVote(uint _pollID, uint _voteOption, uint _salt) public {
// Make sure the reveal period is active
require(revealPeriodActive(_pollID));
require(pollMap[_pollID].didCommit[msg.sender]); // make sure user has committed a vote for this poll
require(!pollMap[_pollID].didReveal[msg.sender]); // prevent user from revealing multiple times
require(keccak256(_voteOption, _salt) == getCommitHash(msg.sender, _pollID)); // compare resultant hash from inputs to original commitHash
uint numTokens = getNumTokens(msg.sender, _pollID);
if (_voteOption == 1) {// apply numTokens to appropriate poll choice
pollMap[_pollID].votesFor += numTokens;
} else {
pollMap[_pollID].votesAgainst += numTokens;
}
dllMap[msg.sender].remove(_pollID); // remove the node referring to this vote upon reveal
pollMap[_pollID].didReveal[msg.sender] = true;
emit _VoteRevealed(_pollID, numTokens, pollMap[_pollID].votesFor, pollMap[_pollID].votesAgainst, _voteOption, msg.sender);
}
/**
@notice Reveals multiple votes with choices and secret salts used in generating commitHashes to attribute committed tokens
@param _pollIDs Array of integer identifiers associated with target polls
@param _voteOptions Array of vote choices used to generate commitHashes for associated polls
@param _salts Array of secret numbers used to generate commitHashes for associated polls
*/
function revealVotes(uint[] _pollIDs, uint[] _voteOptions, uint[] _salts) external {
// make sure the array lengths are all the same
require(_pollIDs.length == _voteOptions.length);
require(_pollIDs.length == _salts.length);
// loop through arrays, revealing each individual vote values
for (uint i = 0; i < _pollIDs.length; i++) {
revealVote(_pollIDs[i], _voteOptions[i], _salts[i]);
}
}
/**
@param _pollID Integer identifier associated with target poll
@param _salt Arbitrarily chosen integer used to generate secretHash
@return correctVotes Number of tokens voted for winning option
*/
function getNumPassingTokens(address _voter, uint _pollID, uint _salt) public constant returns (uint correctVotes) {
require(pollEnded(_pollID));
require(pollMap[_pollID].didReveal[_voter]);
uint winningChoice = isPassed(_pollID) ? 1 : 0;
bytes32 winnerHash = keccak256(winningChoice, _salt);
bytes32 commitHash = getCommitHash(_voter, _pollID);
require(winnerHash == commitHash);
return getNumTokens(_voter, _pollID);
}
// ==================
// POLLING INTERFACE:
// ==================
/**
@dev Initiates a poll with canonical configured parameters at pollID emitted by PollCreated event
@param _voteQuorum Type of majority (out of 100) that is necessary for poll to be successful
@param _commitDuration Length of desired commit period in seconds
@param _revealDuration Length of desired reveal period in seconds
*/
function startPoll(uint _voteQuorum, uint _commitDuration, uint _revealDuration) public returns (uint pollID) {
pollNonce = pollNonce + 1;
uint commitEndDate = block.timestamp.add(_commitDuration);
uint revealEndDate = commitEndDate.add(_revealDuration);
pollMap[pollNonce] = Poll({
voteQuorum: _voteQuorum,
commitEndDate: commitEndDate,
revealEndDate: revealEndDate,
votesFor: 0,
votesAgainst: 0
});
emit _PollCreated(_voteQuorum, commitEndDate, revealEndDate, pollNonce, msg.sender);
return pollNonce;
}
/**
@notice Determines if proposal has passed
@dev Check if votesFor out of totalVotes exceeds votesQuorum (requires pollEnded)
@param _pollID Integer identifier associated with target poll
*/
function isPassed(uint _pollID) constant public returns (bool passed) {
require(pollEnded(_pollID));
Poll memory poll = pollMap[_pollID];
return (100 * poll.votesFor) > (poll.voteQuorum * (poll.votesFor + poll.votesAgainst));
}
// ----------------
// POLLING HELPERS:
// ----------------
/**
@dev Gets the total winning votes for reward distribution purposes
@param _pollID Integer identifier associated with target poll
@return Total number of votes committed to the winning option for specified poll
*/
function getTotalNumberOfTokensForWinningOption(uint _pollID) constant public returns (uint numTokens) {
require(pollEnded(_pollID));
if (isPassed(_pollID))
return pollMap[_pollID].votesFor;
else
return pollMap[_pollID].votesAgainst;
}
/**
@notice Determines if poll is over
@dev Checks isExpired for specified poll's revealEndDate
@return Boolean indication of whether polling period is over
*/
function pollEnded(uint _pollID) constant public returns (bool ended) {
require(pollExists(_pollID));
return isExpired(pollMap[_pollID].revealEndDate);
}
/**
@notice Checks if the commit period is still active for the specified poll
@dev Checks isExpired for the specified poll's commitEndDate
@param _pollID Integer identifier associated with target poll
@return Boolean indication of isCommitPeriodActive for target poll
*/
function commitPeriodActive(uint _pollID) constant public returns (bool active) {
require(pollExists(_pollID));
return !isExpired(pollMap[_pollID].commitEndDate);
}
/**
@notice Checks if the reveal period is still active for the specified poll
@dev Checks isExpired for the specified poll's revealEndDate
@param _pollID Integer identifier associated with target poll
*/
function revealPeriodActive(uint _pollID) constant public returns (bool active) {
require(pollExists(_pollID));
return !isExpired(pollMap[_pollID].revealEndDate) && !commitPeriodActive(_pollID);
}
/**
@dev Checks if user has committed for specified poll
@param _voter Address of user to check against
@param _pollID Integer identifier associated with target poll
@return Boolean indication of whether user has committed
*/
function didCommit(address _voter, uint _pollID) constant public returns (bool committed) {
require(pollExists(_pollID));
return pollMap[_pollID].didCommit[_voter];
}
/**
@dev Checks if user has revealed for specified poll
@param _voter Address of user to check against
@param _pollID Integer identifier associated with target poll
@return Boolean indication of whether user has revealed
*/
function didReveal(address _voter, uint _pollID) constant public returns (bool revealed) {
require(pollExists(_pollID));
return pollMap[_pollID].didReveal[_voter];
}
/**
@dev Checks if a poll exists
@param _pollID The pollID whose existance is to be evaluated.
@return Boolean Indicates whether a poll exists for the provided pollID
*/
function pollExists(uint _pollID) constant public returns (bool exists) {
return (_pollID != 0 && _pollID <= pollNonce);
}
// ---------------------------
// DOUBLE-LINKED-LIST HELPERS:
// ---------------------------
/**
@dev Gets the bytes32 commitHash property of target poll
@param _voter Address of user to check against
@param _pollID Integer identifier associated with target poll
@return Bytes32 hash property attached to target poll
*/
function getCommitHash(address _voter, uint _pollID) constant public returns (bytes32 commitHash) {
return bytes32(store.getAttribute(attrUUID(_voter, _pollID), "commitHash"));
}
/**
@dev Wrapper for getAttribute with attrName="numTokens"
@param _voter Address of user to check against
@param _pollID Integer identifier associated with target poll
@return Number of tokens committed to poll in sorted poll-linked-list
*/
function getNumTokens(address _voter, uint _pollID) constant public returns (uint numTokens) {
return store.getAttribute(attrUUID(_voter, _pollID), "numTokens");
}
/**
@dev Gets top element of sorted poll-linked-list
@param _voter Address of user to check against
@return Integer identifier to poll with maximum number of tokens committed to it
*/
function getLastNode(address _voter) constant public returns (uint pollID) {
return dllMap[_voter].getPrev(0);
}
/**
@dev Gets the numTokens property of getLastNode
@param _voter Address of user to check against
@return Maximum number of tokens committed in poll specified
*/
function getLockedTokens(address _voter) constant public returns (uint numTokens) {
return getNumTokens(_voter, getLastNode(_voter));
}
/*
@dev Takes the last node in the user's DLL and iterates backwards through the list searching
for a node with a value less than or equal to the provided _numTokens value. When such a node
is found, if the provided _pollID matches the found nodeID, this operation is an in-place
update. In that case, return the previous node of the node being updated. Otherwise return the
first node that was found with a value less than or equal to the provided _numTokens.
@param _voter The voter whose DLL will be searched
@param _numTokens The value for the numTokens attribute in the node to be inserted
@return the node which the propoded node should be inserted after
*/
function getInsertPointForNumTokens(address _voter, uint _numTokens, uint _pollID)
constant public returns (uint prevNode) {
// Get the last node in the list and the number of tokens in that node
uint nodeID = getLastNode(_voter);
uint tokensInNode = getNumTokens(_voter, nodeID);
// Iterate backwards through the list until reaching the root node
while(nodeID != 0) {
// Get the number of tokens in the current node
tokensInNode = getNumTokens(_voter, nodeID);
if(tokensInNode <= _numTokens) { // We found the insert point!
if(nodeID == _pollID) {
// This is an in-place update. Return the prev node of the node being updated
nodeID = dllMap[_voter].getPrev(nodeID);
}
// Return the insert point
return nodeID;
}
// We did not find the insert point. Continue iterating backwards through the list
nodeID = dllMap[_voter].getPrev(nodeID);
}
// The list is empty, or a smaller value than anything else in the list is being inserted
return nodeID;
}
// ----------------
// GENERAL HELPERS:
// ----------------
/**
@dev Checks if an expiration date has been reached
@param _terminationDate Integer timestamp of date to compare current timestamp with
@return expired Boolean indication of whether the terminationDate has passed
*/
function isExpired(uint _terminationDate) constant public returns (bool expired) {
return (block.timestamp > _terminationDate);
}
/**
@dev Generates an identifier which associates a user and a poll together
@param _pollID Integer identifier associated with target poll
@return UUID Hash which is deterministic from _user and _pollID
*/
function attrUUID(address _user, uint _pollID) public pure returns (bytes32 UUID) {
return keccak256(_user, _pollID);
}
}
// File: contracts/Parameterizer.sol
pragma solidity^0.4.11;
contract Parameterizer {
// ------
// EVENTS
// ------
event _ReparameterizationProposal(string name, uint value, bytes32 propID, uint deposit, uint appEndDate, address indexed proposer);
event _NewChallenge(bytes32 indexed propID, uint challengeID, uint commitEndDate, uint revealEndDate, address indexed challenger);
event _ProposalAccepted(bytes32 indexed propID, string name, uint value);
event _ProposalExpired(bytes32 indexed propID);
event _ChallengeSucceeded(bytes32 indexed propID, uint indexed challengeID, uint rewardPool, uint totalTokens);
event _ChallengeFailed(bytes32 indexed propID, uint indexed challengeID, uint rewardPool, uint totalTokens);
event _RewardClaimed(uint indexed challengeID, uint reward, address indexed voter);
// ------
// DATA STRUCTURES
// ------
using SafeMath for uint;
struct ParamProposal {
uint appExpiry;
uint challengeID;
uint deposit;
string name;
address owner;
uint processBy;
uint value;
}
struct Challenge {
uint rewardPool; // (remaining) pool of tokens distributed amongst winning voters
address challenger; // owner of Challenge
bool resolved; // indication of if challenge is resolved
uint stake; // number of tokens at risk for either party during challenge
uint winningTokens; // (remaining) amount of tokens used for voting by the winning side
mapping(address => bool) tokenClaims;
}
// ------
// STATE
// ------
mapping(bytes32 => uint) public params;
// maps challengeIDs to associated challenge data
mapping(uint => Challenge) public challenges;
// maps pollIDs to intended data change if poll passes
mapping(bytes32 => ParamProposal) public proposals;
// Global Variables
EIP20Interface public token;
PLCRVoting public voting;
uint public PROCESSBY = 604800; // 7 days
/**
@dev Initializer Can only be called once
@param _token The address where the ERC20 token contract is deployed
@param _plcr address of a PLCR voting contract for the provided token
@notice _parameters array of canonical parameters
*/
function init(
address _token,
address _plcr,
uint[] _parameters
) public {
require(_token != 0 && address(token) == 0);
require(_plcr != 0 && address(voting) == 0);
token = EIP20Interface(_token);
voting = PLCRVoting(_plcr);
// minimum deposit for listing to be whitelisted
set("minDeposit", _parameters[0]);
// minimum deposit to propose a reparameterization
set("pMinDeposit", _parameters[1]);
// period over which applicants wait to be whitelisted
set("applyStageLen", _parameters[2]);
// period over which reparmeterization proposals wait to be processed
set("pApplyStageLen", _parameters[3]);
// length of commit period for voting
set("commitStageLen", _parameters[4]);
// length of commit period for voting in parameterizer
set("pCommitStageLen", _parameters[5]);
// length of reveal period for voting
set("revealStageLen", _parameters[6]);
// length of reveal period for voting in parameterizer
set("pRevealStageLen", _parameters[7]);
// percentage of losing party's deposit distributed to winning party
set("dispensationPct", _parameters[8]);
// percentage of losing party's deposit distributed to winning party in parameterizer
set("pDispensationPct", _parameters[9]);
// type of majority out of 100 necessary for candidate success
set("voteQuorum", _parameters[10]);
// type of majority out of 100 necessary for proposal success in parameterizer
set("pVoteQuorum", _parameters[11]);
}
// -----------------------
// TOKEN HOLDER INTERFACE
// -----------------------
/**
@notice propose a reparamaterization of the key _name's value to _value.
@param _name the name of the proposed param to be set
@param _value the proposed value to set the param to be set
*/
function proposeReparameterization(string _name, uint _value) public returns (bytes32) {
uint deposit = get("pMinDeposit");
bytes32 propID = keccak256(_name, _value);
if (keccak256(_name) == keccak256("dispensationPct") ||
keccak256(_name) == keccak256("pDispensationPct")) {
require(_value <= 100);
}
require(!propExists(propID)); // Forbid duplicate proposals
require(get(_name) != _value); // Forbid NOOP reparameterizations
// attach name and value to pollID
proposals[propID] = ParamProposal({
appExpiry: now.add(get("pApplyStageLen")),
challengeID: 0,
deposit: deposit,
name: _name,
owner: msg.sender,
processBy: now.add(get("pApplyStageLen"))
.add(get("pCommitStageLen"))
.add(get("pRevealStageLen"))
.add(PROCESSBY),
value: _value
});
require(token.transferFrom(msg.sender, this, deposit)); // escrow tokens (deposit amt)
emit _ReparameterizationProposal(_name, _value, propID, deposit, proposals[propID].appExpiry, msg.sender);
return propID;
}
/**
@notice challenge the provided proposal ID, and put tokens at stake to do so.
@param _propID the proposal ID to challenge
*/
function challengeReparameterization(bytes32 _propID) public returns (uint challengeID) {
ParamProposal memory prop = proposals[_propID];
uint deposit = prop.deposit;
require(propExists(_propID) && prop.challengeID == 0);
//start poll
uint pollID = voting.startPoll(
get("pVoteQuorum"),
get("pCommitStageLen"),
get("pRevealStageLen")
);
challenges[pollID] = Challenge({
challenger: msg.sender,
rewardPool: SafeMath.sub(100, get("pDispensationPct")).mul(deposit).div(100),
stake: deposit,
resolved: false,
winningTokens: 0
});
proposals[_propID].challengeID = pollID; // update listing to store most recent challenge
//take tokens from challenger
require(token.transferFrom(msg.sender, this, deposit));
var (commitEndDate, revealEndDate,) = voting.pollMap(pollID);
emit _NewChallenge(_propID, pollID, commitEndDate, revealEndDate, msg.sender);
return pollID;
}
/**
@notice for the provided proposal ID, set it, resolve its challenge, or delete it depending on whether it can be set, has a challenge which can be resolved, or if its "process by" date has passed
@param _propID the proposal ID to make a determination and state transition for
*/
function processProposal(bytes32 _propID) public {
ParamProposal storage prop = proposals[_propID];
address propOwner = prop.owner;
uint propDeposit = prop.deposit;
// Before any token transfers, deleting the proposal will ensure that if reentrancy occurs the
// prop.owner and prop.deposit will be 0, thereby preventing theft
if (canBeSet(_propID)) {
// There is no challenge against the proposal. The processBy date for the proposal has not
// passed, but the proposal's appExpirty date has passed.
set(prop.name, prop.value);
emit _ProposalAccepted(_propID, prop.name, prop.value);
delete proposals[_propID];
require(token.transfer(propOwner, propDeposit));
} else if (challengeCanBeResolved(_propID)) {
// There is a challenge against the proposal.
resolveChallenge(_propID);
} else if (now > prop.processBy) {
// There is no challenge against the proposal, but the processBy date has passed.
emit _ProposalExpired(_propID);
delete proposals[_propID];
require(token.transfer(propOwner, propDeposit));
} else {
// There is no challenge against the proposal, and neither the appExpiry date nor the
// processBy date has passed.
revert();
}
assert(get("dispensationPct") <= 100);
assert(get("pDispensationPct") <= 100);
// verify that future proposal appExpiry and processBy times will not overflow
now.add(get("pApplyStageLen"))
.add(get("pCommitStageLen"))
.add(get("pRevealStageLen"))
.add(PROCESSBY);
delete proposals[_propID];
}
/**
@notice Claim the tokens owed for the msg.sender in the provided challenge
@param _challengeID the challenge ID to claim tokens for
@param _salt the salt used to vote in the challenge being withdrawn for
*/
function claimReward(uint _challengeID, uint _salt) public {
// ensure voter has not already claimed tokens and challenge results have been processed
require(challenges[_challengeID].tokenClaims[msg.sender] == false);
require(challenges[_challengeID].resolved == true);
uint voterTokens = voting.getNumPassingTokens(msg.sender, _challengeID, _salt);
uint reward = voterReward(msg.sender, _challengeID, _salt);
// subtract voter's information to preserve the participation ratios of other voters
// compared to the remaining pool of rewards
challenges[_challengeID].winningTokens -= voterTokens;
challenges[_challengeID].rewardPool -= reward;
// ensures a voter cannot claim tokens again
challenges[_challengeID].tokenClaims[msg.sender] = true;
emit _RewardClaimed(_challengeID, reward, msg.sender);
require(token.transfer(msg.sender, reward));
}
/**
@dev Called by a voter to claim their rewards for each completed vote.
Someone must call updateStatus() before this can be called.
@param _challengeIDs The PLCR pollIDs of the challenges rewards are being claimed for
@param _salts The salts of a voter's commit hashes in the given polls
*/
function claimRewards(uint[] _challengeIDs, uint[] _salts) public {
// make sure the array lengths are the same
require(_challengeIDs.length == _salts.length);
// loop through arrays, claiming each individual vote reward
for (uint i = 0; i < _challengeIDs.length; i++) {
claimReward(_challengeIDs[i], _salts[i]);
}
}
// --------
// GETTERS
// --------
/**
@dev Calculates the provided voter's token reward for the given poll.
@param _voter The address of the voter whose reward balance is to be returned
@param _challengeID The ID of the challenge the voter's reward is being calculated for
@param _salt The salt of the voter's commit hash in the given poll
@return The uint indicating the voter's reward
*/
function voterReward(address _voter, uint _challengeID, uint _salt)
public view returns (uint) {
uint winningTokens = challenges[_challengeID].winningTokens;
uint rewardPool = challenges[_challengeID].rewardPool;
uint voterTokens = voting.getNumPassingTokens(_voter, _challengeID, _salt);
return (voterTokens * rewardPool) / winningTokens;
}
/**
@notice Determines whether a proposal passed its application stage without a challenge
@param _propID The proposal ID for which to determine whether its application stage passed without a challenge
*/
function canBeSet(bytes32 _propID) view public returns (bool) {
ParamProposal memory prop = proposals[_propID];
return (now > prop.appExpiry && now < prop.processBy && prop.challengeID == 0);
}
/**
@notice Determines whether a proposal exists for the provided proposal ID
@param _propID The proposal ID whose existance is to be determined
*/
function propExists(bytes32 _propID) view public returns (bool) {
return proposals[_propID].processBy > 0;
}
/**
@notice Determines whether the provided proposal ID has a challenge which can be resolved
@param _propID The proposal ID whose challenge to inspect
*/
function challengeCanBeResolved(bytes32 _propID) view public returns (bool) {
ParamProposal memory prop = proposals[_propID];
Challenge memory challenge = challenges[prop.challengeID];
return (prop.challengeID > 0 && challenge.resolved == false && voting.pollEnded(prop.challengeID));
}
/**
@notice Determines the number of tokens to awarded to the winning party in a challenge
@param _challengeID The challengeID to determine a reward for
*/
function challengeWinnerReward(uint _challengeID) public view returns (uint) {
if(voting.getTotalNumberOfTokensForWinningOption(_challengeID) == 0) {
// Edge case, nobody voted, give all tokens to the challenger.
return 2 * challenges[_challengeID].stake;
}
return (2 * challenges[_challengeID].stake) - challenges[_challengeID].rewardPool;
}
/**
@notice gets the parameter keyed by the provided name value from the params mapping
@param _name the key whose value is to be determined
*/
function get(string _name) public view returns (uint value) {
return params[keccak256(_name)];
}
/**
@dev Getter for Challenge tokenClaims mappings
@param _challengeID The challengeID to query
@param _voter The voter whose claim status to query for the provided challengeID
*/
function tokenClaims(uint _challengeID, address _voter) public view returns (bool) {
return challenges[_challengeID].tokenClaims[_voter];
}
// ----------------
// PRIVATE FUNCTIONS
// ----------------
/**
@dev resolves a challenge for the provided _propID. It must be checked in advance whether the _propID has a challenge on it
@param _propID the proposal ID whose challenge is to be resolved.
*/
function resolveChallenge(bytes32 _propID) private {
ParamProposal memory prop = proposals[_propID];
Challenge storage challenge = challenges[prop.challengeID];
// winner gets back their full staked deposit, and dispensationPct*loser's stake
uint reward = challengeWinnerReward(prop.challengeID);
challenge.winningTokens = voting.getTotalNumberOfTokensForWinningOption(prop.challengeID);
challenge.resolved = true;
if (voting.isPassed(prop.challengeID)) { // The challenge failed
if(prop.processBy > now) {
set(prop.name, prop.value);
}
emit _ChallengeFailed(_propID, prop.challengeID, challenge.rewardPool, challenge.winningTokens);
require(token.transfer(prop.owner, reward));
}
else { // The challenge succeeded or nobody voted
emit _ChallengeSucceeded(_propID, prop.challengeID, challenge.rewardPool, challenge.winningTokens);
require(token.transfer(challenges[prop.challengeID].challenger, reward));
}
}
/**
@dev sets the param keted by the provided name to the provided value
@param _name the name of the param to be set
@param _value the value to set the param to be set
*/
function set(string _name, uint _value) private {
params[keccak256(_name)] = _value;
}
}
// File: plcr-revival/ProxyFactory.sol
/***
* Shoutouts:
*
* Bytecode origin https://www.reddit.com/r/ethereum/comments/6ic49q/any_assembly_programmers_willing_to_write_a/dj5ceuw/
* Modified version of Vitalik's https://www.reddit.com/r/ethereum/comments/6c1jui/delegatecall_forwarders_how_to_save_5098_on/
* Credits to Jorge Izquierdo (@izqui) for coming up with this design here: https://gist.github.com/izqui/7f904443e6d19c1ab52ec7f5ad46b3a8
* Credits to Stefan George (@Georgi87) for inspiration for many of the improvements from Gnosis Safe: https://github.com/gnosis/gnosis-safe-contracts
*
* This version has many improvements over the original @izqui's library like using REVERT instead of THROWing on failed calls.
* It also implements the awesome design pattern for initializing code as seen in Gnosis Safe Factory: https://github.com/gnosis/gnosis-safe-contracts/blob/master/contracts/ProxyFactory.sol
* but unlike this last one it doesn't require that you waste storage on both the proxy and the proxied contracts (v. https://github.com/gnosis/gnosis-safe-contracts/blob/master/contracts/Proxy.sol#L8 & https://github.com/gnosis/gnosis-safe-contracts/blob/master/contracts/GnosisSafe.sol#L14)
*
*
* v0.0.2
* The proxy is now only 60 bytes long in total. Constructor included.
* No functionalities were added. The change was just to make the proxy leaner.
*
* v0.0.3
* Thanks @dacarley for noticing the incorrect check for the subsequent call to the proxy. 🙌
* Note: I'm creating a new version of this that doesn't need that one call.
* Will add tests and put this in its own repository soon™.
*
* v0.0.4
* All the merit in this fix + update of the factory is @dacarley 's. 🙌
* Thank you! 😄
*
* Potential updates can be found at https://gist.github.com/GNSPS/ba7b88565c947cfd781d44cf469c2ddb
*
***/
pragma solidity ^0.4.19;
/* solhint-disable no-inline-assembly, indent, state-visibility, avoid-low-level-calls */
contract ProxyFactory {
event ProxyDeployed(address proxyAddress, address targetAddress);
event ProxiesDeployed(address[] proxyAddresses, address targetAddress);
function createManyProxies(uint256 _count, address _target, bytes _data)
public
{
address[] memory proxyAddresses = new address[](_count);
for (uint256 i = 0; i < _count; ++i) {
proxyAddresses[i] = createProxyImpl(_target, _data);
}
ProxiesDeployed(proxyAddresses, _target);
}
function createProxy(address _target, bytes _data)
public
returns (address proxyContract)
{
proxyContract = createProxyImpl(_target, _data);
ProxyDeployed(proxyContract, _target);
}
function createProxyImpl(address _target, bytes _data)
internal
returns (address proxyContract)
{
assembly {
let contractCode := mload(0x40) // Find empty storage location using "free memory pointer"
mstore(add(contractCode, 0x0b), _target) // Add target address, with a 11 bytes [i.e. 23 - (32 - 20)] offset to later accomodate first part of the bytecode
mstore(sub(contractCode, 0x09), 0x000000000000000000603160008181600b9039f3600080808080368092803773) // First part of the bytecode, shifted left by 9 bytes, overwrites left padding of target address
mstore(add(contractCode, 0x2b), 0x5af43d828181803e808314602f57f35bfd000000000000000000000000000000) // Final part of bytecode, offset by 43 bytes
proxyContract := create(0, contractCode, 60) // total length 60 bytes
if iszero(extcodesize(proxyContract)) {
revert(0, 0)
}
// check if the _data.length > 0 and if it is forward it to the newly created contract
let dataLength := mload(_data)
if iszero(iszero(dataLength)) {
if iszero(call(gas, proxyContract, 0, add(_data, 0x20), dataLength, 0, 0)) {
revert(0, 0)
}
}
}
}
}
// File: tokens/eip20/EIP20.sol
/*
Implements EIP20 token standard: https://github.com/ethereum/EIPs/issues/20
.*/
pragma solidity ^0.4.8;
contract EIP20 is EIP20Interface {
uint256 constant MAX_UINT256 = 2**256 - 1;
/*
NOTE:
The following variables are OPTIONAL vanities. One does not have to include them.
They allow one to customise the token contract & in no way influences the core functionality.
Some wallets/interfaces might not even bother to look at this information.
*/
string public name; //fancy name: eg Simon Bucks
uint8 public decimals; //How many decimals to show.
string public symbol; //An identifier: eg SBX
function EIP20(
uint256 _initialAmount,
string _tokenName,
uint8 _decimalUnits,
string _tokenSymbol
) public {
balances[msg.sender] = _initialAmount; // Give the creator all initial tokens
totalSupply = _initialAmount; // Update total supply
name = _tokenName; // Set the name for display purposes
decimals = _decimalUnits; // Amount of decimals for display purposes
symbol = _tokenSymbol; // Set the symbol for display purposes
}
function transfer(address _to, uint256 _value) public returns (bool success) {
//Default assumes totalSupply can't be over max (2^256 - 1).
//If your token leaves out totalSupply and can issue more tokens as time goes on, you need to check if it doesn't wrap.
//Replace the if with this one instead.
//require(balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]);
require(balances[msg.sender] >= _value);
balances[msg.sender] -= _value;
balances[_to] += _value;
Transfer(msg.sender, _to, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
//same as above. Replace this line with the following if you want to protect against wrapping uints.
//require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]);
uint256 allowance = allowed[_from][msg.sender];
require(balances[_from] >= _value && allowance >= _value);
balances[_to] += _value;
balances[_from] -= _value;
if (allowance < MAX_UINT256) {
allowed[_from][msg.sender] -= _value;
}
Transfer(_from, _to, _value);
return true;
}
function balanceOf(address _owner) view public returns (uint256 balance) {
return balances[_owner];
}
function approve(address _spender, uint256 _value) public returns (bool success) {
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender)
view public returns (uint256 remaining) {
return allowed[_owner][_spender];
}
mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed;
}
// File: plcr-revival/PLCRFactory.sol
contract PLCRFactory {
event newPLCR(address creator, EIP20 token, PLCRVoting plcr);
ProxyFactory public proxyFactory;
PLCRVoting public canonizedPLCR;
/// @dev constructor deploys a new canonical PLCRVoting contract and a proxyFactory.
constructor() {
canonizedPLCR = new PLCRVoting();
proxyFactory = new ProxyFactory();
}
/*
@dev deploys and initializes a new PLCRVoting contract that consumes a token at an address
supplied by the user.
@param _token an EIP20 token to be consumed by the new PLCR contract
*/
function newPLCRBYOToken(EIP20 _token) public returns (PLCRVoting) {
PLCRVoting plcr = PLCRVoting(proxyFactory.createProxy(canonizedPLCR, ""));
plcr.init(_token);
emit newPLCR(msg.sender, _token, plcr);
return plcr;
}
/*
@dev deploys and initializes a new PLCRVoting contract and an EIP20 to be consumed by the PLCR's
initializer.
@param _supply the total number of tokens to mint in the EIP20 contract
@param _name the name of the new EIP20 token
@param _decimals the decimal precision to be used in rendering balances in the EIP20 token
@param _symbol the symbol of the new EIP20 token
*/
function newPLCRWithToken(
uint _supply,
string _name,
uint8 _decimals,
string _symbol
) public returns (PLCRVoting) {
// Create a new token and give all the tokens to the PLCR creator
EIP20 token = new EIP20(_supply, _name, _decimals, _symbol);
token.transfer(msg.sender, _supply);
// Create and initialize a new PLCR contract
PLCRVoting plcr = PLCRVoting(proxyFactory.createProxy(canonizedPLCR, ""));
plcr.init(token);
emit newPLCR(msg.sender, token, plcr);
return plcr;
}
}
// File: contracts/ParameterizerFactory.sol
contract ParameterizerFactory {
event NewParameterizer(address creator, address token, address plcr, Parameterizer parameterizer);
PLCRFactory public plcrFactory;
ProxyFactory public proxyFactory;
Parameterizer public canonizedParameterizer;
/// @dev constructor deploys a new canonical Parameterizer contract and a proxyFactory.
constructor(PLCRFactory _plcrFactory) public {
plcrFactory = _plcrFactory;
proxyFactory = plcrFactory.proxyFactory();
canonizedParameterizer = new Parameterizer();
}
/*
@dev deploys and initializes a new Parameterizer contract that consumes a token at an address
supplied by the user.
@param _token an EIP20 token to be consumed by the new Parameterizer contract
@param _plcr a PLCR voting contract to be consumed by the new Parameterizer contract
@param _parameters array of canonical parameters
*/
function newParameterizerBYOToken(
EIP20 _token,
uint[] _parameters
) public returns (Parameterizer) {
PLCRVoting plcr = plcrFactory.newPLCRBYOToken(_token);
Parameterizer parameterizer = Parameterizer(proxyFactory.createProxy(canonizedParameterizer, ""));
parameterizer.init(
_token,
plcr,
_parameters
);
emit NewParameterizer(msg.sender, _token, plcr, parameterizer);
return parameterizer;
}
/*
@dev deploys and initializes new EIP20, PLCRVoting, and Parameterizer contracts
@param _supply the total number of tokens to mint in the EIP20 contract
@param _name the name of the new EIP20 token
@param _decimals the decimal precision to be used in rendering balances in the EIP20 token
@param _symbol the symbol of the new EIP20 token
@param _parameters array of canonical parameters
*/
function newParameterizerWithToken(
uint _supply,
string _name,
uint8 _decimals,
string _symbol,
uint[] _parameters
) public returns (Parameterizer) {
// Creates a new EIP20 token & transfers the supply to creator (msg.sender)
// Deploys & initializes a new PLCRVoting contract
PLCRVoting plcr = plcrFactory.newPLCRWithToken(_supply, _name, _decimals, _symbol);
EIP20 token = EIP20(plcr.token());
token.transfer(msg.sender, _supply);
// Create & initialize a new Parameterizer contract
Parameterizer parameterizer = Parameterizer(proxyFactory.createProxy(canonizedParameterizer, ""));
parameterizer.init(
token,
plcr,
_parameters
);
emit NewParameterizer(msg.sender, token, plcr, parameterizer);
return parameterizer;
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"constant":false,"inputs":[{"name":"_supply","type":"uint256"},{"name":"_name","type":"string"},{"name":"_decimals","type":"uint8"},{"name":"_symbol","type":"string"},{"name":"_parameters","type":"uint256[]"}],"name":"newParameterizerWithToken","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_parameters","type":"uint256[]"}],"name":"newParameterizerBYOToken","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"plcrFactory","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"proxyFactory","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"canonizedParameterizer","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_plcrFactory","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"creator","type":"address"},{"indexed":false,"name":"token","type":"address"},{"indexed":false,"name":"plcr","type":"address"},{"indexed":false,"name":"parameterizer","type":"address"}],"name":"NewParameterizer","type":"event"}]Contract Creation Code
608060405234801561001057600080fd5b50604051602080614c6383398101806040528101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c10f1a756040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1580156100f857600080fd5b505af115801561010c573d6000803e3d6000fd5b505050506040513d602081101561012257600080fd5b8101908080519060200190929190505050600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061017b6101de565b604051809103906000f080158015610197573d6000803e3d6000fd5b50600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506101ee565b604051613b328061113183390190565b610f34806101fd6000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631f4d7ec4146100725780637087ec14146101bb578063ad3eb71f14610281578063c10f1a75146102d8578063c34fb5ca1461032f575b600080fd5b34801561007e57600080fd5b5061017960048036038101908080359060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803560ff169060200190929190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290505050610386565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101c757600080fd5b5061023f600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290505050610a2f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561028d57600080fd5b50610296610e97565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e457600080fd5b506102ed610ebc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561033b57600080fd5b50610344610ee2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000806000806000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bf6c4de98a8a8a8a6040518563ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180858152602001806020018460ff1660ff16815260200180602001838103835286818151815260200191508051906020019080838360005b8381101561044e578082015181840152602081019050610433565b50505050905090810190601f16801561047b5780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b838110156104b4578082015181840152602081019050610499565b50505050905090810190601f1680156104e15780820380516001836020036101000a031916815260200191505b509650505050505050602060405180830381600087803b15801561050457600080fd5b505af1158015610518573d6000803e3d6000fd5b505050506040513d602081101561052e57600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff1663fc0c546a6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1580156105a557600080fd5b505af11580156105b9573d6000803e3d6000fd5b505050506040513d60208110156105cf57600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb338b6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561068557600080fd5b505af1158015610699573d6000803e3d6000fd5b505050506040513d60208110156106af57600080fd5b810190808051906020019092919050505050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166361b69abd600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018060200182810382526000815260200160200192505050602060405180830381600087803b1580156107b457600080fd5b505af11580156107c8573d6000803e3d6000fd5b505050506040513d60208110156107de57600080fd5b810190808051906020019092919050505090508073ffffffffffffffffffffffffffffffffffffffff166344b776808385886040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019060200280838360005b838110156108e25780820151818401526020810190506108c7565b50505050905001945050505050600060405180830381600087803b15801561090957600080fd5b505af115801561091d573d6000803e3d6000fd5b505050507ff4a0eaa30ff3ec1d59441beedaa51ca40523fa3157d309772749e14cfa9f934633838584604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200194505050505060405180910390a180935050505095945050505050565b60008060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d5b8169c866040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b158015610af057600080fd5b505af1158015610b04573d6000803e3d6000fd5b505050506040513d6020811015610b1a57600080fd5b81019080805190602001909291905050509150600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166361b69abd600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018060200182810382526000815260200160200192505050602060405180830381600087803b158015610c2057600080fd5b505af1158015610c34573d6000803e3d6000fd5b505050506040513d6020811015610c4a57600080fd5b810190808051906020019092919050505090508073ffffffffffffffffffffffffffffffffffffffff166344b776808684876040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019060200280838360005b83811015610d4e578082015181840152602081019050610d33565b50505050905001945050505050600060405180830381600087803b158015610d7557600080fd5b505af1158015610d89573d6000803e3d6000fd5b505050507ff4a0eaa30ff3ec1d59441beedaa51ca40523fa3157d309772749e14cfa9f934633868484604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200194505050505060405180910390a1809250505092915050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16815600a165627a7a7230582021d7de9c18043baf9fd62a17222eb70752cede4162b4a431c531b674b50a73c90029608060405262093a8060055534801561001757600080fd5b50613b0b806100276000396000f300608060405260043610610106576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806229514f1461010b57806330490e911461013657806332ed5b1214610167578063353009901461026757806344b77680146102b057806350411552146103565780635f02116f14610397578063693ec85e1461044057806377609a41146104bd5780638240ae4b1461050657806386bb8f371461054b5780638f1d377614610582578063a5ba3b1e1461060f578063a7aad3db14610674578063bade1c54146106df578063c51131fb1461076e578063dc6ab527146107b7578063fc0c546a146107fc578063fce1ccca14610853575b600080fd5b34801561011757600080fd5b506101206108aa565b6040518082815260200191505060405180910390f35b34801561014257600080fd5b5061016560048036038101908080356000191690602001909291905050506108b0565b005b34801561017357600080fd5b506101966004803603810190808035600019169060200190929190505050611019565b60405180888152602001878152602001868152602001806020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001838152602001828103825286818151815260200191508051906020019080838360005b8381101561022657808201518184015260208101905061020b565b50505050905090810190601f1680156102535780820380516001836020036101000a031916815260200191505b509850505050505050505060405180910390f35b34801561027357600080fd5b506102966004803603810190808035600019169060200190929190505050611113565b604051808215151515815260200191505060405180910390f35b3480156102bc57600080fd5b50610354600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929050505061113d565b005b34801561036257600080fd5b50610381600480360381019080803590602001909291905050506116ac565b6040518082815260200191505060405180910390f35b3480156103a357600080fd5b5061043e60048036038101908080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192905050506117dc565b005b34801561044c57600080fd5b506104a7600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050611846565b6040518082815260200191505060405180910390f35b3480156104c957600080fd5b506104ec60048036038101908080356000191690602001909291905050506118cc565b604051808215151515815260200191505060405180910390f35b34801561051257600080fd5b506105356004803603810190808035600019169060200190929190505050611be2565b6040518082815260200191505060405180910390f35b34801561055757600080fd5b50610580600480360381019080803590602001909291908035906020019092919050505061231b565b005b34801561058e57600080fd5b506105ad600480360381019080803590602001909291905050506126f1565b604051808681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001841515151581526020018381526020018281526020019550505050505060405180910390f35b34801561061b57600080fd5b5061065a60048036038101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612754565b604051808215151515815260200191505060405180910390f35b34801561068057600080fd5b506106c9600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291905050506127bf565b6040518082815260200191505060405180910390f35b3480156106eb57600080fd5b50610750600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192908035906020019092919050505061291b565b60405180826000191660001916815260200191505060405180910390f35b34801561077a57600080fd5b5061079d6004803603810190808035600019169060200190929190505050612fec565b604051808215151515815260200191505060405180910390f35b3480156107c357600080fd5b506107e66004803603810190808035600019169060200190929190505050613177565b6040518082815260200191505060405180910390f35b34801561080857600080fd5b5061081161318f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561085f57600080fd5b506108686131b5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60055481565b600080600060026000856000191660001916815260200190815260200160002092508260040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691508260020154905061090984612fec565b15610c12576109b8836003018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109a95780601f1061097e576101008083540402835291602001916109a9565b820191906000526020600020905b81548152906001019060200180831161098c57829003601f168201915b505050505084600601546131db565b83600019167f37f3986c71e1aa2c470cfc4a92af70820610c3065589d35ef1664ea27f3e73a58460030185600601546040518080602001838152602001828103825284818154600181600116156101000203166002900481526020019150805460018160011615610100020316600290048015610a765780601f10610a4b57610100808354040283529160200191610a76565b820191906000526020600020905b815481529060010190602001808311610a5957829003601f168201915b5050935050505060405180910390a260026000856000191660001916815260200190815260200160002060008082016000905560018201600090556002820160009055600382016000610ac99190613956565b6004820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600582016000905560068201600090555050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015610bc757600080fd5b505af1158015610bdb573d6000803e3d6000fd5b505050506040513d6020811015610bf157600080fd5b81019080805190602001909291905050501515610c0d57600080fd5b610dff565b610c1b846118cc565b15610c2e57610c2984613260565b610dfe565b8260050154421115610df85783600019167f29026cb2acebe6d0a4b6d593ccadf76e3fc6d0a02254e078b0c4a619608089d760405160405180910390a260026000856000191660001916815260200190815260200160002060008082016000905560018201600090556002820160009055600382016000610caf9190613956565b6004820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600582016000905560068201600090555050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015610dad57600080fd5b505af1158015610dc1573d6000803e3d6000fd5b505050506040513d6020811015610dd757600080fd5b81019080805190602001909291905050501515610df357600080fd5b610dfd565b600080fd5b5b5b6064610e3f6040805190810160405280600f81526020017f64697370656e736174696f6e5063740000000000000000000000000000000000815250611846565b11151515610e4957fe5b6064610e896040805190810160405280601081526020017f7044697370656e736174696f6e50637400000000000000000000000000000000815250611846565b11151515610e9357fe5b610f95600554610f87610eda6040805190810160405280600f81526020017f7052657665616c53746167654c656e0000000000000000000000000000000000815250611846565b610f79610f1b6040805190810160405280600f81526020017f70436f6d6d697453746167654c656e0000000000000000000000000000000000815250611846565b610f6b610f5c6040805190810160405280600e81526020017f704170706c7953746167654c656e000000000000000000000000000000000000815250611846565b426138d190919063ffffffff16565b6138d190919063ffffffff16565b6138d190919063ffffffff16565b6138d190919063ffffffff16565b5060026000856000191660001916815260200190815260200160002060008082016000905560018201600090556002820160009055600382016000610fda9190613956565b6004820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560058201600090556006820160009055505050505050565b6002602052806000526040600020600091509050806000015490806001015490806002015490806003018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156110d75780601f106110ac576101008083540402835291602001916110d7565b820191906000526020600020905b8154815290600101906020018083116110ba57829003601f168201915b5050505050908060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060050154908060060154905087565b60008060026000846000191660001916815260200190815260200160002060050154119050919050565b60008373ffffffffffffffffffffffffffffffffffffffff161415801561119c57506000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b15156111a757600080fd5b60008273ffffffffffffffffffffffffffffffffffffffff161415801561120657506000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b151561121157600080fd5b82600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506112ea6040805190810160405280600a81526020017f6d696e4465706f736974000000000000000000000000000000000000000000008152508260008151811015156112db57fe5b906020019060200201516131db565b6113416040805190810160405280600b81526020017f704d696e4465706f73697400000000000000000000000000000000000000000081525082600181518110151561133257fe5b906020019060200201516131db565b6113986040805190810160405280600d81526020017f6170706c7953746167654c656e0000000000000000000000000000000000000081525082600281518110151561138957fe5b906020019060200201516131db565b6113ef6040805190810160405280600e81526020017f704170706c7953746167654c656e0000000000000000000000000000000000008152508260038151811015156113e057fe5b906020019060200201516131db565b6114466040805190810160405280600e81526020017f636f6d6d697453746167654c656e00000000000000000000000000000000000081525082600481518110151561143757fe5b906020019060200201516131db565b61149d6040805190810160405280600f81526020017f70436f6d6d697453746167654c656e000000000000000000000000000000000081525082600581518110151561148e57fe5b906020019060200201516131db565b6114f46040805190810160405280600e81526020017f72657665616c53746167654c656e0000000000000000000000000000000000008152508260068151811015156114e557fe5b906020019060200201516131db565b61154b6040805190810160405280600f81526020017f7052657665616c53746167654c656e000000000000000000000000000000000081525082600781518110151561153c57fe5b906020019060200201516131db565b6115a26040805190810160405280600f81526020017f64697370656e736174696f6e506374000000000000000000000000000000000081525082600881518110151561159357fe5b906020019060200201516131db565b6115f96040805190810160405280601081526020017f7044697370656e736174696f6e506374000000000000000000000000000000008152508260098151811015156115ea57fe5b906020019060200201516131db565b6116506040805190810160405280600a81526020017f766f746551756f72756d0000000000000000000000000000000000000000000081525082600a81518110151561164157fe5b906020019060200201516131db565b6116a76040805190810160405280600b81526020017f70566f746551756f72756d00000000000000000000000000000000000000000081525082600b81518110151561169857fe5b906020019060200201516131db565b505050565b600080600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663053e71a6846040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b15801561174057600080fd5b505af1158015611754573d6000803e3d6000fd5b505050506040513d602081101561176a57600080fd5b810190808051906020019092919050505014156117a257600160008381526020019081526020016000206002015460020290506117d7565b600160008381526020019081526020016000206000015460016000848152602001908152602001600020600201546002020390505b919050565b6000815183511415156117ee57600080fd5b600090505b825181101561184157611834838281518110151561180d57fe5b90602001906020020151838381518110151561182557fe5b9060200190602002015161231b565b80806001019150506117f3565b505050565b6000806000836040518082805190602001908083835b602083101515611881578051825260208201915060208101905060208303925061185c565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916600019168152602001908152602001600020549050919050565b60006118d661399e565b6118de6139f2565b60026000856000191660001916815260200190815260200160002060e06040519081016040529081600082015481526020016001820154815260200160028201548152602001600382018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156119bc5780601f10611991576101008083540402835291602001916119bc565b820191906000526020600020905b81548152906001019060200180831161199f57829003601f168201915b505050505081526020016004820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600582015481526020016006820154815250509150600160008360200151815260200190815260200160002060a06040519081016040529081600082015481526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160149054906101000a900460ff1615151515815260200160028201548152602001600382015481525050905060008260200151118015611b0157506000151581604001511515145b8015611bd95750600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ee68483083602001516040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b158015611b9d57600080fd5b505af1158015611bb1573d6000803e3d6000fd5b505050506040513d6020811015611bc757600080fd5b81019080805190602001909291905050505b92505050919050565b6000611bec61399e565b60008060008060026000886000191660001916815260200190815260200160002060e06040519081016040529081600082015481526020016001820154815260200160028201548152602001600382018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611cd05780601f10611ca557610100808354040283529160200191611cd0565b820191906000526020600020905b815481529060010190602001808311611cb357829003601f168201915b505050505081526020016004820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160058201548152602001600682015481525050945084604001519350611d5587611113565b8015611d65575060008560200151145b1515611d7057600080fd5b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166332ed3d60611dec6040805190810160405280600b81526020017f70566f746551756f72756d000000000000000000000000000000000000000000815250611846565b611e2a6040805190810160405280600f81526020017f70436f6d6d697453746167654c656e0000000000000000000000000000000000815250611846565b611e686040805190810160405280600f81526020017f7052657665616c53746167654c656e0000000000000000000000000000000000815250611846565b6040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808481526020018381526020018281526020019350505050602060405180830381600087803b158015611ec857600080fd5b505af1158015611edc573d6000803e3d6000fd5b505050506040513d6020811015611ef257600080fd5b8101908080519060200190929190505050925060a060405190810160405280611f7e6064611f7088611f626064611f5d6040805190810160405280601081526020017f7044697370656e736174696f6e50637400000000000000000000000000000000815250611846565b6138ef565b61390890919063ffffffff16565b61393b90919063ffffffff16565b81526020013373ffffffffffffffffffffffffffffffffffffffff1681526020016000151581526020018581526020016000815250600160008581526020019081526020016000206000820151816000015560208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160146101000a81548160ff02191690831515021790555060608201518160020155608082015181600301559050508260026000896000191660001916815260200190815260200160002060010181905550600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330876040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801561216a57600080fd5b505af115801561217e573d6000803e3d6000fd5b505050506040513d602081101561219457600080fd5b810190808051906020019092919050505015156121b057600080fd5b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636148fed5846040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018082815260200191505060a060405180830381600087803b15801561224157600080fd5b505af1158015612255573d6000803e3d6000fd5b505050506040513d60a081101561226b57600080fd5b810190808051906020019092919080519060200190929190805190602001909291908051906020019092919080519060200190929190505050505050915091503373ffffffffffffffffffffffffffffffffffffffff1687600019167fe94e3086c4bfe84acba4437b85a80fca3721dfc419d1f7afe4fa4e470e670b4885858560405180848152602001838152602001828152602001935050505060405180910390a38295505050505050919050565b600080600015156001600086815260200190815260200160002060040160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514151561239157600080fd5b600115156001600086815260200190815260200160002060010160149054906101000a900460ff1615151415156123c757600080fd5b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b43bd0693386866040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018381526020018281526020019350505050602060405180830381600087803b15801561249457600080fd5b505af11580156124a8573d6000803e3d6000fd5b505050506040513d60208110156124be57600080fd5b810190808051906020019092919050505091506124dc3385856127bf565b9050816001600086815260200190815260200160002060030160008282540392505081905550806001600086815260200190815260200160002060000160008282540392505081905550600180600086815260200190815260200160002060040160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff16847f6f4c982acc31b0af2cf1dc1556f21c0325d893782d65e83c68a5534a33f59957836040518082815260200191505060405180910390a3600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156126a557600080fd5b505af11580156126b9573d6000803e3d6000fd5b505050506040513d60208110156126cf57600080fd5b810190808051906020019092919050505015156126eb57600080fd5b50505050565b60016020528060005260406000206000915090508060000154908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010160149054906101000a900460ff16908060020154908060030154905085565b60006001600084815260200190815260200160002060040160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6000806000806001600087815260200190815260200160002060030154925060016000878152602001908152602001600020600001549150600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b43bd0698888886040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018381526020018281526020019350505050602060405180830381600087803b1580156128c457600080fd5b505af11580156128d8573d6000803e3d6000fd5b505050506040513d60208110156128ee57600080fd5b810190808051906020019092919050505090508282820281151561290e57fe5b0493505050509392505050565b600080600061295e6040805190810160405280600b81526020017f704d696e4465706f736974000000000000000000000000000000000000000000815250611846565b915084846040518083805190602001908083835b6020831015156129975780518252602082019150602081019050602083039250612972565b6001836020036101000a038019825116818451168082178552505050505050905001828152602001925050506040518091039020905060405180807f64697370656e736174696f6e5063740000000000000000000000000000000000815250600f019050604051809103902060001916856040518082805190602001908083835b602083101515612a3d5780518252602082019150602081019050602083039250612a18565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019161480612b18575060405180807f7044697370656e736174696f6e506374000000000000000000000000000000008152506010019050604051809103902060001916856040518082805190602001908083835b602083101515612ae55780518252602082019150602081019050602083039250612ac0565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916145b15612b2e5760648411151515612b2d57600080fd5b5b612b3781611113565b151515612b4357600080fd5b83612b4d86611846565b14151515612b5a57600080fd5b60e060405190810160405280612bb6612ba76040805190810160405280600e81526020017f704170706c7953746167654c656e000000000000000000000000000000000000815250611846565b426138d190919063ffffffff16565b8152602001600081526020018381526020018681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001612cec600554612cde612c316040805190810160405280600f81526020017f7052657665616c53746167654c656e0000000000000000000000000000000000815250611846565b612cd0612c726040805190810160405280600f81526020017f70436f6d6d697453746167654c656e0000000000000000000000000000000000815250611846565b612cc2612cb36040805190810160405280600e81526020017f704170706c7953746167654c656e000000000000000000000000000000000000815250611846565b426138d190919063ffffffff16565b6138d190919063ffffffff16565b6138d190919063ffffffff16565b6138d190919063ffffffff16565b8152602001858152506002600083600019166000191681526020019081526020016000206000820151816000015560208201518160010155604082015181600201556060820151816003019080519060200190612d4a929190613a3a565b5060808201518160040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a0820151816005015560c08201518160060155905050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b158015612ea257600080fd5b505af1158015612eb6573d6000803e3d6000fd5b505050506040513d6020811015612ecc57600080fd5b81019080805190602001909291905050501515612ee857600080fd5b3373ffffffffffffffffffffffffffffffffffffffff167fb25bdef16105f099e5c185f9c7fd969571e8e0caa3f7bd75409512fe0a41a60b868684866002600088600019166000191681526020019081526020016000206000015460405180806020018681526020018560001916600019168152602001848152602001838152602001828103825287818151815260200191508051906020019080838360005b83811015612fa3578082015181840152602081019050612f88565b50505050905090810190601f168015612fd05780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a2809250505092915050565b6000612ff661399e565b60026000846000191660001916815260200190815260200160002060e06040519081016040529081600082015481526020016001820154815260200160028201548152602001600382018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156130d45780601f106130a9576101008083540402835291602001916130d4565b820191906000526020600020905b8154815290600101906020018083116130b757829003601f168201915b505050505081526020016004820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160058201548152602001600682015481525050905080600001514211801561315f57508060a0015142105b801561316f575060008160200151145b915050919050565b60006020528060005260406000206000915090505481565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b80600080846040518082805190602001908083835b60208310151561321557805182526020820191506020810190506020830392506131f0565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916600019168152602001908152602001600020819055505050565b61326861399e565b60008060026000856000191660001916815260200190815260200160002060e06040519081016040529081600082015481526020016001820154815260200160028201548152602001600382018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156133495780601f1061331e57610100808354040283529160200191613349565b820191906000526020600020905b81548152906001019060200180831161332c57829003601f168201915b505050505081526020016004820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600582015481526020016006820154815250509250600160008460200151815260200190815260200160002091506133e483602001516116ac565b9050600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663053e71a684602001516040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b15801561347b57600080fd5b505af115801561348f573d6000803e3d6000fd5b505050506040513d60208110156134a557600080fd5b8101908080519060200190929190505050826003018190555060018260010160146101000a81548160ff021916908315150217905550600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634940318384602001516040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b15801561357057600080fd5b505af1158015613584573d6000803e3d6000fd5b505050506040513d602081101561359a57600080fd5b81019080805190602001909291905050501561373457428360a0015111156135cf576135ce83606001518460c001516131db565b5b826020015184600019167fc4497224aa78dd50c9b3e344aab02596201ca1e6dca4057a91a6c02f83f4f6c184600001548560030154604051808381526020018281526020019250505060405180910390a3600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8460800151836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156136e957600080fd5b505af11580156136fd573d6000803e3d6000fd5b505050506040513d602081101561371357600080fd5b8101908080519060200190929190505050151561372f57600080fd5b6138cb565b826020015184600019167f362a12431f779a2baff4f77f75ba7960ae993a5c41b425df11f7fd0af2b9cbe684600001548560030154604051808381526020018281526020019250505060405180910390a3600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600160008660200151815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561388457600080fd5b505af1158015613898573d6000803e3d6000fd5b505050506040513d60208110156138ae57600080fd5b810190808051906020019092919050505015156138ca57600080fd5b5b50505050565b60008082840190508381101515156138e557fe5b8091505092915050565b60008282111515156138fd57fe5b818303905092915050565b60008082840290506000841480613929575082848281151561392657fe5b04145b151561393157fe5b8091505092915050565b600080828481151561394957fe5b0490508091505092915050565b50805460018160011615610100020316600290046000825580601f1061397c575061399b565b601f01602090049060005260206000209081019061399a9190613aba565b5b50565b60e06040519081016040528060008152602001600081526020016000815260200160608152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081525090565b60a06040519081016040528060008152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160001515815260200160008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613a7b57805160ff1916838001178555613aa9565b82800160010185558215613aa9579182015b82811115613aa8578251825591602001919060010190613a8d565b5b509050613ab69190613aba565b5090565b613adc91905b80821115613ad8576000816000905550600101613ac0565b5090565b905600a165627a7a723058206911d935c2d795dd9196cee19eff246428da3852116f509158450e197092bb6f0029000000000000000000000000df9c10e2e9bb8968b908261d38860b1a038cc2ef
Deployed Bytecode
0x60806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631f4d7ec4146100725780637087ec14146101bb578063ad3eb71f14610281578063c10f1a75146102d8578063c34fb5ca1461032f575b600080fd5b34801561007e57600080fd5b5061017960048036038101908080359060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803560ff169060200190929190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290505050610386565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101c757600080fd5b5061023f600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290505050610a2f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561028d57600080fd5b50610296610e97565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e457600080fd5b506102ed610ebc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561033b57600080fd5b50610344610ee2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000806000806000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bf6c4de98a8a8a8a6040518563ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180858152602001806020018460ff1660ff16815260200180602001838103835286818151815260200191508051906020019080838360005b8381101561044e578082015181840152602081019050610433565b50505050905090810190601f16801561047b5780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b838110156104b4578082015181840152602081019050610499565b50505050905090810190601f1680156104e15780820380516001836020036101000a031916815260200191505b509650505050505050602060405180830381600087803b15801561050457600080fd5b505af1158015610518573d6000803e3d6000fd5b505050506040513d602081101561052e57600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff1663fc0c546a6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1580156105a557600080fd5b505af11580156105b9573d6000803e3d6000fd5b505050506040513d60208110156105cf57600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb338b6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561068557600080fd5b505af1158015610699573d6000803e3d6000fd5b505050506040513d60208110156106af57600080fd5b810190808051906020019092919050505050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166361b69abd600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018060200182810382526000815260200160200192505050602060405180830381600087803b1580156107b457600080fd5b505af11580156107c8573d6000803e3d6000fd5b505050506040513d60208110156107de57600080fd5b810190808051906020019092919050505090508073ffffffffffffffffffffffffffffffffffffffff166344b776808385886040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019060200280838360005b838110156108e25780820151818401526020810190506108c7565b50505050905001945050505050600060405180830381600087803b15801561090957600080fd5b505af115801561091d573d6000803e3d6000fd5b505050507ff4a0eaa30ff3ec1d59441beedaa51ca40523fa3157d309772749e14cfa9f934633838584604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200194505050505060405180910390a180935050505095945050505050565b60008060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d5b8169c866040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b158015610af057600080fd5b505af1158015610b04573d6000803e3d6000fd5b505050506040513d6020811015610b1a57600080fd5b81019080805190602001909291905050509150600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166361b69abd600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018060200182810382526000815260200160200192505050602060405180830381600087803b158015610c2057600080fd5b505af1158015610c34573d6000803e3d6000fd5b505050506040513d6020811015610c4a57600080fd5b810190808051906020019092919050505090508073ffffffffffffffffffffffffffffffffffffffff166344b776808684876040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019060200280838360005b83811015610d4e578082015181840152602081019050610d33565b50505050905001945050505050600060405180830381600087803b158015610d7557600080fd5b505af1158015610d89573d6000803e3d6000fd5b505050507ff4a0eaa30ff3ec1d59441beedaa51ca40523fa3157d309772749e14cfa9f934633868484604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200194505050505060405180910390a1809250505092915050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16815600a165627a7a7230582021d7de9c18043baf9fd62a17222eb70752cede4162b4a431c531b674b50a73c90029
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000df9c10e2e9bb8968b908261d38860b1a038cc2ef
-----Decoded View---------------
Arg [0] : _plcrFactory (address): 0xdF9C10E2E9bb8968B908261d38860B1a038cc2EF
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000df9c10e2e9bb8968b908261d38860b1a038cc2ef
Swarm Source
bzzr://6911d935c2d795dd9196cee19eff246428da3852116f509158450e197092bb6f
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.