Contract Address Details
contract
0x5489443C7Fa9F408683273bF06f67dDB380D0960
Sponsored:
- Contract name:
- Voting
- Optimization enabled
- true
- Compiler version
- v0.4.26+commit.4563c3fc
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2023-10-02T01:57:01.019585Z
Contract source code
// File: contracts/abstracts/VotingBase.sol
pragma solidity ^0.4.24;
/**
* @title Interface to be implemented by voting contract
* @author LiorRabin
* @dev abstract contract
*/
contract VotingBase {
/**
* @dev Possible states of quorum
* @param InProgress - state while a ballot has not been finalized yet
* @param Accepted - state after finalizing the ballot and majority have voted ActionChoices.Accept
* @param Rejected - state after finalizing the ballot and majority have voted ActionChoices.Reject
*/
enum QuorumStates {
Invalid,
InProgress,
Accepted,
Rejected
}
/**
* @dev Possible choices for a ballot
*/
enum ActionChoices {
Invalid,
Accept,
Reject
}
/**
* @dev This event will be emitted every time a new ballot is created
* @param id ballot id
* @param creator address of ballot creator
*/
event BallotCreated(uint256 indexed id, address indexed creator);
/**
* @dev This event will be emitted when a ballot if finalized
* @param id ballot id
*/
event BallotFinalized(uint256 indexed id);
/**
* @dev This event will be emitted on each vote
* @param id ballot id
* @param decision voter decision (see VotingBase.ActionChoices)
* @param voter address of the voter
*/
event Vote(uint256 indexed id, uint256 decision, address indexed voter);
/**
* @dev Function to be called when voting on a ballot
* @param _id ballot id
* @param _choice voter decision on the ballot (see VotingBase.ActionChoices)
*/
function vote(uint256 _id, uint256 _choice) external;
}
// File: contracts/eternal-storage/EternalStorage.sol
pragma solidity ^0.4.24;
/**
* @title EternalStorage
* @author LiorRabin
* @dev This contract holds all the necessary state variables to carry out the storage of any contract and to support the upgrade functionality.
*/
contract EternalStorage {
// Version number of the current implementation
uint256 internal version;
// Address of the current implementation
address internal implementation;
// Storage mappings
mapping(bytes32 => uint256) internal uintStorage;
mapping(bytes32 => string) internal stringStorage;
mapping(bytes32 => address) internal addressStorage;
mapping(bytes32 => bytes) internal bytesStorage;
mapping(bytes32 => bool) internal boolStorage;
mapping(bytes32 => int256) internal intStorage;
mapping(bytes32 => uint256[]) internal uintArrayStorage;
mapping(bytes32 => string[]) internal stringArrayStorage;
mapping(bytes32 => address[]) internal addressArrayStorage;
mapping(bytes32 => bytes[]) internal bytesArrayStorage;
mapping(bytes32 => bool[]) internal boolArrayStorage;
mapping(bytes32 => int256[]) internal intArrayStorage;
mapping(bytes32 => bytes32[]) internal bytes32ArrayStorage;
function isInitialized() public view returns(bool) {
return boolStorage[keccak256(abi.encodePacked("isInitialized"))];
}
function setInitialized(bool _status) internal {
boolStorage[keccak256(abi.encodePacked("isInitialized"))] = _status;
}
}
// File: contracts/interfaces/IConsensus.sol
pragma solidity ^0.4.24;
interface IConsensus {
function currentValidatorsLength() external view returns(uint256);
function currentValidatorsAtPosition(uint256 _p) external view returns(address);
function getCycleDurationBlocks() external view returns(uint256);
function getCurrentCycleEndBlock() external view returns(uint256);
function cycle(address _validator) external;
function isValidator(address _address) external view returns(bool);
function getDelegatorsForRewardDistribution(address _validator, uint256 _rewardAmount) external view returns(address[], uint256[]);
function isFinalized() external view returns(bool);
function stakeAmount(address _address) external view returns(uint256);
function totalStakeAmount() external view returns(uint256);
}
// File: contracts/eternal-storage/EternalStorageProxy.sol
pragma solidity ^0.4.24;
/**
* @title EternalStorageProxy
* @author LiorRabin
* @dev This proxy holds the storage of the token contract and delegates every call to the current implementation set.
* Besides, it allows to upgrade the token's behaviour towards further implementations, and provides authorization control functionalities
*/
contract EternalStorageProxy is EternalStorage {
/**
* @dev This event will be emitted every time the implementation gets upgraded
* @param version representing the version number of the upgraded implementation
* @param implementation representing the address of the upgraded implementation
*/
event Upgraded(uint256 version, address indexed implementation);
/**
* @dev This event will be emitted when ownership is renounces
* @param previousOwner address which is renounced from ownership
*/
event OwnershipRenounced(address indexed previousOwner);
/**
* @dev This event will be emitted when ownership is transferred
* @param previousOwner address which represents the previous owner
* @param newOwner address which represents the new owner
*/
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev This modifier verifies that msg.sender is the ProxyStorage contract
*/
modifier onlyProxyStorage() {
require(msg.sender == getProxyStorage());
_;
}
/**
* @dev This modifier verifies that msg.sender is the owner of the contract
*/
modifier onlyOwner() {
require(msg.sender == getOwner());
_;
}
/**
* @dev Constructor
* @param _proxyStorage address representing the ProxyStorage contract
* @param _implementation address representing the implementation contract
*/
constructor(address _proxyStorage, address _implementation) public {
require(_implementation != address(0));
if (_proxyStorage != address(0)) {
_setProxyStorage(_proxyStorage);
} else {
_setProxyStorage(address(this));
}
_setImplementation(_implementation);
_setOwner(msg.sender);
}
/**
* @dev Fallback function allowing to perform a delegatecall to the given implementation.
* This function will return whatever the implementation call returns
*/
// solhint-disable no-complex-fallback, no-inline-assembly
function() payable public {
address _impl = getImplementation();
require(_impl != address(0));
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0
calldatacopy(0, 0, calldatasize)
// Call the implementation.
// out and outsize are 0 because we don't know the size yet
let result := delegatecall(gas, _impl, 0, calldatasize, 0, 0)
// Copy the returned data
returndatacopy(0, 0, returndatasize)
switch result
// delegatecall returns 0 on error
case 0 { revert(0, returndatasize) }
default { return(0, returndatasize) }
}
}
// solhint-enable no-complex-fallback, no-inline-assembly
/**
* @dev Allows ProxyStorage contract (only) to upgrade the current implementation.
* @param _newImplementation representing the address of the new implementation to be set.
*/
function upgradeTo(address _newImplementation) public onlyProxyStorage returns(bool) {
if (_newImplementation == address(0)) return false;
if (getImplementation() == _newImplementation) return false;
uint256 _newVersion = getVersion() + 1;
_setVersion(_newVersion);
_setImplementation(_newImplementation);
emit Upgraded(_newVersion, _newImplementation);
return true;
}
/**
* @dev Allows the current owner to relinquish ownership.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipRenounced(getOwner());
_setOwner(address(0));
}
/**
* @dev Allows the current owner to transfer control of the contract to a _newOwner.
* @param _newOwner The address to transfer ownership to.
*/
function transferOwnership(address _newOwner) public onlyOwner {
require(_newOwner != address(0));
emit OwnershipTransferred(getOwner(), _newOwner);
_setOwner(_newOwner);
}
function getOwner() public view returns(address) {
return addressStorage[keccak256(abi.encodePacked("owner"))];
}
function _setOwner(address _owner) private {
addressStorage[keccak256(abi.encodePacked("owner"))] = _owner;
}
function getVersion() public view returns(uint256) {
return version;
}
function _setVersion(uint256 _newVersion) private {
version = _newVersion;
}
function getImplementation() public view returns(address) {
return implementation;
}
function _setImplementation(address _newImplementation) private {
implementation = _newImplementation;
}
function getProxyStorage() public view returns(address) {
return addressStorage[keccak256(abi.encodePacked("proxyStorage"))];
}
function _setProxyStorage(address _proxyStorage) private {
addressStorage[keccak256(abi.encodePacked("proxyStorage"))] = _proxyStorage;
}
}
// File: openzeppelin-solidity/contracts/math/SafeMath.sol
pragma solidity ^0.4.24;
/**
* @title SafeMath
* @dev Math operations with safety checks that revert on error
*/
library SafeMath {
int256 constant private INT256_MIN = -2**255;
/**
* @dev Multiplies two unsigned integers, reverts on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Multiplies two signed integers, reverts on overflow.
*/
function mul(int256 a, int256 b) internal pure returns (int256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
require(!(a == -1 && b == INT256_MIN)); // This is the only case of overflow not detected by the check below
int256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Integer division of two signed integers truncating the quotient, reverts on division by zero.
*/
function div(int256 a, int256 b) internal pure returns (int256) {
require(b != 0); // Solidity only automatically asserts when dividing by 0
require(!(b == -1 && a == INT256_MIN)); // This is the only case of overflow
int256 c = a / b;
return c;
}
/**
* @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
/**
* @dev Subtracts two signed integers, reverts on overflow.
*/
function sub(int256 a, int256 b) internal pure returns (int256) {
int256 c = a - b;
require((b >= 0 && c <= a) || (b < 0 && c > a));
return c;
}
/**
* @dev Adds two unsigned integers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
/**
* @dev Adds two signed integers, reverts on overflow.
*/
function add(int256 a, int256 b) internal pure returns (int256) {
int256 c = a + b;
require((b >= 0 && c >= a) || (b < 0 && c < a));
return c;
}
/**
* @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
* reverts when dividing by zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}
// File: contracts/ProxyStorage.sol
pragma solidity ^0.4.24;
/**
* @title Contract used for access and upgradeability to all network contracts
* @author LiorRabin
*/
contract ProxyStorage is EternalStorage {
using SafeMath for uint256;
/**
* @dev Available contract types on the network
*/
enum ContractTypes {
Invalid,
Consensus,
BlockReward,
ProxyStorage,
Voting
}
/**
* @dev This event will be emitted when all contract addresses have been initialized by the contract owner
*/
event ProxyInitialized(
address consensus,
address blockReward,
address voting
);
/**
* @dev This event will be emitted each time a contract address is updated
* @param contractType contract type (See ContractTypes enum)
* @param contractAddress contract address set for the contract type
*/
event AddressSet(uint256 contractType, address contractAddress);
/**
* @dev This modifier verifies that msg.sender is the owner of the contract
*/
modifier onlyOwner() {
require(msg.sender == addressStorage[OWNER]);
_;
}
/**
* @dev This modifier verifies that msg.sender is the voting contract which implement proxy address change
*/
modifier onlyVoting() {
require(msg.sender == getVoting());
_;
}
/**
* @dev Function to be called on contract initialization
* @param _consensus address of the network consensus contract
*/
function initialize(address _consensus) external onlyOwner {
require(!isInitialized());
require(_consensus != address(0));
require(_consensus != address(this));
_setConsensus(_consensus);
setInitialized(true);
}
/**
* @dev Function to be called to initialize all available contract types addresses
*/
function initializeAddresses(address _blockReward, address _voting) external onlyOwner {
require(!boolStorage[PROXY_STORAGE_ADDRESSES_INITIALIZED]);
addressStorage[BLOCK_REWARD] = _blockReward;
addressStorage[VOTING] = _voting;
boolStorage[PROXY_STORAGE_ADDRESSES_INITIALIZED] = true;
emit ProxyInitialized(
getConsensus(),
_blockReward,
_voting
);
}
/**
* @dev Function to be called to set specific contract type address
* @param _contractType contract type (See ContractTypes enum)
* @param _contractAddress contract address set for the contract type
*/
function setContractAddress(uint256 _contractType, address _contractAddress) external onlyVoting returns(bool) {
if (!isInitialized()) return false;
if (_contractAddress == address(0)) return false;
bool success = false;
if (_contractType == uint256(ContractTypes.Consensus)) {
success = EternalStorageProxy(getConsensus()).upgradeTo(_contractAddress);
} else if (_contractType == uint256(ContractTypes.BlockReward)) {
success = EternalStorageProxy(getBlockReward()).upgradeTo(_contractAddress);
} else if (_contractType == uint256(ContractTypes.ProxyStorage)) {
success = EternalStorageProxy(this).upgradeTo(_contractAddress);
} else if (_contractType == uint256(ContractTypes.Voting)) {
success = EternalStorageProxy(getVoting()).upgradeTo(_contractAddress);
}
if (success) {
emit AddressSet(_contractType, _contractAddress);
}
return success;
}
/**
* @dev Function checking if a contract type is valid one for proxy usage
* @param _contractType contract type to check if valid
*/
function isValidContractType(uint256 _contractType) external pure returns(bool) {
return
_contractType == uint256(ContractTypes.Consensus) ||
_contractType == uint256(ContractTypes.BlockReward) ||
_contractType == uint256(ContractTypes.ProxyStorage) ||
_contractType == uint256(ContractTypes.Voting);
}
bytes32 internal constant OWNER = keccak256(abi.encodePacked("owner"));
bytes32 internal constant CONSENSUS = keccak256(abi.encodePacked("consensus"));
bytes32 internal constant BLOCK_REWARD = keccak256(abi.encodePacked("blockReward"));
bytes32 internal constant VOTING = keccak256(abi.encodePacked("voting"));
bytes32 internal constant PROXY_STORAGE_ADDRESSES_INITIALIZED = keccak256(abi.encodePacked("proxyStorageAddressesInitialized"));
function _setConsensus(address _consensus) private {
addressStorage[CONSENSUS] = _consensus;
}
function getConsensus() public view returns(address){
return addressStorage[CONSENSUS];
}
function getBlockReward() public view returns(address){
return addressStorage[BLOCK_REWARD];
}
function getVoting() public view returns(address){
return addressStorage[VOTING];
}
}
// File: contracts/VotingUtils.sol
pragma solidity ^0.4.24;
/**
* @title Voting utility contract
* @author LiorRabin
*/
contract VotingUtils is EternalStorage, VotingBase {
using SafeMath for uint256;
uint256 public constant DECIMALS = 10 ** 18;
uint256 public constant MAX_LIMIT_OF_BALLOTS = 100;
uint256 public constant MIN_BALLOT_DURATION_CYCLES = 2;
uint256 public constant MAX_BALLOT_DURATION_CYCLES = 14;
uint256 public constant MINIMUM_TURNOUT_BP = 2000; //20%
/**
* @dev This modifier verifies that msg.sender is the owner of the contract
*/
modifier onlyOwner() {
require(msg.sender == addressStorage[OWNER]);
_;
}
/**
* @dev This modifier verifies the duration of the ballot is valid
*/
modifier onlyValidDuration(uint256 _startAfterNumberOfCycles, uint256 _cyclesDuration) {
require(_startAfterNumberOfCycles > 0);
require(_cyclesDuration > 0);
require(_cyclesDuration >= getMinBallotDurationCycles());
require(_cyclesDuration <= getMaxBallotDurationCycles());
_;
}
/**
* @dev This modifier verifies an address is valid for voting
*/
modifier onlyValidVotingKey(address _address) {
require(isValidVotingKey(_address));
_;
}
/**
* @dev This modifier verifies that msg.sender is the consensus contract
*/
modifier onlyConsensus() {
require(msg.sender == ProxyStorage(getProxyStorage()).getConsensus());
_;
}
bytes32 internal constant OWNER = keccak256(abi.encodePacked("owner"));
bytes32 internal constant NEXT_BALLOT_ID = keccak256(abi.encodePacked("nextBallotId"));
bytes32 internal constant ACTIVE_BALLOTS = keccak256(abi.encodePacked("activeBallots"));
bytes32 internal constant PROXY_STORAGE = keccak256(abi.encodePacked("proxyStorage"));
/**
* @dev Function to check if a contract type is a valid network contract
* @param _contractType contract type to check (See ProxyStorage.ContractTypes)
*/
function validContractType(uint256 _contractType) public view returns(bool) {
return ProxyStorage(getProxyStorage()).isValidContractType(_contractType);
}
/**
* @dev This function checks if an address is valid for voting (is a validator)
* @param _address the address to check if valid for voting
*/
function isValidVotingKey(address _address) public view returns(bool) {
bool valid = false;
IConsensus consensus = IConsensus(ProxyStorage(getProxyStorage()).getConsensus());
for (uint256 i; i < consensus.currentValidatorsLength(); i++) {
address validator = consensus.currentValidatorsAtPosition(i);
if (validator == _address) {
valid = true;
}
}
return valid;
}
/**
* @dev Function to get the number of "open" (active) ballots each validator (someone with voting rights) can have at the same time
*/
function getBallotLimitPerValidator() public view returns(uint256) {
uint256 validatorsCount = getTotalNumberOfValidators();
if (validatorsCount == 0) {
return MAX_LIMIT_OF_BALLOTS;
}
uint256 limit = MAX_LIMIT_OF_BALLOTS.div(validatorsCount);
if (limit == 0) {
limit = 1;
}
return limit;
}
/**
* @dev Function used to check if a voting key has voted on a specific ballot
* @param _id ballot id to get info of
* @param _key voter key to get if voted already
*/
function hasAlreadyVoted(uint256 _id, address _key) public view returns(bool) {
if (_key == address(0)) {
return false;
}
return getVoterChoice(_id, _key) != 0;
}
/**
* @dev This function is used to check if a ballot can be finalized
* @param _id ballot id to check
*/
function canBeFinalized(uint256 _id) public view returns(bool) {
if (_id >= getNextBallotId()) return false;
if (getStartBlock(_id) > block.number) return false;
if (getIsFinalized(_id)) return false;
return block.number >= getEndBlock(_id);
}
function getProposedValue(uint256 _id) public view returns(address) {
return addressStorage[keccak256(abi.encodePacked("votingState", _id, "proposedValue"))];
}
function _setProposedValue(uint256 _id, address _value) internal {
addressStorage[keccak256(abi.encodePacked("votingState", _id, "proposedValue"))] = _value;
}
function getContractType(uint256 _id) public view returns(uint256) {
return uintStorage[keccak256(abi.encodePacked("votingState", _id, "contractType"))];
}
function _setContractType(uint256 _id, uint256 _value) internal {
uintStorage[keccak256(abi.encodePacked("votingState", _id, "contractType"))] = _value;
}
/**
* @dev This function is used to create a ballot
* @param _startAfterNumberOfCycles number of cycles after which the ballot should open for voting
* @param _cyclesDuration number of cycles the ballot will remain open for voting
* @param _description ballot text description
*/
function _createBallot(uint256 _startAfterNumberOfCycles, uint256 _cyclesDuration, string _description) internal returns(uint256) {
require(isInitialized());
address creator = msg.sender;
require(withinLimit(creator));
uint256 ballotId = getNextBallotId();
_setNextBallotId(ballotId.add(1));
_setStartBlock(ballotId, _startAfterNumberOfCycles);
_setEndBlock(ballotId, _cyclesDuration);
_setIsFinalized(ballotId, false);
_setQuorumState(ballotId, uint256(QuorumStates.InProgress));
_setCreator(ballotId, creator);
_setDescription(ballotId, _description);
_setIndex(ballotId, activeBallotsLength());
_setBelowTurnOut(ballotId, false);
_activeBallotsAdd(ballotId);
_increaseValidatorLimit(creator);
emit BallotCreated(ballotId, creator);
return ballotId;
}
function _finalize(uint256 _id) internal {
if (!getFinalizeCalled(_id)) {
_decreaseValidatorLimit(_id);
_setFinalizeCalled(_id);
}
// check the turnout
if (_checkTurnout(_id)) {
if (getAccepted(_id) > getRejected(_id)) {
if (_finalizeBallot(_id)) {
_setQuorumState(_id, uint256(QuorumStates.Accepted));
} else {
return;
}
} else {
_setQuorumState(_id, uint256(QuorumStates.Rejected));
}
_setBelowTurnOut(_id, false);
} else {
// didn't meet the turn out
_setBelowTurnOut(_id, true);
_setQuorumState(_id, uint256(QuorumStates.Rejected));
}
_deactivateBallot(_id);
_setIsFinalized(_id, true);
emit BallotFinalized(_id);
}
function _deactivateBallot(uint256 _id) internal {
uint256 removedIndex = getIndex(_id);
uint256 lastIndex = activeBallotsLength() - 1;
uint256 lastBallotId = activeBallotsAtIndex(lastIndex);
// Override the removed ballot with the last one.
_activeBallotsSet(removedIndex, lastBallotId);
// Update the index of the last validator.
_setIndex(lastBallotId, removedIndex);
_activeBallotsSet(lastIndex, 0);
_activeBallotsDecreaseLength();
}
function _finalizeBallot(uint256 _id) internal returns(bool) {
return ProxyStorage(getProxyStorage()).setContractAddress(getContractType(_id), getProposedValue(_id));
}
function isActiveBallot(uint256 _id) public view returns(bool) {
return getStartBlock(_id) < block.number && block.number < getEndBlock(_id);
}
function getQuorumState(uint256 _id) external view returns(uint256) {
return uintStorage[keccak256(abi.encodePacked("votingState", _id, "quorumState"))];
}
function _setQuorumState(uint256 _id, uint256 _value) internal {
uintStorage[keccak256(abi.encodePacked("votingState", _id, "quorumState"))] = _value;
}
function getNextBallotId() public view returns(uint256) {
return uintStorage[NEXT_BALLOT_ID];
}
function _setNextBallotId(uint256 _id) internal {
uintStorage[NEXT_BALLOT_ID] = _id;
}
/**
* returns minimum number of cycles a ballot can be open before finalization
*/
function getMinBallotDurationCycles() public pure returns(uint256) {
return MIN_BALLOT_DURATION_CYCLES;
}
/**
* returns maximum number of cycles a ballot can be open before finalization
*/
function getMaxBallotDurationCycles() public pure returns(uint256) {
return MAX_BALLOT_DURATION_CYCLES;
}
function getStartBlock(uint256 _id) public view returns(uint256) {
return uintStorage[keccak256(abi.encodePacked("votingState", _id, "startBlock"))];
}
function _setStartBlock(uint256 _id, uint256 _startAfterNumberOfCycles) internal {
IConsensus consensus = IConsensus(ProxyStorage(getProxyStorage()).getConsensus());
uint256 cycleDurationBlocks = consensus.getCycleDurationBlocks();
uint256 currentCycleEndBlock = consensus.getCurrentCycleEndBlock();
uint256 startBlock = currentCycleEndBlock.add(_startAfterNumberOfCycles.mul(cycleDurationBlocks));
uintStorage[keccak256(abi.encodePacked("votingState", _id, "startBlock"))] = startBlock;
}
function getEndBlock(uint256 _id) public view returns(uint256) {
return uintStorage[keccak256(abi.encodePacked("votingState", _id, "endBlock"))];
}
function _setEndBlock(uint256 _id, uint256 _cyclesDuration) internal {
uint256 cycleDurationBlocks = IConsensus(ProxyStorage(getProxyStorage()).getConsensus()).getCycleDurationBlocks();
uint256 startBlock = getStartBlock(_id);
uint256 endBlock = startBlock.add(_cyclesDuration.mul(cycleDurationBlocks));
uintStorage[keccak256(abi.encodePacked("votingState", _id, "endBlock"))] = endBlock;
}
function getIsFinalized(uint256 _id) public view returns(bool) {
return boolStorage[keccak256(abi.encodePacked("votingState", _id, "isFinalized"))];
}
function _setIsFinalized(uint256 _id, bool _value) internal {
boolStorage[keccak256(abi.encodePacked("votingState", _id, "isFinalized"))] = _value;
}
function getBelowTurnOut(uint256 _id) public view returns(bool) {
return boolStorage[keccak256(abi.encodePacked("votingState", _id, "belowTurnOut"))];
}
function _setBelowTurnOut(uint256 _id, bool _value) internal {
boolStorage[keccak256(abi.encodePacked("votingState", _id, "belowTurnOut"))] = _value;
}
function getDescription(uint256 _id) public view returns(string) {
return stringStorage[keccak256(abi.encodePacked("votingState", _id, "description"))];
}
function _setDescription(uint256 _id, string _value) internal {
stringStorage[keccak256(abi.encodePacked("votingState", _id, "description"))] = _value;
}
function getCreator(uint256 _id) public view returns(address) {
return addressStorage[keccak256(abi.encodePacked("votingState", _id, "creator"))];
}
function _setCreator(uint256 _id, address _value) internal {
addressStorage[keccak256(abi.encodePacked("votingState", _id, "creator"))] = _value;
}
function getIndex(uint256 _id) public view returns(uint256) {
return uintStorage[keccak256(abi.encodePacked("votingState", _id, "index"))];
}
function _setIndex(uint256 _id, uint256 _value) internal {
uintStorage[keccak256(abi.encodePacked("votingState", _id, "index"))] = _value;
}
function activeBallots() public view returns(uint[]) {
return uintArrayStorage[ACTIVE_BALLOTS];
}
function activeBallotsAtIndex(uint256 _index) public view returns(uint256) {
return uintArrayStorage[ACTIVE_BALLOTS][_index];
}
function activeBallotsLength() public view returns(uint256) {
return uintArrayStorage[ACTIVE_BALLOTS].length;
}
function _activeBallotsAdd(uint256 _id) internal {
uintArrayStorage[ACTIVE_BALLOTS].push(_id);
}
function _activeBallotsDecreaseLength() internal {
if (activeBallotsLength() > 0) {
uintArrayStorage[ACTIVE_BALLOTS].length--;
}
}
function _activeBallotsSet(uint256 _index, uint256 _id) internal {
uintArrayStorage[ACTIVE_BALLOTS][_index] = _id;
}
function validatorActiveBallots(address _key) public view returns(uint256) {
return uintStorage[keccak256(abi.encodePacked("validatorActiveBallots", _key))];
}
function _setValidatorActiveBallots(address _key, uint256 _value) internal {
uintStorage[keccak256(abi.encodePacked("validatorActiveBallots", _key))] = _value;
}
function _increaseValidatorLimit(address _key) internal {
_setValidatorActiveBallots(_key, validatorActiveBallots(_key).add(1));
}
function _decreaseValidatorLimit(uint256 _id) internal {
address key = getCreator(_id);
uint256 ballotsCount = validatorActiveBallots(key);
if (ballotsCount > 0) {
_setValidatorActiveBallots(key, ballotsCount - 1);
}
}
function getFinalizeCalled(uint256 _id) public view returns(bool) {
return boolStorage[keccak256(abi.encodePacked("finalizeCalled", _id))];
}
function _setFinalizeCalled(uint256 _id) internal {
boolStorage[keccak256(abi.encodePacked("finalizeCalled", _id))] = true;
}
function getProxyStorage() public view returns(address) {
return addressStorage[PROXY_STORAGE];
}
function getTotalNumberOfValidators() internal view returns(uint256) {
return IConsensus(ProxyStorage(getProxyStorage()).getConsensus()).currentValidatorsLength();
}
function getStake(address _key) internal view returns(uint256) {
return IConsensus(ProxyStorage(getProxyStorage()).getConsensus()).stakeAmount(_key);
}
function _setVoterChoice(uint256 _id, address _key, uint256 _choice) internal {
uintStorage[keccak256(abi.encodePacked("votingState", _id, "voters", _key))] = _choice;
}
function getVoterChoice(uint256 _id, address _key) public view returns(uint256) {
return uintStorage[keccak256(abi.encodePacked("votingState", _id, "voters", _key))];
}
function withinLimit(address _key) internal view returns(bool) {
return validatorActiveBallots(_key) < getBallotLimitPerValidator();
}
function getAccepted(uint256 _id) public view returns(uint256) {
return uintStorage[keccak256(abi.encodePacked("votingState", _id, "accepted"))];
}
function _setAccepted(uint256 _id, uint256 _value) internal {
uintStorage[keccak256(abi.encodePacked("votingState", _id, "accepted"))] = _value;
}
function getRejected(uint256 _id) public view returns(uint256) {
return uintStorage[keccak256(abi.encodePacked("votingState", _id, "rejected"))];
}
function _setRejected(uint256 _id, uint256 _value) internal {
uintStorage[keccak256(abi.encodePacked("votingState", _id, "rejected"))] = _value;
}
function getTotalStake(uint256 _id) public view returns(uint256) {
return uintStorage[keccak256(abi.encodePacked("votingState", _id, "totalStake"))];
}
function _setTotalStake(uint256 _id) internal {
uintStorage[keccak256(abi.encodePacked("votingState", _id, "totalStake"))] = IConsensus(ProxyStorage(getProxyStorage()).getConsensus()).totalStakeAmount();
}
function _checkTurnout(uint256 _id) internal view returns(bool) {
uint256 stake = getTotalStake(_id);
uint256 minTurnout = stake * MINIMUM_TURNOUT_BP / 10000;
uint256 totalVotedFor = getAccepted(_id);
return totalVotedFor > minTurnout;
}
}
// File: contracts/Voting.sol
pragma solidity ^0.4.24;
/**
* @title Contract handling vote to change implementations network contracts
* @author LiorRabin
*/
contract Voting is VotingUtils {
/**
* @dev Function to be called on contract initialization
*/
function initialize() external onlyOwner {
require(!isInitialized());
setInitialized(true);
}
/**
* @dev Function to create a new ballot
* @param _startAfterNumberOfCycles number of cycles after which the ballot should open for voting
* @param _cyclesDuration number of cycles the ballot will remain open for voting
* @param _contractType contract type to change its address (See ProxyStorage.ContractTypes)
* @param _proposedValue proposed address for the contract type
* @param _description ballot text description
*/
function newBallot(uint256 _startAfterNumberOfCycles, uint256 _cyclesDuration, uint256 _contractType, address _proposedValue, string _description) external onlyValidVotingKey(msg.sender) onlyValidDuration(_startAfterNumberOfCycles, _cyclesDuration) returns(uint256) {
require(_proposedValue != address(0));
require(validContractType(_contractType));
uint256 ballotId = _createBallot(_startAfterNumberOfCycles, _cyclesDuration, _description);
_setProposedValue(ballotId, _proposedValue);
_setContractType(ballotId, _contractType);
return ballotId;
}
/**
* @dev Function to get specific ballot info along with voters involvment on it
* @param _id ballot id to get info of
* @param _key voter key to get if voted already
*/
function getBallotInfo(uint256 _id, address _key) external view returns(uint256 startBlock, uint256 endBlock, bool isFinalized, address proposedValue, uint256 contractType, address creator, string description, bool canBeFinalizedNow, bool alreadyVoted, bool belowTurnOut, uint256 accepted, uint256 rejected, uint256 totalStake) {
startBlock = getStartBlock(_id);
endBlock = getEndBlock(_id);
isFinalized = getIsFinalized(_id);
proposedValue = getProposedValue(_id);
contractType = getContractType(_id);
creator = getCreator(_id);
description = getDescription(_id);
canBeFinalizedNow = canBeFinalized(_id);
alreadyVoted = hasAlreadyVoted(_id, _key);
belowTurnOut = getBelowTurnOut(_id);
accepted = getAccepted(_id);
rejected = getRejected(_id);
totalStake = getTotalStake(_id);
return (startBlock, endBlock, isFinalized, proposedValue, contractType, creator, description, canBeFinalizedNow, alreadyVoted, belowTurnOut, accepted, rejected, totalStake);
}
/**
* @dev This function is used to vote on a ballot
* @param _id ballot id to vote on
* @param _choice voting decision on the ballot (see VotingBase.ActionChoices)
*/
function vote(uint256 _id, uint256 _choice) external {
require(!getIsFinalized(_id));
address voter = msg.sender;
require(isActiveBallot(_id));
require(!hasAlreadyVoted(_id, voter));
require(_choice == uint(ActionChoices.Accept) || _choice == uint(ActionChoices.Reject));
_setVoterChoice(_id, voter, _choice);
emit Vote(_id, _choice, voter);
}
/**
* @dev Function to be called by the consensus contract when a cycles ends
* In this function, all active ballots votes will be counted and updated according to the current validators
*/
function onCycleEnd(address[] validators) external onlyConsensus {
uint256 numOfValidators = validators.length;
if (numOfValidators == 0) {
return;
}
uint[] memory ballots = activeBallots();
for (uint256 i = 0; i < ballots.length; i++) {
uint256 ballotId = ballots[i];
if (getStartBlock(ballotId) < block.number && !getFinalizeCalled(ballotId)) {
if (canBeFinalized(ballotId)) {
uint256 accepts = 0;
uint256 rejects = 0;
for (uint256 j = 0; j < numOfValidators; j++) {
uint256 choice = getVoterChoice(ballotId, validators[j]);
if (choice == uint(ActionChoices.Accept)) {
accepts = accepts.add(getStake(validators[j]));
} else if (choice == uint256(ActionChoices.Reject)) {
rejects = rejects.add(getStake(validators[j]));
}
}
_setAccepted(ballotId, accepts);
_setRejected(ballotId, rejects);
_setTotalStake(ballotId);
_finalize(ballotId);
}
}
}
}
}
Contract ABI
[{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"DECIMALS","inputs":[],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"MAX_BALLOT_DURATION_CYCLES","inputs":[],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"MAX_LIMIT_OF_BALLOTS","inputs":[],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"MINIMUM_TURNOUT_BP","inputs":[],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"MIN_BALLOT_DURATION_CYCLES","inputs":[],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":""}],"name":"activeBallots","inputs":[],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"activeBallotsAtIndex","inputs":[{"type":"uint256","name":"_index"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"activeBallotsLength","inputs":[],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":""}],"name":"canBeFinalized","inputs":[{"type":"uint256","name":"_id"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"getAccepted","inputs":[{"type":"uint256","name":"_id"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"startBlock"},{"type":"uint256","name":"endBlock"},{"type":"bool","name":"isFinalized"},{"type":"address","name":"proposedValue"},{"type":"uint256","name":"contractType"},{"type":"address","name":"creator"},{"type":"string","name":"description"},{"type":"bool","name":"canBeFinalizedNow"},{"type":"bool","name":"alreadyVoted"},{"type":"bool","name":"belowTurnOut"},{"type":"uint256","name":"accepted"},{"type":"uint256","name":"rejected"},{"type":"uint256","name":"totalStake"}],"name":"getBallotInfo","inputs":[{"type":"uint256","name":"_id"},{"type":"address","name":"_key"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"getBallotLimitPerValidator","inputs":[],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":""}],"name":"getBelowTurnOut","inputs":[{"type":"uint256","name":"_id"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"getContractType","inputs":[{"type":"uint256","name":"_id"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":""}],"name":"getCreator","inputs":[{"type":"uint256","name":"_id"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":""}],"name":"getDescription","inputs":[{"type":"uint256","name":"_id"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"getEndBlock","inputs":[{"type":"uint256","name":"_id"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":""}],"name":"getFinalizeCalled","inputs":[{"type":"uint256","name":"_id"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"getIndex","inputs":[{"type":"uint256","name":"_id"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":""}],"name":"getIsFinalized","inputs":[{"type":"uint256","name":"_id"}],"constant":true},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":""}],"name":"getMaxBallotDurationCycles","inputs":[],"constant":true},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":""}],"name":"getMinBallotDurationCycles","inputs":[],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"getNextBallotId","inputs":[],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":""}],"name":"getProposedValue","inputs":[{"type":"uint256","name":"_id"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":""}],"name":"getProxyStorage","inputs":[],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"getQuorumState","inputs":[{"type":"uint256","name":"_id"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"getRejected","inputs":[{"type":"uint256","name":"_id"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"getStartBlock","inputs":[{"type":"uint256","name":"_id"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"getTotalStake","inputs":[{"type":"uint256","name":"_id"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"getVoterChoice","inputs":[{"type":"uint256","name":"_id"},{"type":"address","name":"_key"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":""}],"name":"hasAlreadyVoted","inputs":[{"type":"uint256","name":"_id"},{"type":"address","name":"_key"}],"constant":true},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[],"constant":false},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":""}],"name":"isActiveBallot","inputs":[{"type":"uint256","name":"_id"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":""}],"name":"isInitialized","inputs":[],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":""}],"name":"isValidVotingKey","inputs":[{"type":"address","name":"_address"}],"constant":true},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":""}],"name":"newBallot","inputs":[{"type":"uint256","name":"_startAfterNumberOfCycles"},{"type":"uint256","name":"_cyclesDuration"},{"type":"uint256","name":"_contractType"},{"type":"address","name":"_proposedValue"},{"type":"string","name":"_description"}],"constant":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"onCycleEnd","inputs":[{"type":"address[]","name":"validators"}],"constant":false},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":""}],"name":"validContractType","inputs":[{"type":"uint256","name":"_contractType"}],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":""}],"name":"validatorActiveBallots","inputs":[{"type":"address","name":"_key"}],"constant":true},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"vote","inputs":[{"type":"uint256","name":"_id"},{"type":"uint256","name":"_choice"}],"constant":false},{"type":"event","name":"BallotCreated","inputs":[{"type":"uint256","name":"id","indexed":true},{"type":"address","name":"creator","indexed":true}],"anonymous":false},{"type":"event","name":"BallotFinalized","inputs":[{"type":"uint256","name":"id","indexed":true}],"anonymous":false},{"type":"event","name":"Vote","inputs":[{"type":"uint256","name":"id","indexed":true},{"type":"uint256","name":"decision","indexed":false},{"type":"address","name":"voter","indexed":true}],"anonymous":false}]
Contract Creation Code
0x608060405234801561001057600080fd5b506138f2806100206000396000f3006080604052600436106101d45763ffffffff60e060020a60003504166301b2320e81146101d957806308dbb18e146102035780630af58e771461021b5780630eac27f41461023057806322e5fe9d1461025457806323e1a0a81461026c5780632b592f92146102985780632dfba528146102b05780632e0f2625146102c8578063340d3dc2146102dd578063392e53cd146102f25780633ee2f2121461030757806345367f231461031c578063480ca380146103345780634925ec551461034957806360970b6f146103d657806362f4c26b146103ee5780636ccc02341461040657806377da79301461041b5780638129fc1c1461043c57806382c4c96314610453578063897ba3e41461046b5780638be774d3146104805780638c64a20d146104955780638c8ab7ad146105b95780638e7cb6e1146105d1578063b384abef146105e9578063bbac62c814610604578063bdd4ae5514610624578063c12eefd21461063c578063c14bfd2914610675578063d21dc68a14610699578063d48e638a146106fe578063d6edcb3814610732578063df0444771461074a578063ec15a5e614610762578063edaab22314610777578063f3161a4d1461078f578063f49774ee146107a4578063fcff021c146107c5575b600080fd5b3480156101e557600080fd5b506101f16004356107da565b60408051918252519081900360200190f35b34801561020f57600080fd5b506101f16004356108b0565b34801561022757600080fd5b506101f1610942565b34801561023c57600080fd5b506101f1600435600160a060020a0360243516610947565b34801561026057600080fd5b506101f1600435610a39565b34801561027857600080fd5b50610284600435610acb565b604080519115158252519081900360200190f35b3480156102a457600080fd5b50610284600435610ba2565b3480156102bc57600080fd5b50610284600435610bc7565b3480156102d457600080fd5b506101f1610c43565b3480156102e957600080fd5b506101f1610c4f565b3480156102fe57600080fd5b50610284610c55565b34801561031357600080fd5b506101f1610d0e565b34801561032857600080fd5b506101f1600435610dc3565b34801561034057600080fd5b506101f1610e55565b34801561035557600080fd5b50610361600435610e5a565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561039b578181015183820152602001610383565b50505050905090810190601f1680156103c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103e257600080fd5b50610284600435610fd0565b3480156103fa57600080fd5b506101f1600435611062565b34801561041257600080fd5b506101f16110f4565b34801561042757600080fd5b50610284600160a060020a0360043516611156565b34801561044857600080fd5b506104516112e6565b005b34801561045f57600080fd5b506102846004356113c8565b34801561047757600080fd5b506101f1611420565b34801561048c57600080fd5b506101f1611425565b3480156104a157600080fd5b506104b9600435600160a060020a036024351661142a565b604051808e81526020018d81526020018c1515151581526020018b600160a060020a0316600160a060020a031681526020018a815260200189600160a060020a0316600160a060020a0316815260200180602001881515151581526020018715151515815260200186151515158152602001858152602001848152602001838152602001828103825289818151815260200191508051906020019080838360005b8381101561057257818101518382015260200161055a565b50505050905090810190601f16801561059f5780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060405180910390f35b3480156105c557600080fd5b506101f16004356114e0565b3480156105dd57600080fd5b506101f1600435611572565b3480156105f557600080fd5b50610451600435602435611604565b34801561061057600080fd5b5061045160048035602481019101356116ad565b34801561063057600080fd5b506101f16004356118a3565b34801561064857600080fd5b506101f16004803590602480359160443591600160a060020a036064351691608435918201910135611935565b34801561068157600080fd5b50610284600435600160a060020a0360243516611a1a565b3480156106a557600080fd5b506106ae611a47565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156106ea5781810151838201526020016106d2565b505050509050019250505060405180910390f35b34801561070a57600080fd5b50610716600435611b34565b60408051600160a060020a039092168252519081900360200190f35b34801561073e57600080fd5b50610716600435611c11565b34801561075657600080fd5b506101f1600435611ca3565b34801561076e57600080fd5b50610716611d61565b34801561078357600080fd5b50610284600435611e1f565b34801561079b57600080fd5b506101f1611ea3565b3480156107b057600080fd5b506101f1600160a060020a0360043516611ea8565b3480156107d157600080fd5b506101f1611f45565b6000600260008360405160200180806000805160206138a7833981519152815250600b01828152602001807f7374617274426c6f636b00000000000000000000000000000000000000000000815250600a019150506040516020818303038152906040526040518082805190602001908083835b6020831061086d5780518252601f19909201916020918201910161084e565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205493505050505b919050565b6000600260008360405160200180806000805160206138a7833981519152815250600b01828152602001807f71756f72756d5374617465000000000000000000000000000000000000000000815250600b019150506040516020818303038152906040526040518082805190602001908083836020831061086d5780518252601f19909201916020918201910161084e565b600281565b604080516000805160206138a7833981519152602080830191909152602b82018590527f766f746572730000000000000000000000000000000000000000000000000000604b8301526c01000000000000000000000000600160a060020a0385160260518301528251604581840301815260659092019283905281516000936002938593909282918401908083835b602083106109f55780518252601f1990920191602091820191016109d6565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205493505050505b92915050565b6000600260008360405160200180806000805160206138a7833981519152815250600b01828152602001807f61636365707465640000000000000000000000000000000000000000000000008152506008019150506040516020818303038152906040526040518082805190602001908083836020831061086d5780518252601f19909201916020918201910161084e565b6000600660008360405160200180806000805160206138a7833981519152815250600b01828152602001807f697346696e616c697a6564000000000000000000000000000000000000000000815250600b019150506040516020818303038152906040526040518082805190602001908083835b60208310610b5e5780518252601f199092019160209182019101610b3f565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff1695945050505050565b600043610bae836107da565b108015610a335750610bbf826114e0565b431092915050565b6000600660008360405160200180807f66696e616c697a6543616c6c6564000000000000000000000000000000000000815250600e0182815260200191505060405160208183030381529060405260405180828051906020019080838360208310610b5e5780518252601f199092019160209182019101610b3f565b670de0b6b3a764000081565b6107d081565b60006006600060405160200180807f6973496e697469616c697a656400000000000000000000000000000000000000815250600d0190506040516020818303038152906040526040518082805190602001908083835b60208310610cca5780518252601f199092019160209182019101610cab565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff1693505050505b90565b60006002600060405160200180807f6e65787442616c6c6f7449640000000000000000000000000000000000000000815250600c0190506040516020818303038152906040526040518082805190602001908083835b60208310610d835780518252601f199092019160209182019101610d64565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054949350505050565b6000600260008360405160200180806000805160206138a7833981519152815250600b01828152602001807f746f74616c5374616b6500000000000000000000000000000000000000000000815250600a019150506040516020818303038152906040526040518082805190602001908083836020831061086d5780518252601f19909201916020918201910161084e565b600e81565b6060600360008360405160200180806000805160206138a7833981519152815250600b01828152602001807f6465736372697074696f6e000000000000000000000000000000000000000000815250600b019150506040516020818303038152906040526040518082805190602001908083835b60208310610eed5780518252601f199092019160209182019101610ece565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019166000191681526020019081526020016000208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fc45780601f10610f9957610100808354040283529160200191610fc4565b820191906000526020600020905b815481529060010190602001808311610fa757829003601f168201915b50505050509050919050565b6000600660008360405160200180806000805160206138a7833981519152815250600b01828152602001807f62656c6f775475726e4f75740000000000000000000000000000000000000000815250600c0191505060405160208183030381529060405260405180828051906020019080838360208310610b5e5780518252601f199092019160209182019101610b3f565b6000600260008360405160200180806000805160206138a7833981519152815250600b01828152602001807f72656a65637465640000000000000000000000000000000000000000000000008152506008019150506040516020818303038152906040526040518082805190602001908083836020831061086d5780518252601f19909201916020918201910161084e565b6000600860006040516020018080600080516020613887833981519152815250600d01905060405160208183030381529060405260405180828051906020019080838360208310610d835780518252601f199092019160209182019101610d64565b600080808080611164611d61565b600160a060020a031663179e740b6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156111a157600080fd5b505af11580156111b5573d6000803e3d6000fd5b505050506040513d60208110156111cb57600080fd5b505192505b82600160a060020a03166340c9cdeb6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561120e57600080fd5b505af1158015611222573d6000803e3d6000fd5b505050506040513d602081101561123857600080fd5b50518210156112dc5782600160a060020a03166357aeefc5836040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b15801561128a57600080fd5b505af115801561129e573d6000803e3d6000fd5b505050506040513d60208110156112b457600080fd5b50519050600160a060020a0380821690871614156112d157600193505b6001909101906111d0565b5091949350505050565b6004600060405160200180807f6f776e657200000000000000000000000000000000000000000000000000000081525060050190506040516020818303038152906040526040518082805190602001908083835b602083106113595780518252601f19909201916020918201910161133a565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a0316331492506113aa91505057600080fd5b6113b2610c55565b156113bc57600080fd5b6113c66001611f8b565b565b60006113d2610d0e565b82106113e0575060006108ab565b436113ea836107da565b11156113f8575060006108ab565b61140182610acb565b1561140e575060006108ab565b611417826114e0565b43101592915050565b606481565b600e90565b60008060008060008060606000806000806000806114478f6107da565b9c506114528f6114e0565b9b5061145d8f610acb565b9a506114688f611c11565b99506114738f6118a3565b985061147e8f611b34565b97506114898f610e5a565b96506114948f6113c8565b95506114a08f8f611a1a565b94506114ab8f610fd0565b93506114b68f610a39565b92506114c18f611062565b91506114cc8f610dc3565b90509295989b9e9194979a9d509295989b50565b6000600260008360405160200180806000805160206138a7833981519152815250600b01828152602001807f656e64426c6f636b0000000000000000000000000000000000000000000000008152506008019150506040516020818303038152906040526040518082805190602001908083836020831061086d5780518252601f19909201916020918201910161084e565b6000600260008360405160200180806000805160206138a7833981519152815250600b01828152602001807f696e6465780000000000000000000000000000000000000000000000000000008152506005019150506040516020818303038152906040526040518082805190602001908083836020831061086d5780518252601f19909201916020918201910161084e565b600061160f83610acb565b1561161957600080fd5b503361162483610ba2565b151561162f57600080fd5b6116398382611a1a565b1561164357600080fd5b60018214806116525750600282145b151561165d57600080fd5b61166883828461204c565b604080518381529051600160a060020a0383169185917f7c2f48a4bf2e759e77b1e77a8bf1034cdf16e9034dad596d3655bb8b315f85eb9181900360200190a3505050565b600060606000806000806000806116c2611d61565b600160a060020a031663179e740b6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156116ff57600080fd5b505af1158015611713573d6000803e3d6000fd5b505050506040513d602081101561172957600080fd5b5051600160a060020a0316331461173f57600080fd5b88975087151561174e57611897565b611756611a47565b9650600095505b865186101561189757868681518110151561177457fe5b9060200190602002015194504361178a866107da565b10801561179d575061179b85610bc7565b155b1561188c576117ab856113c8565b1561188c576000935060009250600091505b87821015611866576117ea858b8b858181106117d557fe5b90506020020135600160a060020a0316610947565b905060018114156118305761182961181c8b8b8581811061180757fe5b90506020020135600160a060020a031661213d565b859063ffffffff61221516565b935061185b565b600281141561185b5761185861184b8b8b8581811061180757fe5b849063ffffffff61221516565b92505b6001909101906117bd565b6118708585612232565b61187a8584612306565b61188385612397565b61188c85612561565b60019095019461175d565b50505050505050505050565b6000600260008360405160200180806000805160206138a7833981519152815250600b01828152602001807f636f6e7472616374547970650000000000000000000000000000000000000000815250600c019150506040516020818303038152906040526040518082805190602001908083836020831061086d5780518252601f19909201916020918201910161084e565b6000803361194281611156565b151561194d57600080fd5b88886000821161195c57600080fd5b6000811161196957600080fd5b611971611ea3565b81101561197d57600080fd5b611985611425565b81111561199157600080fd5b600160a060020a03881615156119a657600080fd5b6119af89611e1f565b15156119ba57600080fd5b6119f58b8b89898080601f01602080910402602001604051908101604052809392919081815260200183838082843750612645945050505050565b9350611a018489612742565b611a0b848a61283e565b50919998505050505050505050565b6000600160a060020a0382161515611a3457506000610a33565b611a3e8383610947565b15159392505050565b6060600860006040516020018080600080516020613887833981519152815250600d0190506040516020818303038152906040526040518082805190602001908083835b60208310611aaa5780518252601f199092019160209182019101611a8b565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652858101969096525092830160002080548451818702810187019095528085529394909392508401905082828015611b2a57602002820191906000526020600020905b815481526020019060010190808311611b16575b5050505050905090565b6000600460008360405160200180806000805160206138a7833981519152815250600b01828152602001807f63726561746f72000000000000000000000000000000000000000000000000008152506007019150506040516020818303038152906040526040518082805190602001908083835b60208310611bc75780518252601f199092019160209182019101611ba8565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a031695945050505050565b6000600460008360405160200180806000805160206138a7833981519152815250600b01828152602001807f70726f706f73656456616c756500000000000000000000000000000000000000815250600d0191505060405160208183030381529060405260405180828051906020019080838360208310611bc75780518252601f199092019160209182019101611ba8565b6000600860006040516020018080600080516020613887833981519152815250600d0190506040516020818303038152906040526040518082805190602001908083835b60208310611d065780518252601f199092019160209182019101611ce7565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805490935085925082109050611d4f57fe5b90600052602060002001549050919050565b60006004600060405160200180807f70726f787953746f726167650000000000000000000000000000000000000000815250600c0190506040516020818303038152906040526040518082805190602001908083835b60208310611dd65780518252601f199092019160209182019101611db7565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a0316949350505050565b6000611e29611d61565b600160a060020a03166333875fdd836040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b158015611e7157600080fd5b505af1158015611e85573d6000803e3d6000fd5b505050506040513d6020811015611e9b57600080fd5b505192915050565b600290565b6000600260008360405160200180807f76616c696461746f7241637469766542616c6c6f74730000000000000000000081525060160182600160a060020a0316600160a060020a03166c010000000000000000000000000281526014019150506040516020818303038152906040526040518082805190602001908083836020831061086d5780518252601f19909201916020918201910161084e565b6000806000611f526128cf565b9150811515611f645760649250611f86565b611f7560648363ffffffff6129d016565b9050801515611f82575060015b8092505b505090565b806006600060405160200180807f6973496e697469616c697a656400000000000000000000000000000000000000815250600d0190506040516020818303038152906040526040518082805190602001908083835b60208310611fff5780518252601f199092019160209182019101611fe0565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff19169415159490941790935550505050565b604080516000805160206138a7833981519152602080830191909152602b82018690527f766f746572730000000000000000000000000000000000000000000000000000604b8301526c01000000000000000000000000600160a060020a0386160260518301528251604581840301815260659092019283905281518493600293600093909282918401908083835b602083106120fa5780518252601f1990920191602091820191016120db565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002093909355505050505050565b6000612147611d61565b600160a060020a031663179e740b6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561218457600080fd5b505af1158015612198573d6000803e3d6000fd5b505050506040513d60208110156121ae57600080fd5b5051604080517fbf135267000000000000000000000000000000000000000000000000000000008152600160a060020a0385811660048301529151919092169163bf1352679160248083019260209291908290030181600087803b158015611e7157600080fd5b60008282018381101561222757600080fd5b8091505b5092915050565b80600260008460405160200180806000805160206138a7833981519152815250600b01828152602001807f61636365707465640000000000000000000000000000000000000000000000008152506008019150506040516020818303038152906040526040518082805190602001908083835b602083106122c45780518252601f1990920191602091820191016122a5565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020939093555050505050565b80600260008460405160200180806000805160206138a7833981519152815250600b01828152602001807f72656a6563746564000000000000000000000000000000000000000000000000815250600801915050604051602081830303815290604052604051808280519060200190808383602083106122c45780518252601f1990920191602091820191016122a5565b61239f611d61565b600160a060020a031663179e740b6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156123dc57600080fd5b505af11580156123f0573d6000803e3d6000fd5b505050506040513d602081101561240657600080fd5b5051604080517f94409a560000000000000000000000000000000000000000000000000000000081529051600160a060020a03909216916394409a56916004808201926020929091908290030181600087803b15801561246557600080fd5b505af1158015612479573d6000803e3d6000fd5b505050506040513d602081101561248f57600080fd5b5051604080516000805160206138a7833981519152602082810191909152602b82018590527f746f74616c5374616b6500000000000000000000000000000000000000000000604b83015282516035818403018152605590920192839052815160029360009392909182918401908083835b602083106125205780518252601f199092019160209182019101612501565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000209390935550505050565b61256a81610bc7565b151561258257612579816129f3565b61258281612a27565b61258b81612aa3565b156125ec5761259981611062565b6125a282610a39565b11156125d1576125b181612ad4565b156125c7576125c28160025b612b50565b6125cc565b612642565b6125dc565b6125dc8160036125bd565b6125e7816000612be1565b612602565b6125f7816001612be1565b6126028160036125bd565b61260b81612cc1565b612616816001612d16565b60405181907fd470bb0d3dcb39ff5a62757e0a1cdfe60f8200eba22fd0d82383630d457f868690600090a25b50565b6000806000612652610c55565b151561265d57600080fd5b33915061266982612da7565b151561267457600080fd5b61267c610d0e565b905061269761269282600163ffffffff61221516565b612dc1565b6126a18187612e34565b6126ab81866130bd565b6126b6816000612d16565b6126c18160016125bd565b6126cb81836132b5565b6126d58185613346565b6126e6816126e16110f4565b613426565b6126f1816000612be1565b6126fa816134b7565b6127038261356c565b604051600160a060020a0383169082907fe64b3864f6f22f8969f8cb16c039eaf6454ef5e23c09791df010163000a7023590600090a395945050505050565b80600460008460405160200180806000805160206138a7833981519152815250600b01828152602001807f70726f706f73656456616c756500000000000000000000000000000000000000815250600d019150506040516020818303038152906040526040518082805190602001908083835b602083106127d45780518252601f1990920191602091820191016127b5565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0395909516949094179093555050505050565b80600260008460405160200180806000805160206138a7833981519152815250600b01828152602001807f636f6e7472616374547970650000000000000000000000000000000000000000815250600c01915050604051602081830303815290604052604051808280519060200190808383602083106122c45780518252601f1990920191602091820191016122a5565b60006128d9611d61565b600160a060020a031663179e740b6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561291657600080fd5b505af115801561292a573d6000803e3d6000fd5b505050506040513d602081101561294057600080fd5b5051604080517f40c9cdeb0000000000000000000000000000000000000000000000000000000081529051600160a060020a03909216916340c9cdeb916004808201926020929091908290030181600087803b15801561299f57600080fd5b505af11580156129b3573d6000803e3d6000fd5b505050506040513d60208110156129c957600080fd5b5051905090565b6000808083116129df57600080fd5b82848115156129ea57fe5b04949350505050565b6000806129ff83611b34565b9150612a0a82611ea8565b90506000811115612a2257612a22826001830361358a565b505050565b6001600660008360405160200180807f66696e616c697a6543616c6c6564000000000000000000000000000000000000815250600e0182815260200191505060405160208183030381529060405260405180828051906020019080838360208310611fff5780518252601f199092019160209182019101611fe0565b600080600080612ab285610dc3565b92506127106107d08402049150612ac885610a39565b91909111949350505050565b6000612ade611d61565b600160a060020a031663bb0165b1612af5846118a3565b612afe85611c11565b6040518363ffffffff1660e060020a0281526004018083815260200182600160a060020a0316600160a060020a0316815260200192505050602060405180830381600087803b158015611e7157600080fd5b80600260008460405160200180806000805160206138a7833981519152815250600b01828152602001807f71756f72756d5374617465000000000000000000000000000000000000000000815250600b01915050604051602081830303815290604052604051808280519060200190808383602083106122c45780518252601f1990920191602091820191016122a5565b80600660008460405160200180806000805160206138a7833981519152815250600b01828152602001807f62656c6f775475726e4f75740000000000000000000000000000000000000000815250600c019150506040516020818303038152906040526040518082805190602001908083835b60208310612c735780518252601f199092019160209182019101612c54565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff1916941515949094179093555050505050565b6000806000612ccf84611572565b92506001612cdb6110f4565b039150612ce782611ca3565b9050612cf38382613626565b612cfd8184613426565b612d08826000613626565b612d106136e1565b50505050565b80600660008460405160200180806000805160206138a7833981519152815250600b01828152602001807f697346696e616c697a6564000000000000000000000000000000000000000000815250600b0191505060405160208183030381529060405260405180828051906020019080838360208310612c735780518252601f199092019160209182019101612c54565b6000612db1611f45565b612dba83611ea8565b1092915050565b806002600060405160200180807f6e65787442616c6c6f7449640000000000000000000000000000000000000000815250600c019050604051602081830303815290604052604051808280519060200190808383602083106125205780518252601f199092019160209182019101612501565b600080600080612e42611d61565b600160a060020a031663179e740b6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015612e7f57600080fd5b505af1158015612e93573d6000803e3d6000fd5b505050506040513d6020811015612ea957600080fd5b5051604080517fa65249230000000000000000000000000000000000000000000000000000000081529051919550600160a060020a0386169163a6524923916004808201926020929091908290030181600087803b158015612f0a57600080fd5b505af1158015612f1e573d6000803e3d6000fd5b505050506040513d6020811015612f3457600080fd5b5051604080517faf2951810000000000000000000000000000000000000000000000000000000081529051919450600160a060020a0386169163af295181916004808201926020929091908290030181600087803b158015612f9557600080fd5b505af1158015612fa9573d6000803e3d6000fd5b505050506040513d6020811015612fbf57600080fd5b50519150612fe3612fd6868563ffffffff6137a016565b839063ffffffff61221516565b905080600260008860405160200180806000805160206138a7833981519152815250600b01828152602001807f7374617274426c6f636b00000000000000000000000000000000000000000000815250600a019150506040516020818303038152906040526040518082805190602001908083835b602083106130775780518252601f199092019160209182019101613058565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002093909355505050505050505050565b60008060006130ca611d61565b600160a060020a031663179e740b6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561310757600080fd5b505af115801561311b573d6000803e3d6000fd5b505050506040513d602081101561313157600080fd5b5051604080517fa65249230000000000000000000000000000000000000000000000000000000081529051600160a060020a039092169163a6524923916004808201926020929091908290030181600087803b15801561319057600080fd5b505af11580156131a4573d6000803e3d6000fd5b505050506040513d60208110156131ba57600080fd5b505192506131c7856107da565b91506131dc612fd6858563ffffffff6137a016565b905080600260008760405160200180806000805160206138a7833981519152815250600b01828152602001807f656e64426c6f636b0000000000000000000000000000000000000000000000008152506008019150506040516020818303038152906040526040518082805190602001908083835b602083106132705780518252601f199092019160209182019101613251565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020939093555050505050505050565b80600460008460405160200180806000805160206138a7833981519152815250600b01828152602001807f63726561746f7200000000000000000000000000000000000000000000000000815250600701915050604051602081830303815290604052604051808280519060200190808383602083106127d45780518252601f1990920191602091820191016127b5565b80600360008460405160200180806000805160206138a7833981519152815250600b01828152602001807f6465736372697074696f6e000000000000000000000000000000000000000000815250600b019150506040516020818303038152906040526040518082805190602001908083835b602083106133d85780518252601f1990920191602091820191016133b9565b51815160001960209485036101000a01908116901991909116179052604080519490920184900390932086528583019690965250929093016000208451612a229591945092019190506137ce565b80600260008460405160200180806000805160206138a7833981519152815250600b01828152602001807f696e646578000000000000000000000000000000000000000000000000000000815250600501915050604051602081830303815290604052604051808280519060200190808383602083106122c45780518252601f1990920191602091820191016122a5565b600860006040516020018080600080516020613887833981519152815250600d0190506040516020818303038152906040526040518082805190602001908083835b602083106135185780518252601f1990920191602091820191016134f9565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285810196909652509290920160009081208054600181018255908252939020909201929092555050565b6126428161358a600161357e85611ea8565b9063ffffffff61221516565b80600260008460405160200180807f76616c696461746f7241637469766542616c6c6f74730000000000000000000081525060160182600160a060020a0316600160a060020a03166c01000000000000000000000000028152601401915050604051602081830303815290604052604051808280519060200190808383602083106122c45780518252601f1990920191602091820191016122a5565b80600860006040516020018080600080516020613887833981519152815250600d0190506040516020818303038152906040526040518082805190602001908083835b602083106136885780518252601f199092019160209182019101613669565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000208054909350869250821090506136d157fe5b6000918252602090912001555050565b60006136eb6110f4565b11156113c657600860006040516020018080600080516020613887833981519152815250600d0190506040516020818303038152906040526040518082805190602001908083835b602083106137525780518252601f199092019160209182019101613733565b51815160001960209485036101000a8101918216911992909216179091526040805195909301859003909420875286019690965250929093016000208054935061264292909150830161384c565b6000808315156137b3576000915061222b565b508282028284828115156137c357fe5b041461222757600080fd5b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061380f57805160ff191683800117855561383c565b8280016001018555821561383c579182015b8281111561383c578251825591602001919060010190613821565b5061384892915061386c565b5090565b815481835581811115612a2257600083815260209020612a229181019083015b610d0b91905b808211156138485760008155600101613872560061637469766542616c6c6f747300000000000000000000000000000000000000766f74696e675374617465000000000000000000000000000000000000000000a165627a7a723058208d70072ebed43198b496d8e8560f428fa5f8fefd60a01bc2bd679521aeb93a290029
Deployed ByteCode
0x6080604052600436106101d45763ffffffff60e060020a60003504166301b2320e81146101d957806308dbb18e146102035780630af58e771461021b5780630eac27f41461023057806322e5fe9d1461025457806323e1a0a81461026c5780632b592f92146102985780632dfba528146102b05780632e0f2625146102c8578063340d3dc2146102dd578063392e53cd146102f25780633ee2f2121461030757806345367f231461031c578063480ca380146103345780634925ec551461034957806360970b6f146103d657806362f4c26b146103ee5780636ccc02341461040657806377da79301461041b5780638129fc1c1461043c57806382c4c96314610453578063897ba3e41461046b5780638be774d3146104805780638c64a20d146104955780638c8ab7ad146105b95780638e7cb6e1146105d1578063b384abef146105e9578063bbac62c814610604578063bdd4ae5514610624578063c12eefd21461063c578063c14bfd2914610675578063d21dc68a14610699578063d48e638a146106fe578063d6edcb3814610732578063df0444771461074a578063ec15a5e614610762578063edaab22314610777578063f3161a4d1461078f578063f49774ee146107a4578063fcff021c146107c5575b600080fd5b3480156101e557600080fd5b506101f16004356107da565b60408051918252519081900360200190f35b34801561020f57600080fd5b506101f16004356108b0565b34801561022757600080fd5b506101f1610942565b34801561023c57600080fd5b506101f1600435600160a060020a0360243516610947565b34801561026057600080fd5b506101f1600435610a39565b34801561027857600080fd5b50610284600435610acb565b604080519115158252519081900360200190f35b3480156102a457600080fd5b50610284600435610ba2565b3480156102bc57600080fd5b50610284600435610bc7565b3480156102d457600080fd5b506101f1610c43565b3480156102e957600080fd5b506101f1610c4f565b3480156102fe57600080fd5b50610284610c55565b34801561031357600080fd5b506101f1610d0e565b34801561032857600080fd5b506101f1600435610dc3565b34801561034057600080fd5b506101f1610e55565b34801561035557600080fd5b50610361600435610e5a565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561039b578181015183820152602001610383565b50505050905090810190601f1680156103c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103e257600080fd5b50610284600435610fd0565b3480156103fa57600080fd5b506101f1600435611062565b34801561041257600080fd5b506101f16110f4565b34801561042757600080fd5b50610284600160a060020a0360043516611156565b34801561044857600080fd5b506104516112e6565b005b34801561045f57600080fd5b506102846004356113c8565b34801561047757600080fd5b506101f1611420565b34801561048c57600080fd5b506101f1611425565b3480156104a157600080fd5b506104b9600435600160a060020a036024351661142a565b604051808e81526020018d81526020018c1515151581526020018b600160a060020a0316600160a060020a031681526020018a815260200189600160a060020a0316600160a060020a0316815260200180602001881515151581526020018715151515815260200186151515158152602001858152602001848152602001838152602001828103825289818151815260200191508051906020019080838360005b8381101561057257818101518382015260200161055a565b50505050905090810190601f16801561059f5780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060405180910390f35b3480156105c557600080fd5b506101f16004356114e0565b3480156105dd57600080fd5b506101f1600435611572565b3480156105f557600080fd5b50610451600435602435611604565b34801561061057600080fd5b5061045160048035602481019101356116ad565b34801561063057600080fd5b506101f16004356118a3565b34801561064857600080fd5b506101f16004803590602480359160443591600160a060020a036064351691608435918201910135611935565b34801561068157600080fd5b50610284600435600160a060020a0360243516611a1a565b3480156106a557600080fd5b506106ae611a47565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156106ea5781810151838201526020016106d2565b505050509050019250505060405180910390f35b34801561070a57600080fd5b50610716600435611b34565b60408051600160a060020a039092168252519081900360200190f35b34801561073e57600080fd5b50610716600435611c11565b34801561075657600080fd5b506101f1600435611ca3565b34801561076e57600080fd5b50610716611d61565b34801561078357600080fd5b50610284600435611e1f565b34801561079b57600080fd5b506101f1611ea3565b3480156107b057600080fd5b506101f1600160a060020a0360043516611ea8565b3480156107d157600080fd5b506101f1611f45565b6000600260008360405160200180806000805160206138a7833981519152815250600b01828152602001807f7374617274426c6f636b00000000000000000000000000000000000000000000815250600a019150506040516020818303038152906040526040518082805190602001908083835b6020831061086d5780518252601f19909201916020918201910161084e565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205493505050505b919050565b6000600260008360405160200180806000805160206138a7833981519152815250600b01828152602001807f71756f72756d5374617465000000000000000000000000000000000000000000815250600b019150506040516020818303038152906040526040518082805190602001908083836020831061086d5780518252601f19909201916020918201910161084e565b600281565b604080516000805160206138a7833981519152602080830191909152602b82018590527f766f746572730000000000000000000000000000000000000000000000000000604b8301526c01000000000000000000000000600160a060020a0385160260518301528251604581840301815260659092019283905281516000936002938593909282918401908083835b602083106109f55780518252601f1990920191602091820191016109d6565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205493505050505b92915050565b6000600260008360405160200180806000805160206138a7833981519152815250600b01828152602001807f61636365707465640000000000000000000000000000000000000000000000008152506008019150506040516020818303038152906040526040518082805190602001908083836020831061086d5780518252601f19909201916020918201910161084e565b6000600660008360405160200180806000805160206138a7833981519152815250600b01828152602001807f697346696e616c697a6564000000000000000000000000000000000000000000815250600b019150506040516020818303038152906040526040518082805190602001908083835b60208310610b5e5780518252601f199092019160209182019101610b3f565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff1695945050505050565b600043610bae836107da565b108015610a335750610bbf826114e0565b431092915050565b6000600660008360405160200180807f66696e616c697a6543616c6c6564000000000000000000000000000000000000815250600e0182815260200191505060405160208183030381529060405260405180828051906020019080838360208310610b5e5780518252601f199092019160209182019101610b3f565b670de0b6b3a764000081565b6107d081565b60006006600060405160200180807f6973496e697469616c697a656400000000000000000000000000000000000000815250600d0190506040516020818303038152906040526040518082805190602001908083835b60208310610cca5780518252601f199092019160209182019101610cab565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff1693505050505b90565b60006002600060405160200180807f6e65787442616c6c6f7449640000000000000000000000000000000000000000815250600c0190506040516020818303038152906040526040518082805190602001908083835b60208310610d835780518252601f199092019160209182019101610d64565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054949350505050565b6000600260008360405160200180806000805160206138a7833981519152815250600b01828152602001807f746f74616c5374616b6500000000000000000000000000000000000000000000815250600a019150506040516020818303038152906040526040518082805190602001908083836020831061086d5780518252601f19909201916020918201910161084e565b600e81565b6060600360008360405160200180806000805160206138a7833981519152815250600b01828152602001807f6465736372697074696f6e000000000000000000000000000000000000000000815250600b019150506040516020818303038152906040526040518082805190602001908083835b60208310610eed5780518252601f199092019160209182019101610ece565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019166000191681526020019081526020016000208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fc45780601f10610f9957610100808354040283529160200191610fc4565b820191906000526020600020905b815481529060010190602001808311610fa757829003601f168201915b50505050509050919050565b6000600660008360405160200180806000805160206138a7833981519152815250600b01828152602001807f62656c6f775475726e4f75740000000000000000000000000000000000000000815250600c0191505060405160208183030381529060405260405180828051906020019080838360208310610b5e5780518252601f199092019160209182019101610b3f565b6000600260008360405160200180806000805160206138a7833981519152815250600b01828152602001807f72656a65637465640000000000000000000000000000000000000000000000008152506008019150506040516020818303038152906040526040518082805190602001908083836020831061086d5780518252601f19909201916020918201910161084e565b6000600860006040516020018080600080516020613887833981519152815250600d01905060405160208183030381529060405260405180828051906020019080838360208310610d835780518252601f199092019160209182019101610d64565b600080808080611164611d61565b600160a060020a031663179e740b6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156111a157600080fd5b505af11580156111b5573d6000803e3d6000fd5b505050506040513d60208110156111cb57600080fd5b505192505b82600160a060020a03166340c9cdeb6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561120e57600080fd5b505af1158015611222573d6000803e3d6000fd5b505050506040513d602081101561123857600080fd5b50518210156112dc5782600160a060020a03166357aeefc5836040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b15801561128a57600080fd5b505af115801561129e573d6000803e3d6000fd5b505050506040513d60208110156112b457600080fd5b50519050600160a060020a0380821690871614156112d157600193505b6001909101906111d0565b5091949350505050565b6004600060405160200180807f6f776e657200000000000000000000000000000000000000000000000000000081525060050190506040516020818303038152906040526040518082805190602001908083835b602083106113595780518252601f19909201916020918201910161133a565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a0316331492506113aa91505057600080fd5b6113b2610c55565b156113bc57600080fd5b6113c66001611f8b565b565b60006113d2610d0e565b82106113e0575060006108ab565b436113ea836107da565b11156113f8575060006108ab565b61140182610acb565b1561140e575060006108ab565b611417826114e0565b43101592915050565b606481565b600e90565b60008060008060008060606000806000806000806114478f6107da565b9c506114528f6114e0565b9b5061145d8f610acb565b9a506114688f611c11565b99506114738f6118a3565b985061147e8f611b34565b97506114898f610e5a565b96506114948f6113c8565b95506114a08f8f611a1a565b94506114ab8f610fd0565b93506114b68f610a39565b92506114c18f611062565b91506114cc8f610dc3565b90509295989b9e9194979a9d509295989b50565b6000600260008360405160200180806000805160206138a7833981519152815250600b01828152602001807f656e64426c6f636b0000000000000000000000000000000000000000000000008152506008019150506040516020818303038152906040526040518082805190602001908083836020831061086d5780518252601f19909201916020918201910161084e565b6000600260008360405160200180806000805160206138a7833981519152815250600b01828152602001807f696e6465780000000000000000000000000000000000000000000000000000008152506005019150506040516020818303038152906040526040518082805190602001908083836020831061086d5780518252601f19909201916020918201910161084e565b600061160f83610acb565b1561161957600080fd5b503361162483610ba2565b151561162f57600080fd5b6116398382611a1a565b1561164357600080fd5b60018214806116525750600282145b151561165d57600080fd5b61166883828461204c565b604080518381529051600160a060020a0383169185917f7c2f48a4bf2e759e77b1e77a8bf1034cdf16e9034dad596d3655bb8b315f85eb9181900360200190a3505050565b600060606000806000806000806116c2611d61565b600160a060020a031663179e740b6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156116ff57600080fd5b505af1158015611713573d6000803e3d6000fd5b505050506040513d602081101561172957600080fd5b5051600160a060020a0316331461173f57600080fd5b88975087151561174e57611897565b611756611a47565b9650600095505b865186101561189757868681518110151561177457fe5b9060200190602002015194504361178a866107da565b10801561179d575061179b85610bc7565b155b1561188c576117ab856113c8565b1561188c576000935060009250600091505b87821015611866576117ea858b8b858181106117d557fe5b90506020020135600160a060020a0316610947565b905060018114156118305761182961181c8b8b8581811061180757fe5b90506020020135600160a060020a031661213d565b859063ffffffff61221516565b935061185b565b600281141561185b5761185861184b8b8b8581811061180757fe5b849063ffffffff61221516565b92505b6001909101906117bd565b6118708585612232565b61187a8584612306565b61188385612397565b61188c85612561565b60019095019461175d565b50505050505050505050565b6000600260008360405160200180806000805160206138a7833981519152815250600b01828152602001807f636f6e7472616374547970650000000000000000000000000000000000000000815250600c019150506040516020818303038152906040526040518082805190602001908083836020831061086d5780518252601f19909201916020918201910161084e565b6000803361194281611156565b151561194d57600080fd5b88886000821161195c57600080fd5b6000811161196957600080fd5b611971611ea3565b81101561197d57600080fd5b611985611425565b81111561199157600080fd5b600160a060020a03881615156119a657600080fd5b6119af89611e1f565b15156119ba57600080fd5b6119f58b8b89898080601f01602080910402602001604051908101604052809392919081815260200183838082843750612645945050505050565b9350611a018489612742565b611a0b848a61283e565b50919998505050505050505050565b6000600160a060020a0382161515611a3457506000610a33565b611a3e8383610947565b15159392505050565b6060600860006040516020018080600080516020613887833981519152815250600d0190506040516020818303038152906040526040518082805190602001908083835b60208310611aaa5780518252601f199092019160209182019101611a8b565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652858101969096525092830160002080548451818702810187019095528085529394909392508401905082828015611b2a57602002820191906000526020600020905b815481526020019060010190808311611b16575b5050505050905090565b6000600460008360405160200180806000805160206138a7833981519152815250600b01828152602001807f63726561746f72000000000000000000000000000000000000000000000000008152506007019150506040516020818303038152906040526040518082805190602001908083835b60208310611bc75780518252601f199092019160209182019101611ba8565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a031695945050505050565b6000600460008360405160200180806000805160206138a7833981519152815250600b01828152602001807f70726f706f73656456616c756500000000000000000000000000000000000000815250600d0191505060405160208183030381529060405260405180828051906020019080838360208310611bc75780518252601f199092019160209182019101611ba8565b6000600860006040516020018080600080516020613887833981519152815250600d0190506040516020818303038152906040526040518082805190602001908083835b60208310611d065780518252601f199092019160209182019101611ce7565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805490935085925082109050611d4f57fe5b90600052602060002001549050919050565b60006004600060405160200180807f70726f787953746f726167650000000000000000000000000000000000000000815250600c0190506040516020818303038152906040526040518082805190602001908083835b60208310611dd65780518252601f199092019160209182019101611db7565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a0316949350505050565b6000611e29611d61565b600160a060020a03166333875fdd836040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b158015611e7157600080fd5b505af1158015611e85573d6000803e3d6000fd5b505050506040513d6020811015611e9b57600080fd5b505192915050565b600290565b6000600260008360405160200180807f76616c696461746f7241637469766542616c6c6f74730000000000000000000081525060160182600160a060020a0316600160a060020a03166c010000000000000000000000000281526014019150506040516020818303038152906040526040518082805190602001908083836020831061086d5780518252601f19909201916020918201910161084e565b6000806000611f526128cf565b9150811515611f645760649250611f86565b611f7560648363ffffffff6129d016565b9050801515611f82575060015b8092505b505090565b806006600060405160200180807f6973496e697469616c697a656400000000000000000000000000000000000000815250600d0190506040516020818303038152906040526040518082805190602001908083835b60208310611fff5780518252601f199092019160209182019101611fe0565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff19169415159490941790935550505050565b604080516000805160206138a7833981519152602080830191909152602b82018690527f766f746572730000000000000000000000000000000000000000000000000000604b8301526c01000000000000000000000000600160a060020a0386160260518301528251604581840301815260659092019283905281518493600293600093909282918401908083835b602083106120fa5780518252601f1990920191602091820191016120db565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002093909355505050505050565b6000612147611d61565b600160a060020a031663179e740b6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561218457600080fd5b505af1158015612198573d6000803e3d6000fd5b505050506040513d60208110156121ae57600080fd5b5051604080517fbf135267000000000000000000000000000000000000000000000000000000008152600160a060020a0385811660048301529151919092169163bf1352679160248083019260209291908290030181600087803b158015611e7157600080fd5b60008282018381101561222757600080fd5b8091505b5092915050565b80600260008460405160200180806000805160206138a7833981519152815250600b01828152602001807f61636365707465640000000000000000000000000000000000000000000000008152506008019150506040516020818303038152906040526040518082805190602001908083835b602083106122c45780518252601f1990920191602091820191016122a5565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020939093555050505050565b80600260008460405160200180806000805160206138a7833981519152815250600b01828152602001807f72656a6563746564000000000000000000000000000000000000000000000000815250600801915050604051602081830303815290604052604051808280519060200190808383602083106122c45780518252601f1990920191602091820191016122a5565b61239f611d61565b600160a060020a031663179e740b6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156123dc57600080fd5b505af11580156123f0573d6000803e3d6000fd5b505050506040513d602081101561240657600080fd5b5051604080517f94409a560000000000000000000000000000000000000000000000000000000081529051600160a060020a03909216916394409a56916004808201926020929091908290030181600087803b15801561246557600080fd5b505af1158015612479573d6000803e3d6000fd5b505050506040513d602081101561248f57600080fd5b5051604080516000805160206138a7833981519152602082810191909152602b82018590527f746f74616c5374616b6500000000000000000000000000000000000000000000604b83015282516035818403018152605590920192839052815160029360009392909182918401908083835b602083106125205780518252601f199092019160209182019101612501565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000209390935550505050565b61256a81610bc7565b151561258257612579816129f3565b61258281612a27565b61258b81612aa3565b156125ec5761259981611062565b6125a282610a39565b11156125d1576125b181612ad4565b156125c7576125c28160025b612b50565b6125cc565b612642565b6125dc565b6125dc8160036125bd565b6125e7816000612be1565b612602565b6125f7816001612be1565b6126028160036125bd565b61260b81612cc1565b612616816001612d16565b60405181907fd470bb0d3dcb39ff5a62757e0a1cdfe60f8200eba22fd0d82383630d457f868690600090a25b50565b6000806000612652610c55565b151561265d57600080fd5b33915061266982612da7565b151561267457600080fd5b61267c610d0e565b905061269761269282600163ffffffff61221516565b612dc1565b6126a18187612e34565b6126ab81866130bd565b6126b6816000612d16565b6126c18160016125bd565b6126cb81836132b5565b6126d58185613346565b6126e6816126e16110f4565b613426565b6126f1816000612be1565b6126fa816134b7565b6127038261356c565b604051600160a060020a0383169082907fe64b3864f6f22f8969f8cb16c039eaf6454ef5e23c09791df010163000a7023590600090a395945050505050565b80600460008460405160200180806000805160206138a7833981519152815250600b01828152602001807f70726f706f73656456616c756500000000000000000000000000000000000000815250600d019150506040516020818303038152906040526040518082805190602001908083835b602083106127d45780518252601f1990920191602091820191016127b5565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0395909516949094179093555050505050565b80600260008460405160200180806000805160206138a7833981519152815250600b01828152602001807f636f6e7472616374547970650000000000000000000000000000000000000000815250600c01915050604051602081830303815290604052604051808280519060200190808383602083106122c45780518252601f1990920191602091820191016122a5565b60006128d9611d61565b600160a060020a031663179e740b6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561291657600080fd5b505af115801561292a573d6000803e3d6000fd5b505050506040513d602081101561294057600080fd5b5051604080517f40c9cdeb0000000000000000000000000000000000000000000000000000000081529051600160a060020a03909216916340c9cdeb916004808201926020929091908290030181600087803b15801561299f57600080fd5b505af11580156129b3573d6000803e3d6000fd5b505050506040513d60208110156129c957600080fd5b5051905090565b6000808083116129df57600080fd5b82848115156129ea57fe5b04949350505050565b6000806129ff83611b34565b9150612a0a82611ea8565b90506000811115612a2257612a22826001830361358a565b505050565b6001600660008360405160200180807f66696e616c697a6543616c6c6564000000000000000000000000000000000000815250600e0182815260200191505060405160208183030381529060405260405180828051906020019080838360208310611fff5780518252601f199092019160209182019101611fe0565b600080600080612ab285610dc3565b92506127106107d08402049150612ac885610a39565b91909111949350505050565b6000612ade611d61565b600160a060020a031663bb0165b1612af5846118a3565b612afe85611c11565b6040518363ffffffff1660e060020a0281526004018083815260200182600160a060020a0316600160a060020a0316815260200192505050602060405180830381600087803b158015611e7157600080fd5b80600260008460405160200180806000805160206138a7833981519152815250600b01828152602001807f71756f72756d5374617465000000000000000000000000000000000000000000815250600b01915050604051602081830303815290604052604051808280519060200190808383602083106122c45780518252601f1990920191602091820191016122a5565b80600660008460405160200180806000805160206138a7833981519152815250600b01828152602001807f62656c6f775475726e4f75740000000000000000000000000000000000000000815250600c019150506040516020818303038152906040526040518082805190602001908083835b60208310612c735780518252601f199092019160209182019101612c54565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff1916941515949094179093555050505050565b6000806000612ccf84611572565b92506001612cdb6110f4565b039150612ce782611ca3565b9050612cf38382613626565b612cfd8184613426565b612d08826000613626565b612d106136e1565b50505050565b80600660008460405160200180806000805160206138a7833981519152815250600b01828152602001807f697346696e616c697a6564000000000000000000000000000000000000000000815250600b0191505060405160208183030381529060405260405180828051906020019080838360208310612c735780518252601f199092019160209182019101612c54565b6000612db1611f45565b612dba83611ea8565b1092915050565b806002600060405160200180807f6e65787442616c6c6f7449640000000000000000000000000000000000000000815250600c019050604051602081830303815290604052604051808280519060200190808383602083106125205780518252601f199092019160209182019101612501565b600080600080612e42611d61565b600160a060020a031663179e740b6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015612e7f57600080fd5b505af1158015612e93573d6000803e3d6000fd5b505050506040513d6020811015612ea957600080fd5b5051604080517fa65249230000000000000000000000000000000000000000000000000000000081529051919550600160a060020a0386169163a6524923916004808201926020929091908290030181600087803b158015612f0a57600080fd5b505af1158015612f1e573d6000803e3d6000fd5b505050506040513d6020811015612f3457600080fd5b5051604080517faf2951810000000000000000000000000000000000000000000000000000000081529051919450600160a060020a0386169163af295181916004808201926020929091908290030181600087803b158015612f9557600080fd5b505af1158015612fa9573d6000803e3d6000fd5b505050506040513d6020811015612fbf57600080fd5b50519150612fe3612fd6868563ffffffff6137a016565b839063ffffffff61221516565b905080600260008860405160200180806000805160206138a7833981519152815250600b01828152602001807f7374617274426c6f636b00000000000000000000000000000000000000000000815250600a019150506040516020818303038152906040526040518082805190602001908083835b602083106130775780518252601f199092019160209182019101613058565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002093909355505050505050505050565b60008060006130ca611d61565b600160a060020a031663179e740b6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561310757600080fd5b505af115801561311b573d6000803e3d6000fd5b505050506040513d602081101561313157600080fd5b5051604080517fa65249230000000000000000000000000000000000000000000000000000000081529051600160a060020a039092169163a6524923916004808201926020929091908290030181600087803b15801561319057600080fd5b505af11580156131a4573d6000803e3d6000fd5b505050506040513d60208110156131ba57600080fd5b505192506131c7856107da565b91506131dc612fd6858563ffffffff6137a016565b905080600260008760405160200180806000805160206138a7833981519152815250600b01828152602001807f656e64426c6f636b0000000000000000000000000000000000000000000000008152506008019150506040516020818303038152906040526040518082805190602001908083835b602083106132705780518252601f199092019160209182019101613251565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020939093555050505050505050565b80600460008460405160200180806000805160206138a7833981519152815250600b01828152602001807f63726561746f7200000000000000000000000000000000000000000000000000815250600701915050604051602081830303815290604052604051808280519060200190808383602083106127d45780518252601f1990920191602091820191016127b5565b80600360008460405160200180806000805160206138a7833981519152815250600b01828152602001807f6465736372697074696f6e000000000000000000000000000000000000000000815250600b019150506040516020818303038152906040526040518082805190602001908083835b602083106133d85780518252601f1990920191602091820191016133b9565b51815160001960209485036101000a01908116901991909116179052604080519490920184900390932086528583019690965250929093016000208451612a229591945092019190506137ce565b80600260008460405160200180806000805160206138a7833981519152815250600b01828152602001807f696e646578000000000000000000000000000000000000000000000000000000815250600501915050604051602081830303815290604052604051808280519060200190808383602083106122c45780518252601f1990920191602091820191016122a5565b600860006040516020018080600080516020613887833981519152815250600d0190506040516020818303038152906040526040518082805190602001908083835b602083106135185780518252601f1990920191602091820191016134f9565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285810196909652509290920160009081208054600181018255908252939020909201929092555050565b6126428161358a600161357e85611ea8565b9063ffffffff61221516565b80600260008460405160200180807f76616c696461746f7241637469766542616c6c6f74730000000000000000000081525060160182600160a060020a0316600160a060020a03166c01000000000000000000000000028152601401915050604051602081830303815290604052604051808280519060200190808383602083106122c45780518252601f1990920191602091820191016122a5565b80600860006040516020018080600080516020613887833981519152815250600d0190506040516020818303038152906040526040518082805190602001908083835b602083106136885780518252601f199092019160209182019101613669565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000208054909350869250821090506136d157fe5b6000918252602090912001555050565b60006136eb6110f4565b11156113c657600860006040516020018080600080516020613887833981519152815250600d0190506040516020818303038152906040526040518082805190602001908083835b602083106137525780518252601f199092019160209182019101613733565b51815160001960209485036101000a8101918216911992909216179091526040805195909301859003909420875286019690965250929093016000208054935061264292909150830161384c565b6000808315156137b3576000915061222b565b508282028284828115156137c357fe5b041461222757600080fd5b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061380f57805160ff191683800117855561383c565b8280016001018555821561383c579182015b8281111561383c578251825591602001919060010190613821565b5061384892915061386c565b5090565b815481835581811115612a2257600083815260209020612a229181019083015b610d0b91905b808211156138485760008155600101613872560061637469766542616c6c6f747300000000000000000000000000000000000000766f74696e675374617465000000000000000000000000000000000000000000a165627a7a723058208d70072ebed43198b496d8e8560f428fa5f8fefd60a01bc2bd679521aeb93a290029