Contract Address Details

0x9Da06E1520B748E3e6deB9EdDED36f27b2B01466

Contract Name
Mystic
Creator
0x179abb–e338e5 at 0x4d1d5a–eee8f9
Balance
0 Ether
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
30989774
Contract name:
Mystic




Optimization enabled
true
Compiler version
v0.5.17+commit.d19bba13




Optimization runs
200
EVM Version
default




Verified at
2020-08-28 21:24:05.031743Z

Contract source code

pragma solidity 0.5.17;
interface IERC20 { // brief interface for erc20 token tx
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
}
interface IWETH { // brief interface for canonical ether token wrapper
function deposit() payable external;
function transfer(address dst, uint wad) external returns (bool);
}
library Address { // helper for address type - see openzeppelin-contracts/blob/master/contracts/utils/Address.sol
function isContract(address account) internal view returns (bool) {
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
// for accounts without code, i.e. `keccak256('')`
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
}
library SafeERC20 { // wrapper around erc20 token tx for non-standard contract - see openzeppelin-contracts/blob/master/contracts/token/ERC20/SafeERC20.sol
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
require(address(token).isContract(), "SafeERC20: call to non-contract");
(bool success, bytes memory returnData) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returnData.length > 0) { // return data is optional
require(abi.decode(returnData, (bool)), "SafeERC20: erc20 operation did not succeed");
}
}
}
library SafeMath { // arithmetic wrapper for unit under/overflow check
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0);
uint256 c = a / b;
return c;
}
}
contract ReentrancyGuard { // call wrapper for reentrancy check
bool private _notEntered;
function _initReentrancyGuard () internal {
_notEntered = true;
}
modifier nonReentrant() {
require(_notEntered, "ReentrancyGuard: reentrant call");
_notEntered = false;
_;
_notEntered = true;
}
}
contract Mystic is ReentrancyGuard {
using SafeERC20 for IERC20;
using SafeMath for uint256;
/***************
GLOBAL CONSTANTS
***************/
address public depositToken; // deposit token contract reference - default = wETH
address public stakeToken; // stake token contract reference for guild voting shares
address public constant wETH = 0x5B160edBa6119828c5B065804e86111921323f9c; // canonical ether token wrapper contract reference for proposals (IDChain)
uint256 public proposalDeposit; // default = 10 deposit token
uint256 public processingReward; // default = 0.1 - amount of deposit token to give to whoever processes a proposal
uint256 public periodDuration; // default = 17280 = 4.8 hours in seconds (5 periods per day)
uint256 public votingPeriodLength; // default = 35 periods (7 days)
uint256 public gracePeriodLength; // default = 35 periods (7 days)
uint256 public dilutionBound; // default = 3 - maximum multiplier a YES voter will be obligated to pay in case of mass ragequit
uint256 public summoningTime; // needed to determine the current period
bool private initialized; // tracks deployment status
// HARD-CODED LIMITS
// These numbers are quite arbitrary; they are small enough to avoid overflows when doing calculations
// with periods or shares, yet big enough to not limit reasonable use cases.
uint256 constant MAX_GUILD_BOUND = 10**36; // maximum bound for guild accounting
uint256 constant MAX_TOKEN_WHITELIST_COUNT = 400; // maximum number of whitelisted tokens
uint256 constant MAX_TOKEN_GUILDBANK_COUNT = 200; // maximum number of tokens with non-zero balance in guildbank
// BANK TOKEN DETAILS
string public constant name = "MYSTIC DAO";
string public constant symbol = "MXDAO";
uint8 public constant decimals = 18;
// **************
// EVENT TRACKING
// **************
event SubmitProposal(address indexed applicant, uint256 sharesRequested, uint256 lootRequested, uint256 tributeOffered, address tributeToken, uint256 paymentRequested, address paymentToken, bytes32 details, uint8[7] flags, bytes data, uint256 proposalId, address indexed delegateKey, address indexed memberAddress);
event CancelProposal(uint256 indexed proposalId, address applicantAddress);
event SponsorProposal(address indexed delegateKey, address indexed memberAddress, uint256 proposalId, uint256 proposalIndex, uint256 startingPeriod);
event SubmitVote(uint256 proposalId, uint256 indexed proposalIndex, address indexed delegateKey, address indexed memberAddress, uint8 uintVote);
event ProcessProposal(uint256 indexed proposalIndex, uint256 indexed proposalId, bool didPass);
event ProcessActionProposal(uint256 indexed proposalIndex, uint256 indexed proposalId, bool didPass);
event ProcessWhitelistProposal(uint256 indexed proposalIndex, uint256 indexed proposalId, bool didPass);
event ProcessGuildKickProposal(uint256 indexed proposalIndex, uint256 indexed proposalId, bool didPass);
event UpdateDelegateKey(address indexed memberAddress, address newDelegateKey);
event Approval(address indexed owner, address indexed spender, uint256 amount); // guild token (loot) allowance tracking
event Transfer(address indexed from, address indexed to, uint256 amount); // guild token mint, burn & (loot) transfer tracking
event Ragequit(address indexed memberAddress, uint256 sharesToBurn, uint256 lootToBurn);
event TokensCollected(address indexed token, uint256 amountToCollect);
event Withdraw(address indexed memberAddress, address token, uint256 amount);
// *******************
// INTERNAL ACCOUNTING
// *******************
address public constant GUILD = address(0xdead);
address public constant ESCROW = address(0xdeaf);
address public constant TOTAL = address(0xdeed);
uint256 public proposalCount; // total proposals submitted
uint256 public totalShares; // total shares across all members
uint256 public totalLoot; // total loot across all members
uint256 public totalGuildBankTokens; // total tokens with non-zero balance in guild bank
mapping(uint256 => bytes) public actions; // proposalId => action data
mapping(address => uint256) private balances; // guild token balances
mapping(address => mapping(address => uint256)) private allowances; // guild token (loot) allowances
mapping(address => mapping(address => uint256)) private userTokenBalances; // userTokenBalances[userAddress][tokenAddress]
enum Vote {
Null, // default value, counted as abstention
Yes,
No
}
struct Member {
address delegateKey; // the key responsible for submitting proposals & voting - defaults to member address unless updated
uint8 exists; // always true (1) once a member has been created
uint256 shares; // the # of voting shares assigned to this member
uint256 loot; // the loot amount available to this member (combined with shares on ragekick) - transferable by guild token
uint256 highestIndexYesVote; // highest proposal index # on which the member voted YES
uint256 jailed; // set to proposalIndex of a passing guild kick proposal for this member, prevents voting on & sponsoring proposals
}
struct Proposal {
address applicant; // the applicant who wishes to become a member - this key will be used for withdrawals (doubles as target for alt. proposals)
address proposer; // the account that submitted the proposal (can be non-member)
address sponsor; // the member that sponsored the proposal (moving it into the queue)
address tributeToken; // tribute token contract reference
address paymentToken; // payment token contract reference
uint8[7] flags; // [sponsored, processed, didPass, cancelled, whitelist, guildkick, action]
uint256 sharesRequested; // the # of shares the applicant is requesting
uint256 lootRequested; // the amount of loot the applicant is requesting
uint256 paymentRequested; // amount of tokens requested as payment
uint256 tributeOffered; // amount of tokens offered as tribute
uint256 startingPeriod; // the period in which voting can start for this proposal
uint256 yesVotes; // the total number of YES votes for this proposal
uint256 noVotes; // the total number of NO votes for this proposal
uint256 maxTotalSharesAndLootAtYesVote; // the maximum # of total shares encountered at a yes vote on this proposal
bytes32 details; // proposal details to add context for members
mapping(address => Vote) votesByMember; // the votes on this proposal by each member
}
address[] public approvedTokens;
mapping(address => bool) public tokenWhitelist;
uint256[] public proposalQueue;
mapping(uint256 => Proposal) public proposals;
mapping(address => bool) public proposedToWhitelist;
mapping(address => bool) public proposedToKick;
mapping(address => Member) public members;
mapping(address => address) public memberAddressByDelegateKey;
modifier onlyDelegate {
require(members[memberAddressByDelegateKey[msg.sender]].shares > 0, "!delegate");
_;
}
function init(
address _depositToken,
address _stakeToken,
address[] calldata _summoner,
uint256[] calldata _summonerShares,
uint256 _summonerDeposit,
uint256 _proposalDeposit,
uint256 _processingReward,
uint256 _periodDuration,
uint256 _votingPeriodLength,
uint256 _gracePeriodLength,
uint256 _dilutionBound
) external {
require(!initialized, "initialized");
require(_depositToken != _stakeToken, "depositToken == stakeToken");
require(_summoner.length == _summonerShares.length, "summoner != summonerShares");
require(_proposalDeposit >= _processingReward, "_processingReward > _proposalDeposit");
for (uint256 i = 0; i < _summoner.length; i++) {
registerMember(_summoner[i], _summonerShares[i]);
mintGuildToken(_summoner[i], _summonerShares[i]);
totalShares = totalShares.add(_summonerShares[i]);
}
require(totalShares <= MAX_GUILD_BOUND, "guild maxed");
tokenWhitelist[_depositToken] = true;
approvedTokens.push(_depositToken);
if (_summonerDeposit > 0) {
totalGuildBankTokens += 1;
unsafeAddToBalance(GUILD, _depositToken, _summonerDeposit);
}
depositToken = _depositToken;
stakeToken = _stakeToken;
proposalDeposit = _proposalDeposit;
processingReward = _processingReward;
periodDuration = _periodDuration;
votingPeriodLength = _votingPeriodLength;
gracePeriodLength = _gracePeriodLength;
dilutionBound = _dilutionBound;
summoningTime = now;
initialized = true;
_initReentrancyGuard();
}
/*****************
PROPOSAL FUNCTIONS
*****************/
function submitProposal(
address applicant,
uint256 sharesRequested,
uint256 lootRequested,
uint256 tributeOffered,
address tributeToken,
uint256 paymentRequested,
address paymentToken,
bytes32 details
) payable external nonReentrant returns (uint256 proposalId) {
require(sharesRequested.add(lootRequested) <= MAX_GUILD_BOUND, "guild maxed");
require(tokenWhitelist[tributeToken], "tributeToken != whitelist");
require(tokenWhitelist[paymentToken], "paymentToken != whitelist");
require(applicant != GUILD && applicant != ESCROW && applicant != TOTAL, "applicant unreservable");
require(members[applicant].jailed == 0, "applicant jailed");
if (tributeOffered > 0 && userTokenBalances[GUILD][tributeToken] == 0) {
require(totalGuildBankTokens < MAX_TOKEN_GUILDBANK_COUNT, "guildbank maxed");
}
// collect tribute from proposer & store it in the Mystic until the proposal is processed - if ether, wrap into wETH
if (tributeToken == wETH && msg.value > 0) {
require(msg.value == tributeOffered, "!ETH");
IWETH(wETH).deposit();
(bool success, ) = wETH.call.value(msg.value)("");
require(success, "!transfer");
IWETH(wETH).transfer(address(this), msg.value);
} else {
IERC20(tributeToken).safeTransferFrom(msg.sender, address(this), tributeOffered);
}
unsafeAddToBalance(ESCROW, tributeToken, tributeOffered);
uint8[7] memory flags; // [sponsored, processed, didPass, cancelled, whitelist, guildkick, action]
_submitProposal(applicant, sharesRequested, lootRequested, tributeOffered, tributeToken, paymentRequested, paymentToken, details, flags, "");
return proposalCount - 1; // return proposalId - contracts calling submit might want it
}
function submitActionProposal( // stages arbitrary function calls for member vote - based on Raid Guild 'Minion'
address actionTo,
address actionToken,
uint256 actionTokenAmount,
uint256 actionValue,
bytes32 details,
bytes calldata data
) external returns (uint256 proposalId) {
uint8[7] memory flags; // [sponsored, processed, didPass, cancelled, whitelist, guildkick, action]
flags[6] = 1; // guild action
_submitProposal(actionTo, 0, 0, actionValue, address(0), actionTokenAmount, actionToken, details, flags, data);
return proposalCount - 1;
}
function submitWhitelistProposal(address tokenToWhitelist, bytes32 details) external returns (uint256 proposalId) {
require(tokenToWhitelist != address(0), "!token");
require(tokenToWhitelist != stakeToken, "tokenToWhitelist == stakeToken");
require(!tokenWhitelist[tokenToWhitelist], "whitelisted");
require(approvedTokens.length < MAX_TOKEN_WHITELIST_COUNT, "whitelist maxed");
uint8[7] memory flags; // [sponsored, processed, didPass, cancelled, whitelist, guildkick, action]
flags[4] = 1; // whitelist
_submitProposal(address(0), 0, 0, 0, tokenToWhitelist, 0, address(0), details, flags, "");
return proposalCount - 1;
}
function submitGuildKickProposal(address memberToKick, bytes32 details) external returns (uint256 proposalId) {
Member memory member = members[memberToKick];
require(member.shares > 0 || member.loot > 0, "!share||loot");
require(members[memberToKick].jailed == 0, "jailed");
uint8[7] memory flags; // [sponsored, processed, didPass, cancelled, whitelist, guildkick, action]
flags[5] = 1; // guild kick
_submitProposal(memberToKick, 0, 0, 0, address(0), 0, address(0), details, flags, "");
return proposalCount - 1;
}
function _submitProposal(
address applicant,
uint256 sharesRequested,
uint256 lootRequested,
uint256 tributeOffered,
address tributeToken,
uint256 paymentRequested,
address paymentToken,
bytes32 details,
uint8[7] memory flags,
bytes memory data
) internal {
Proposal memory proposal = Proposal({
applicant : applicant,
proposer : msg.sender,
sponsor : address(0),
tributeToken : tributeToken,
paymentToken : paymentToken,
flags : flags,
sharesRequested : sharesRequested,
lootRequested : lootRequested,
paymentRequested : paymentRequested,
tributeOffered : tributeOffered,
startingPeriod : 0,
yesVotes : 0,
noVotes : 0,
maxTotalSharesAndLootAtYesVote : 0,
details : details
});
if (proposal.flags[6] == 1) {
actions[proposalCount] = data;
}
proposals[proposalCount] = proposal;
address memberAddress = memberAddressByDelegateKey[msg.sender];
// NOTE: argument order matters, avoid stack too deep
emit SubmitProposal(applicant, sharesRequested, lootRequested, tributeOffered, tributeToken, paymentRequested, paymentToken, details, flags, data, proposalCount, msg.sender, memberAddress);
proposalCount += 1;
}
function sponsorProposal(uint256 proposalId) external nonReentrant onlyDelegate {
// collect proposal deposit from sponsor & store it in the Mystic until the proposal is processed
IERC20(depositToken).safeTransferFrom(msg.sender, address(this), proposalDeposit);
unsafeAddToBalance(ESCROW, depositToken, proposalDeposit);
Proposal storage proposal = proposals[proposalId];
require(proposal.proposer != address(0), "!proposed");
require(proposal.flags[0] == 0, "sponsored");
require(proposal.flags[3] == 0, "cancelled");
require(members[proposal.applicant].jailed == 0, "applicant jailed");
if (proposal.tributeOffered > 0 && userTokenBalances[GUILD][proposal.tributeToken] == 0) {
require(totalGuildBankTokens < MAX_TOKEN_GUILDBANK_COUNT, "guildbank maxed");
}
// whitelist proposal
if (proposal.flags[4] == 1) {
require(!tokenWhitelist[address(proposal.tributeToken)], "whitelisted");
require(!proposedToWhitelist[address(proposal.tributeToken)], "whitelist proposed");
require(approvedTokens.length < MAX_TOKEN_WHITELIST_COUNT, "whitelist maxed");
proposedToWhitelist[address(proposal.tributeToken)] = true;
// guild kick proposal
} else if (proposal.flags[5] == 1) {
require(!proposedToKick[proposal.applicant], "kick proposed");
proposedToKick[proposal.applicant] = true;
}
// compute startingPeriod for proposal
uint256 startingPeriod = max(
getCurrentPeriod(),
proposalQueue.length == 0 ? 0 : proposals[proposalQueue[proposalQueue.length - 1]].startingPeriod
) + 1;
proposal.startingPeriod = startingPeriod;
address memberAddress = memberAddressByDelegateKey[msg.sender];
proposal.sponsor = memberAddress;
proposal.flags[0] = 1; // sponsored
// append proposal to the queue
proposalQueue.push(proposalId);
emit SponsorProposal(msg.sender, memberAddress, proposalId, proposalQueue.length - 1, startingPeriod);
}
// NOTE: In Mystic, proposalIndex != proposalId
function submitVote(uint256 proposalIndex, uint8 uintVote) external onlyDelegate {
address memberAddress = memberAddressByDelegateKey[msg.sender];
Member storage member = members[memberAddress];
require(proposalIndex < proposalQueue.length, "!proposed");
Proposal storage proposal = proposals[proposalQueue[proposalIndex]];
require(uintVote < 3, "!<3");
Vote vote = Vote(uintVote);
require(getCurrentPeriod() >= proposal.startingPeriod, "pending");
require(!hasVotingPeriodExpired(proposal.startingPeriod), "expired");
require(proposal.votesByMember[memberAddress] == Vote.Null, "voted");
require(vote == Vote.Yes || vote == Vote.No, "!Yes||No");
proposal.votesByMember[memberAddress] = vote;
if (vote == Vote.Yes) {
proposal.yesVotes += member.shares;
// set highest index (latest) yes vote - must be processed for member to ragequit
if (proposalIndex > member.highestIndexYesVote) {
member.highestIndexYesVote = proposalIndex;
}
// set maximum of total shares encountered at a yes vote - used to bound dilution for yes voters
if (totalSupply() > proposal.maxTotalSharesAndLootAtYesVote) {
proposal.maxTotalSharesAndLootAtYesVote = totalSupply();
}
} else if (vote == Vote.No) {
proposal.noVotes += member.shares;
}
// NOTE: subgraph indexes by proposalId not proposalIndex since proposalIndex isn't set until it's been sponsored but proposal is created on submission
emit SubmitVote(proposalQueue[proposalIndex], proposalIndex, msg.sender, memberAddress, uintVote);
}
function processProposal(uint256 proposalIndex) external nonReentrant {
_validateProposalForProcessing(proposalIndex);
uint256 proposalId = proposalQueue[proposalIndex];
Proposal storage proposal = proposals[proposalId];
require(proposal.flags[4] == 0 && proposal.flags[5] == 0 && proposal.flags[6] == 0, "!standard");
proposal.flags[1] = 1; // processed
bool didPass = _didPass(proposalIndex);
// Make the proposal fail if the new total number of shares & loot exceeds the limit
if (totalSupply().add(proposal.sharesRequested).add(proposal.lootRequested) > MAX_GUILD_BOUND) {
didPass = false;
}
// Make the proposal fail if it is requesting more tokens as payment than the available guild bank balance
if (proposal.paymentRequested > userTokenBalances[GUILD][proposal.paymentToken]) {
didPass = false;
}
// Make the proposal fail if it would result in too many tokens with non-zero balance in guild bank
if (proposal.tributeOffered > 0 && userTokenBalances[GUILD][proposal.tributeToken] == 0 && totalGuildBankTokens >= MAX_TOKEN_GUILDBANK_COUNT) {
didPass = false;
}
// PROPOSAL PASSED
if (didPass) {
proposal.flags[2] = 1; // didPass
// if the applicant is already a member, add to their existing shares & loot
if (members[proposal.applicant].exists == 1) {
members[proposal.applicant].shares = members[proposal.applicant].shares.add(proposal.sharesRequested);
members[proposal.applicant].loot = members[proposal.applicant].loot.add(proposal.lootRequested);
// if the applicant is a new member, create a new record for them
} else {
registerMember(proposal.applicant, proposal.sharesRequested);
}
// mint new guild token, shares & loot
mintGuildToken(proposal.applicant, proposal.sharesRequested.add(proposal.lootRequested));
totalShares = totalShares.add(proposal.sharesRequested);
totalLoot = totalLoot.add(proposal.lootRequested);
// if the proposal tribute is the first token of its kind to make it into the guild bank, increment total guild bank tokens
if (userTokenBalances[GUILD][proposal.tributeToken] == 0 && proposal.tributeOffered > 0) {
totalGuildBankTokens += 1;
}
unsafeInternalTransfer(ESCROW, GUILD, proposal.tributeToken, proposal.tributeOffered);
unsafeInternalTransfer(GUILD, proposal.applicant, proposal.paymentToken, proposal.paymentRequested);
// if the proposal spends 100% of guild bank balance for a token, decrement total guild bank tokens
if (userTokenBalances[GUILD][proposal.paymentToken] == 0 && proposal.paymentRequested > 0) {
totalGuildBankTokens -= 1;
}
// PROPOSAL FAILED
} else {
// return all tokens to the proposer (not the applicant, because funds come from proposer)
unsafeInternalTransfer(ESCROW, proposal.proposer, proposal.tributeToken, proposal.tributeOffered);
}
_returnDeposit(proposal.sponsor);
emit ProcessProposal(proposalIndex, proposalId, didPass);
}
function processActionProposal(uint256 proposalIndex) external nonReentrant returns (bool, bytes memory) {
_validateProposalForProcessing(proposalIndex);
uint256 proposalId = proposalQueue[proposalIndex];
bytes storage action = actions[proposalId];
Proposal storage proposal = proposals[proposalId];
require(proposal.flags[6] == 1, "!action");
proposal.flags[1] = 1; // processed
bool didPass = _didPass(proposalIndex);
// Make the proposal fail if it is requesting more stake token than the available local balance
if (proposal.paymentToken == stakeToken && proposal.paymentRequested > IERC20(stakeToken).balanceOf(address(this))) {
didPass = false;
}
// Make the proposal fail if it is requesting more tokens than the available guild bank balance
if (tokenWhitelist[proposal.paymentToken] && proposal.paymentRequested > userTokenBalances[GUILD][proposal.paymentToken]) {
didPass = false;
}
// Make the proposal fail if it is requesting more ether than the available local balance
if (proposal.tributeOffered > address(this).balance) {
didPass = false;
}
if (didPass) {
proposal.flags[2] = 1; // didPass
(bool success, bytes memory returnData) = proposal.applicant.call.value(proposal.tributeOffered)(action);
if (tokenWhitelist[proposal.paymentToken]) {
unsafeSubtractFromBalance(GUILD, proposal.paymentToken, proposal.paymentRequested);
// if the action proposal spends 100% of guild bank balance for a token, decrement total guild bank tokens
if (userTokenBalances[GUILD][proposal.paymentToken] == 0 && proposal.paymentRequested > 0) {totalGuildBankTokens -= 1;}
}
return (success, returnData);
}
emit ProcessActionProposal(proposalIndex, proposalId, didPass);
}
function processWhitelistProposal(uint256 proposalIndex) external {
_validateProposalForProcessing(proposalIndex);
uint256 proposalId = proposalQueue[proposalIndex];
Proposal storage proposal = proposals[proposalId];
require(proposal.flags[4] == 1, "!whitelist");
proposal.flags[1] = 1; // processed
bool didPass = _didPass(proposalIndex);
if (approvedTokens.length >= MAX_TOKEN_WHITELIST_COUNT) {
didPass = false;
}
if (didPass) {
proposal.flags[2] = 1; // didPass
tokenWhitelist[address(proposal.tributeToken)] = true;
approvedTokens.push(proposal.tributeToken);
}
proposedToWhitelist[address(proposal.tributeToken)] = false;
_returnDeposit(proposal.sponsor);
emit ProcessWhitelistProposal(proposalIndex, proposalId, didPass);
}
function processGuildKickProposal(uint256 proposalIndex) external nonReentrant {
_validateProposalForProcessing(proposalIndex);
uint256 proposalId = proposalQueue[proposalIndex];
Proposal storage proposal = proposals[proposalId];
require(proposal.flags[5] == 1, "!kick");
proposal.flags[1] = 1; // processed
bool didPass = _didPass(proposalIndex);
if (didPass) {
proposal.flags[2] = 1; // didPass
Member storage member = members[proposal.applicant];
member.jailed = proposalIndex;
// transfer shares to loot
member.loot = member.loot.add(member.shares);
totalShares = totalShares.sub(member.shares);
totalLoot = totalLoot.add(member.shares);
member.shares = 0; // revoke all shares
}
proposedToKick[proposal.applicant] = false;
_returnDeposit(proposal.sponsor);
emit ProcessGuildKickProposal(proposalIndex, proposalId, didPass);
}
function _didPass(uint256 proposalIndex) internal view returns (bool didPass) {
Proposal memory proposal = proposals[proposalQueue[proposalIndex]];
if (proposal.yesVotes > proposal.noVotes) {
didPass = true;
}
// Make the proposal fail if the dilutionBound is exceeded
if ((totalSupply().mul(dilutionBound)) < proposal.maxTotalSharesAndLootAtYesVote) {
didPass = false;
}
// Make the proposal fail if the applicant is jailed
// - for standard proposals, we don't want the applicant to get any shares/loot/payment
// - for guild kick proposals, we should never be able to propose to kick a jailed member (or have two kick proposals active), so it doesn't matter
if (members[proposal.applicant].jailed != 0) {
didPass = false;
}
return didPass;
}
function _validateProposalForProcessing(uint256 proposalIndex) internal view {
require(proposalIndex < proposalQueue.length, "!proposal");
Proposal memory proposal = proposals[proposalQueue[proposalIndex]];
require(getCurrentPeriod() >= proposal.startingPeriod.add(votingPeriodLength).add(gracePeriodLength), "!ready");
require(proposal.flags[1] == 0, "processed");
require(proposalIndex == 0 || proposals[proposalQueue[proposalIndex - 1]].flags[1] == 1, "prior !processed");
}
function _returnDeposit(address sponsor) internal {
unsafeInternalTransfer(ESCROW, msg.sender, depositToken, processingReward);
unsafeInternalTransfer(ESCROW, sponsor, depositToken, proposalDeposit - processingReward);
}
function ragequit(uint256 sharesToBurn, uint256 lootToBurn) external nonReentrant {
require(members[msg.sender].exists == 1, "!member");
_ragequit(msg.sender, sharesToBurn, lootToBurn);
}
function _ragequit(address memberAddress, uint256 sharesToBurn, uint256 lootToBurn) internal {
uint256 initialTotalSharesAndLoot = totalSupply();
Member storage member = members[memberAddress];
require(member.shares >= sharesToBurn, "!shares");
require(member.loot >= lootToBurn, "!loot");
require(canRagequit(member.highestIndexYesVote), "!ragequit until highest index proposal member voted YES processes");
uint256 sharesAndLootToBurn = sharesToBurn.add(lootToBurn);
// burn guild token, shares & loot
burnGuildToken(memberAddress, sharesAndLootToBurn);
member.shares = member.shares.sub(sharesToBurn);
member.loot = member.loot.sub(lootToBurn);
totalShares = totalShares.sub(sharesToBurn);
totalLoot = totalLoot.sub(lootToBurn);
for (uint256 i = 0; i < approvedTokens.length; i++) {
uint256 amountToRagequit = fairShare(userTokenBalances[GUILD][approvedTokens[i]], sharesAndLootToBurn, initialTotalSharesAndLoot);
if (amountToRagequit > 0) { // gas optimization to allow a higher maximum token limit
// deliberately not using safemath here to keep overflows from preventing the function execution (which would break ragekicks)
// if a token overflows, it is because the supply was artificially inflated to oblivion, so we probably don't care about it anyways
userTokenBalances[GUILD][approvedTokens[i]] -= amountToRagequit;
userTokenBalances[memberAddress][approvedTokens[i]] += amountToRagequit;
}
}
emit Ragequit(memberAddress, sharesToBurn, lootToBurn);
}
function ragekick(address memberToKick) external nonReentrant onlyDelegate {
Member storage member = members[memberToKick];
require(member.jailed != 0, "!jailed");
require(member.loot > 0, "!loot"); // note - should be impossible for jailed member to have shares
require(canRagequit(member.highestIndexYesVote), "!ragequit until highest index proposal member voted YES processes");
_ragequit(memberToKick, 0, member.loot);
}
function withdrawBalance(address token, uint256 amount) external nonReentrant {
_withdrawBalance(token, amount);
}
function withdrawBalances(address[] calldata tokens, uint256[] calldata amounts, bool max) external nonReentrant {
require(tokens.length == amounts.length, "tokens != amounts");
for (uint256 i=0; i < tokens.length; i++) {
uint256 withdrawAmount = amounts[i];
if (max) { // withdraw the maximum balance
withdrawAmount = userTokenBalances[msg.sender][tokens[i]];
}
_withdrawBalance(tokens[i], withdrawAmount);
}
}
function _withdrawBalance(address token, uint256 amount) internal {
require(userTokenBalances[msg.sender][token] >= amount, "!balance");
IERC20(token).safeTransfer(msg.sender, amount);
unsafeSubtractFromBalance(msg.sender, token, amount);
emit Withdraw(msg.sender, token, amount);
}
function collectTokens(address token) external nonReentrant onlyDelegate {
uint256 amountToCollect = IERC20(token).balanceOf(address(this)).sub(userTokenBalances[TOTAL][token]);
// only collect if 1) there are tokens to collect & 2) token is whitelisted
require(amountToCollect > 0, "!amount");
require(tokenWhitelist[token], "!whitelisted");
if (userTokenBalances[GUILD][token] == 0 && totalGuildBankTokens < MAX_TOKEN_GUILDBANK_COUNT) {totalGuildBankTokens += 1;}
unsafeAddToBalance(GUILD, token, amountToCollect);
emit TokensCollected(token, amountToCollect);
}
// NOTE: requires that delegate key which sent the original proposal cancels, msg.sender == proposal.proposer
function cancelProposal(uint256 proposalId) external nonReentrant {
Proposal storage proposal = proposals[proposalId];
require(proposal.flags[0] == 0, "sponsored");
require(proposal.flags[3] == 0, "cancelled");
require(msg.sender == proposal.proposer, "!proposer");
proposal.flags[3] = 1; // cancelled
unsafeInternalTransfer(ESCROW, proposal.proposer, proposal.tributeToken, proposal.tributeOffered);
emit CancelProposal(proposalId, msg.sender);
}
function updateDelegateKey(address newDelegateKey) external {
require(members[msg.sender].shares > 0, "caller !shareholder");
require(newDelegateKey != address(0), "newDelegateKey == 0");
// skip checks if member is setting the delegate key to their member address
if (newDelegateKey != msg.sender) {
require(members[newDelegateKey].exists == 0, "!overwrite members");
require(members[memberAddressByDelegateKey[newDelegateKey]].exists == 0, "!overwrite keys");
}
Member storage member = members[msg.sender];
memberAddressByDelegateKey[member.delegateKey] = address(0);
memberAddressByDelegateKey[newDelegateKey] = msg.sender;
member.delegateKey = newDelegateKey;
emit UpdateDelegateKey(msg.sender, newDelegateKey);
}
// can only ragequit if the latest proposal you voted YES on has been processed
function canRagequit(uint256 highestIndexYesVote) public view returns (bool) {
require(highestIndexYesVote < proposalQueue.length, "!proposal");
return proposals[proposalQueue[highestIndexYesVote]].flags[1] == 1;
}
function hasVotingPeriodExpired(uint256 startingPeriod) public view returns (bool) {
return getCurrentPeriod() >= startingPeriod.add(votingPeriodLength);
}
/***************
GETTER FUNCTIONS
***************/
function max(uint256 x, uint256 y) internal pure returns (uint256) {
return x >= y ? x : y;
}
function getCurrentPeriod() public view returns (uint256) {
return now.sub(summoningTime).div(periodDuration);
}
function getMemberProposalVote(address memberAddress, uint256 proposalIndex) external view returns (Vote) {
require(members[memberAddress].exists == 1, "!member");
require(proposalIndex < proposalQueue.length, "!proposed");
return proposals[proposalQueue[proposalIndex]].votesByMember[memberAddress];
}
function getProposalFlags(uint256 proposalId) external view returns (uint8[7] memory) {
return proposals[proposalId].flags;
}
function getProposalQueueLength() external view returns (uint256) {
return proposalQueue.length;
}
function getTokenCount() external view returns (uint256) {
return approvedTokens.length;
}
function getUserTokenBalance(address user, address token) external view returns (uint256) {
return userTokenBalances[user][token];
}
/***************
HELPER FUNCTIONS
***************/
function() external payable {}
function fairShare(uint256 balance, uint256 shares, uint256 totalSharesAndLoot) internal pure returns (uint256) {
require(totalSharesAndLoot != 0);
if (balance == 0) { return 0; }
uint256 prod = balance * shares;
if (prod / balance == shares) { // no overflow in multiplication above?
return prod / totalSharesAndLoot;
}
return (balance / totalSharesAndLoot) * shares;
}
function registerMember(address newMember, uint256 shares) internal {
// if new member is already taken by a member's delegateKey, reset it to their member address
if (members[memberAddressByDelegateKey[newMember]].exists == 1) {
address memberToOverride = memberAddressByDelegateKey[newMember];
memberAddressByDelegateKey[memberToOverride] = memberToOverride;
members[memberToOverride].delegateKey = memberToOverride;
}
members[newMember] = Member({
delegateKey : newMember,
exists : 1, // 'true'
shares : shares,
loot : 0,
highestIndexYesVote : 0,
jailed : 0
});
memberAddressByDelegateKey[newMember] = newMember;
}
function unsafeAddToBalance(address user, address token, uint256 amount) internal {
userTokenBalances[user][token] += amount;
userTokenBalances[TOTAL][token] += amount;
}
function unsafeInternalTransfer(address from, address to, address token, uint256 amount) internal {
unsafeSubtractFromBalance(from, token, amount);
unsafeAddToBalance(to, token, amount);
}
function unsafeSubtractFromBalance(address user, address token, uint256 amount) internal {
userTokenBalances[user][token] -= amount;
userTokenBalances[TOTAL][token] -= amount;
}
/********************
GUILD TOKEN FUNCTIONS
********************/
function allowance(address owner, address spender) external view returns (uint256) { // tracks guild token (loot) allowances
return allowances[owner][spender];
}
function balanceOf(address account) external view returns (uint256) {
return balances[account];
}
function totalSupply() public view returns (uint256) {
return totalShares.add(totalLoot);
}
// BALANCE MGMT FUNCTIONS
function approve(address spender, uint256 amount) external returns (bool) {
require(amount == 0 || allowances[msg.sender][spender] == 0);
allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function burnGuildToken(address memberAddress, uint256 amount) internal {
balances[memberAddress] = balances[memberAddress].sub(amount);
emit Transfer(memberAddress, address(0), amount);
}
function claimShares(uint256 amount) external nonReentrant {
IERC20(stakeToken).safeTransferFrom(msg.sender, address(this), amount); // deposit stake token & claim shares (1:1)
// if the sender is already a member, add to their existing shares
if (members[msg.sender].exists == 1) {
members[msg.sender].shares = members[msg.sender].shares.add(amount);
// if the sender is a new member, create a new record for them
} else {
registerMember(msg.sender, amount);
}
// mint new guild token & shares
mintGuildToken(msg.sender, amount);
totalShares = totalShares.add(amount);
require(totalShares <= MAX_GUILD_BOUND, "guild maxed");
}
function convertSharesToLoot(uint256 sharesToLoot) external nonReentrant {
members[msg.sender].shares = members[msg.sender].shares.sub(sharesToLoot);
members[msg.sender].loot = members[msg.sender].loot.add(sharesToLoot);
totalShares = totalShares.sub(sharesToLoot);
totalLoot = totalLoot.add(sharesToLoot);
}
function mintGuildToken(address memberAddress, uint256 amount) internal {
balances[memberAddress] = balances[memberAddress].add(amount);
emit Transfer(address(0), memberAddress, amount);
}
// LOOT TRANSFER FUNCTIONS
function transfer(address receiver, uint256 lootToTransfer) external returns (bool) {
members[msg.sender].loot = members[msg.sender].loot.sub(lootToTransfer);
members[receiver].loot = members[receiver].loot.add(lootToTransfer);
balances[msg.sender] = balances[msg.sender].sub(lootToTransfer);
balances[receiver] = balances[receiver].add(lootToTransfer);
emit Transfer(msg.sender, receiver, lootToTransfer);
return true;
}
function transferFrom(address sender, address receiver, uint256 lootToTransfer) external returns (bool) {
allowances[sender][msg.sender] = allowances[sender][msg.sender].sub(lootToTransfer);
members[sender].loot = members[sender].loot.sub(lootToTransfer);
members[receiver].loot = members[receiver].loot.add(lootToTransfer);
balances[sender] = balances[sender].sub(lootToTransfer);
balances[receiver] = balances[receiver].add(lootToTransfer);
emit Transfer(sender, receiver, lootToTransfer);
return true;
}
}

Contract ABI

[{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"spender","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"CancelProposal","inputs":[{"type":"uint256","name":"proposalId","internalType":"uint256","indexed":true},{"type":"address","name":"applicantAddress","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"ProcessActionProposal","inputs":[{"type":"uint256","name":"proposalIndex","internalType":"uint256","indexed":true},{"type":"uint256","name":"proposalId","internalType":"uint256","indexed":true},{"type":"bool","name":"didPass","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"ProcessGuildKickProposal","inputs":[{"type":"uint256","name":"proposalIndex","internalType":"uint256","indexed":true},{"type":"uint256","name":"proposalId","internalType":"uint256","indexed":true},{"type":"bool","name":"didPass","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"ProcessProposal","inputs":[{"type":"uint256","name":"proposalIndex","internalType":"uint256","indexed":true},{"type":"uint256","name":"proposalId","internalType":"uint256","indexed":true},{"type":"bool","name":"didPass","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"ProcessWhitelistProposal","inputs":[{"type":"uint256","name":"proposalIndex","internalType":"uint256","indexed":true},{"type":"uint256","name":"proposalId","internalType":"uint256","indexed":true},{"type":"bool","name":"didPass","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"Ragequit","inputs":[{"type":"address","name":"memberAddress","internalType":"address","indexed":true},{"type":"uint256","name":"sharesToBurn","internalType":"uint256","indexed":false},{"type":"uint256","name":"lootToBurn","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SponsorProposal","inputs":[{"type":"address","name":"delegateKey","internalType":"address","indexed":true},{"type":"address","name":"memberAddress","internalType":"address","indexed":true},{"type":"uint256","name":"proposalId","internalType":"uint256","indexed":false},{"type":"uint256","name":"proposalIndex","internalType":"uint256","indexed":false},{"type":"uint256","name":"startingPeriod","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SubmitProposal","inputs":[{"type":"address","name":"applicant","internalType":"address","indexed":true},{"type":"uint256","name":"sharesRequested","internalType":"uint256","indexed":false},{"type":"uint256","name":"lootRequested","internalType":"uint256","indexed":false},{"type":"uint256","name":"tributeOffered","internalType":"uint256","indexed":false},{"type":"address","name":"tributeToken","internalType":"address","indexed":false},{"type":"uint256","name":"paymentRequested","internalType":"uint256","indexed":false},{"type":"address","name":"paymentToken","internalType":"address","indexed":false},{"type":"bytes32","name":"details","internalType":"bytes32","indexed":false},{"type":"uint8[7]","name":"flags","internalType":"uint8[7]","indexed":false},{"type":"bytes","name":"data","internalType":"bytes","indexed":false},{"type":"uint256","name":"proposalId","internalType":"uint256","indexed":false},{"type":"address","name":"delegateKey","internalType":"address","indexed":true},{"type":"address","name":"memberAddress","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"SubmitVote","inputs":[{"type":"uint256","name":"proposalId","internalType":"uint256","indexed":false},{"type":"uint256","name":"proposalIndex","internalType":"uint256","indexed":true},{"type":"address","name":"delegateKey","internalType":"address","indexed":true},{"type":"address","name":"memberAddress","internalType":"address","indexed":true},{"type":"uint8","name":"uintVote","internalType":"uint8","indexed":false}],"anonymous":false},{"type":"event","name":"TokensCollected","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"uint256","name":"amountToCollect","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"UpdateDelegateKey","inputs":[{"type":"address","name":"memberAddress","internalType":"address","indexed":true},{"type":"address","name":"newDelegateKey","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Withdraw","inputs":[{"type":"address","name":"memberAddress","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"fallback","stateMutability":"payable","payable":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"ESCROW","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"GUILD","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"TOTAL","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bytes","name":"","internalType":"bytes"}],"name":"actions","inputs":[{"type":"uint256","name":"","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"spender","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"approvedTokens","inputs":[{"type":"uint256","name":"","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"canRagequit","inputs":[{"type":"uint256","name":"highestIndexYesVote","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"cancelProposal","inputs":[{"type":"uint256","name":"proposalId","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"claimShares","inputs":[{"type":"uint256","name":"amount","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"collectTokens","inputs":[{"type":"address","name":"token","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"convertSharesToLoot","inputs":[{"type":"uint256","name":"sharesToLoot","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"depositToken","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"dilutionBound","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getCurrentPeriod","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint8","name":"","internalType":"enum Mystic.Vote"}],"name":"getMemberProposalVote","inputs":[{"type":"address","name":"memberAddress","internalType":"address"},{"type":"uint256","name":"proposalIndex","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint8[7]","name":"","internalType":"uint8[7]"}],"name":"getProposalFlags","inputs":[{"type":"uint256","name":"proposalId","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getProposalQueueLength","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTokenCount","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getUserTokenBalance","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"address","name":"token","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"gracePeriodLength","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"hasVotingPeriodExpired","inputs":[{"type":"uint256","name":"startingPeriod","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"init","inputs":[{"type":"address","name":"_depositToken","internalType":"address"},{"type":"address","name":"_stakeToken","internalType":"address"},{"type":"address[]","name":"_summoner","internalType":"address[]"},{"type":"uint256[]","name":"_summonerShares","internalType":"uint256[]"},{"type":"uint256","name":"_summonerDeposit","internalType":"uint256"},{"type":"uint256","name":"_proposalDeposit","internalType":"uint256"},{"type":"uint256","name":"_processingReward","internalType":"uint256"},{"type":"uint256","name":"_periodDuration","internalType":"uint256"},{"type":"uint256","name":"_votingPeriodLength","internalType":"uint256"},{"type":"uint256","name":"_gracePeriodLength","internalType":"uint256"},{"type":"uint256","name":"_dilutionBound","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"memberAddressByDelegateKey","inputs":[{"type":"address","name":"","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"delegateKey","internalType":"address"},{"type":"uint8","name":"exists","internalType":"uint8"},{"type":"uint256","name":"shares","internalType":"uint256"},{"type":"uint256","name":"loot","internalType":"uint256"},{"type":"uint256","name":"highestIndexYesVote","internalType":"uint256"},{"type":"uint256","name":"jailed","internalType":"uint256"}],"name":"members","inputs":[{"type":"address","name":"","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"periodDuration","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"},{"type":"bytes","name":"","internalType":"bytes"}],"name":"processActionProposal","inputs":[{"type":"uint256","name":"proposalIndex","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"processGuildKickProposal","inputs":[{"type":"uint256","name":"proposalIndex","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"processProposal","inputs":[{"type":"uint256","name":"proposalIndex","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"processWhitelistProposal","inputs":[{"type":"uint256","name":"proposalIndex","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"processingReward","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"proposalCount","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"proposalDeposit","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"proposalQueue","inputs":[{"type":"uint256","name":"","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"applicant","internalType":"address"},{"type":"address","name":"proposer","internalType":"address"},{"type":"address","name":"sponsor","internalType":"address"},{"type":"address","name":"tributeToken","internalType":"address"},{"type":"address","name":"paymentToken","internalType":"address"},{"type":"uint256","name":"sharesRequested","internalType":"uint256"},{"type":"uint256","name":"lootRequested","internalType":"uint256"},{"type":"uint256","name":"paymentRequested","internalType":"uint256"},{"type":"uint256","name":"tributeOffered","internalType":"uint256"},{"type":"uint256","name":"startingPeriod","internalType":"uint256"},{"type":"uint256","name":"yesVotes","internalType":"uint256"},{"type":"uint256","name":"noVotes","internalType":"uint256"},{"type":"uint256","name":"maxTotalSharesAndLootAtYesVote","internalType":"uint256"},{"type":"bytes32","name":"details","internalType":"bytes32"}],"name":"proposals","inputs":[{"type":"uint256","name":"","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"proposedToKick","inputs":[{"type":"address","name":"","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"proposedToWhitelist","inputs":[{"type":"address","name":"","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"ragekick","inputs":[{"type":"address","name":"memberToKick","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"ragequit","inputs":[{"type":"uint256","name":"sharesToBurn","internalType":"uint256"},{"type":"uint256","name":"lootToBurn","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"sponsorProposal","inputs":[{"type":"uint256","name":"proposalId","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"stakeToken","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"uint256","name":"proposalId","internalType":"uint256"}],"name":"submitActionProposal","inputs":[{"type":"address","name":"actionTo","internalType":"address"},{"type":"address","name":"actionToken","internalType":"address"},{"type":"uint256","name":"actionTokenAmount","internalType":"uint256"},{"type":"uint256","name":"actionValue","internalType":"uint256"},{"type":"bytes32","name":"details","internalType":"bytes32"},{"type":"bytes","name":"data","internalType":"bytes"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"uint256","name":"proposalId","internalType":"uint256"}],"name":"submitGuildKickProposal","inputs":[{"type":"address","name":"memberToKick","internalType":"address"},{"type":"bytes32","name":"details","internalType":"bytes32"}],"constant":false},{"type":"function","stateMutability":"payable","payable":true,"outputs":[{"type":"uint256","name":"proposalId","internalType":"uint256"}],"name":"submitProposal","inputs":[{"type":"address","name":"applicant","internalType":"address"},{"type":"uint256","name":"sharesRequested","internalType":"uint256"},{"type":"uint256","name":"lootRequested","internalType":"uint256"},{"type":"uint256","name":"tributeOffered","internalType":"uint256"},{"type":"address","name":"tributeToken","internalType":"address"},{"type":"uint256","name":"paymentRequested","internalType":"uint256"},{"type":"address","name":"paymentToken","internalType":"address"},{"type":"bytes32","name":"details","internalType":"bytes32"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"submitVote","inputs":[{"type":"uint256","name":"proposalIndex","internalType":"uint256"},{"type":"uint8","name":"uintVote","internalType":"uint8"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"uint256","name":"proposalId","internalType":"uint256"}],"name":"submitWhitelistProposal","inputs":[{"type":"address","name":"tokenToWhitelist","internalType":"address"},{"type":"bytes32","name":"details","internalType":"bytes32"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"summoningTime","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"tokenWhitelist","inputs":[{"type":"address","name":"","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalGuildBankTokens","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalLoot","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalShares","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"receiver","internalType":"address"},{"type":"uint256","name":"lootToTransfer","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"sender","internalType":"address"},{"type":"address","name":"receiver","internalType":"address"},{"type":"uint256","name":"lootToTransfer","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"updateDelegateKey","inputs":[{"type":"address","name":"newDelegateKey","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"votingPeriodLength","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"wETH","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"withdrawBalance","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"withdrawBalances","inputs":[{"type":"address[]","name":"tokens","internalType":"address[]"},{"type":"uint256[]","name":"amounts","internalType":"uint256[]"},{"type":"bool","name":"max","internalType":"bool"}],"constant":false}]
            

Deployed ByteCode

0x6080604052600436106103b85760003560e01c80637a609641116101f2578063b2643aab1161010d578063e1780345116100a0578063ea7b6ffd1161006f578063ea7b6ffd146110c1578063f242862114611116578063f5d54c771461112b578063ff82cc6c14611140576103b8565b8063e178034514611025578063e1a0e3fa14611058578063e63bc62d14611082578063e681c4aa146110ac576103b8565b8063da35c664116100dc578063da35c66414610f78578063dd62ed3e14610f8d578063dfdd369e14610fc8578063e0a8f6f514610ffb576103b8565b8063b2643aab14610ec2578063b470aade14610f24578063c68e45b714610f39578063c89039c514610f63576103b8565b80639746d94011610185578063a42e01c111610154578063a42e01c114610d32578063a4d2d9ec14610e3b578063a9059cbb14610e74578063afe5475f14610ead576103b8565b80639746d94014610c9657806399653fbe14610cc05780639d1722cb14610cf3578063a3dc380014610d08576103b8565b806388fbe1e1116101c157806388fbe1e114610b9b5780638b15a60514610c425780639425a47614610c5757806395d89b4114610c81576103b8565b80637a60964114610b1d5780637d5b6c7214610b4757806383240f8314610b5c5780638340bbce14610b86576103b8565b80633793ab3c116102e2578063635e99aa1161027557806373f8fd4b1161024457806373f8fd4b14610a85578063753d756314610ac057806378a8956714610af3578063797daf7014610b08576103b8565b8063635e99aa146109ef57806363858f2d14610a045780636d4475eb14610a1957806370a0823114610a52576103b8565b8063402c1794116102b1578063402c1794146108a75780634482394b146108da57806351ed6a30146109a757806359999b41146109bc576103b8565b80633793ab3c1461080b5780633a98ef39146108355780633b214a741461084a5780633fc24bba14610874576103b8565b80630cf20cc91161035a57806323b872dd1161032957806323b872dd146107555780632582bf2a1461079857806327efc086146107cb578063313ce567146107e0576103b8565b80630cf20cc91461069157806315eb349e146106ca57806318160ddd146106fa5780631dafede01461070f576103b8565b806306fdde031161039657806306fdde0314610533578063086146d2146105bd57806308ae4b0c146105d2578063095ea7b314610644576103b8565b8063013cf08b146103ba57806303e32fa1146104af578063044a0ca8146104d6575b005b3480156103c657600080fd5b506103e4600480360360208110156103dd57600080fd5b50356111ed565b604051808f6001600160a01b03166001600160a01b031681526020018e6001600160a01b03166001600160a01b031681526020018d6001600160a01b03166001600160a01b031681526020018c6001600160a01b03166001600160a01b031681526020018b6001600160a01b03166001600160a01b031681526020018a81526020018981526020018881526020018781526020018681526020018581526020018481526020018381526020018281526020019e50505050505050505050505050505060405180910390f35b3480156104bb57600080fd5b506104c461126c565b60408051918252519081900360200190f35b3480156104e257600080fd5b5061050f600480360360408110156104f957600080fd5b506001600160a01b038135169060200135611272565b6040518082600281111561051f57fe5b60ff16815260200191505060405180910390f35b34801561053f57600080fd5b50610548611365565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561058257818101518382015260200161056a565b50505050905090810190601f1680156105af5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156105c957600080fd5b506104c461138b565b3480156105de57600080fd5b50610605600480360360208110156105f557600080fd5b50356001600160a01b03166113ba565b604080516001600160a01b03909716875260ff9095166020870152858501939093526060850191909152608084015260a0830152519081900360c00190f35b34801561065057600080fd5b5061067d6004803603604081101561066757600080fd5b506001600160a01b0381351690602001356113fa565b604080519115158252519081900360200190f35b34801561069d57600080fd5b506103b8600480360360408110156106b457600080fd5b506001600160a01b03813516906020013561149a565b3480156106d657600080fd5b506103b8600480360360408110156106ed57600080fd5b5080359060200135611504565b34801561070657600080fd5b506104c46115b3565b34801561071b57600080fd5b506107396004803603602081101561073257600080fd5b50356115cc565b604080516001600160a01b039092168252519081900360200190f35b34801561076157600080fd5b5061067d6004803603606081101561077857600080fd5b506001600160a01b038135811691602081013590911690604001356115f3565b3480156107a457600080fd5b506103b8600480360360208110156107bb57600080fd5b50356001600160a01b031661176a565b3480156107d757600080fd5b5061073961198e565b3480156107ec57600080fd5b506107f5611994565b6040805160ff9092168252519081900360200190f35b34801561081757600080fd5b506103b86004803603602081101561082e57600080fd5b5035611999565b34801561084157600080fd5b506104c4611b54565b34801561085657600080fd5b506104c46004803603602081101561086d57600080fd5b5035611b5a565b34801561088057600080fd5b5061067d6004803603602081101561089757600080fd5b50356001600160a01b0316611b78565b3480156108b357600080fd5b50610739600480360360208110156108ca57600080fd5b50356001600160a01b0316611b8d565b3480156108e657600080fd5b506103b8600480360360608110156108fd57600080fd5b810190602081018135600160201b81111561091757600080fd5b82018360208201111561092957600080fd5b803590602001918460208302840111600160201b8311171561094a57600080fd5b919390929091602081019035600160201b81111561096757600080fd5b82018360208201111561097957600080fd5b803590602001918460208302840111600160201b8311171561099a57600080fd5b9193509150351515611ba8565b3480156109b357600080fd5b50610739611cfa565b3480156109c857600080fd5b506103b8600480360360208110156109df57600080fd5b50356001600160a01b0316611d09565b3480156109fb57600080fd5b506104c4611fab565b348015610a1057600080fd5b506104c4611fb1565b348015610a2557600080fd5b506104c460048036036040811015610a3c57600080fd5b506001600160a01b038135169060200135611fb7565b348015610a5e57600080fd5b506104c460048036036020811015610a7557600080fd5b50356001600160a01b0316612119565b348015610a9157600080fd5b506104c460048036036040811015610aa857600080fd5b506001600160a01b0381358116916020013516612134565b348015610acc57600080fd5b5061067d60048036036020811015610ae357600080fd5b50356001600160a01b031661215f565b348015610aff57600080fd5b506104c4612174565b348015610b1457600080fd5b506104c461217a565b348015610b2957600080fd5b506103b860048036036020811015610b4057600080fd5b5035612180565b348015610b5357600080fd5b506104c4612269565b348015610b6857600080fd5b5061054860048036036020811015610b7f57600080fd5b503561226f565b348015610b9257600080fd5b506104c461230a565b348015610ba757600080fd5b506104c4600480360360c0811015610bbe57600080fd5b6001600160a01b0382358116926020810135909116916040820135916060810135916080820135919081019060c0810160a0820135600160201b811115610c0457600080fd5b820183602082011115610c1657600080fd5b803590602001918460018302840111600160201b83111715610c3757600080fd5b509092509050612310565b348015610c4e57600080fd5b506104c461238e565b348015610c6357600080fd5b5061067d60048036036020811015610c7a57600080fd5b5035612394565b348015610c8d57600080fd5b506105486123bb565b348015610ca257600080fd5b506103b860048036036020811015610cb957600080fd5b50356123dc565b348015610ccc57600080fd5b506103b860048036036040811015610ce357600080fd5b508035906020013560ff166129d3565b348015610cff57600080fd5b506104c4612daa565b348015610d1457600080fd5b5061067d60048036036020811015610d2b57600080fd5b5035612db0565b348015610d3e57600080fd5b506103b86004803603610160811015610d5657600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b811115610d8957600080fd5b820183602082011115610d9b57600080fd5b803590602001918460208302840111600160201b83111715610dbc57600080fd5b919390929091602081019035600160201b811115610dd957600080fd5b820183602082011115610deb57600080fd5b803590602001918460208302840111600160201b83111715610e0c57600080fd5b919350915080359060208101359060408101359060608101359060808101359060a08101359060c00135612e51565b348015610e4757600080fd5b506104c460048036036040811015610e5e57600080fd5b506001600160a01b0381351690602001356131c3565b348015610e8057600080fd5b5061067d60048036036040811015610e9757600080fd5b506001600160a01b038135169060200135613359565b348015610eb957600080fd5b506104c461346e565b348015610ece57600080fd5b50610eec60048036036020811015610ee557600080fd5b5035613474565b604051808260e080838360005b83811015610f11578181015183820152602001610ef9565b5050505090500191505060405180910390f35b348015610f3057600080fd5b506104c46134dc565b348015610f4557600080fd5b506103b860048036036020811015610f5c57600080fd5b50356134e2565b348015610f6f57600080fd5b50610739613639565b348015610f8457600080fd5b506104c461364d565b348015610f9957600080fd5b506104c460048036036040811015610fb057600080fd5b506001600160a01b0381358116916020013516613653565b348015610fd457600080fd5b506103b860048036036020811015610feb57600080fd5b50356001600160a01b031661367e565b34801561100757600080fd5b506103b86004803603602081101561101e57600080fd5b5035613821565b34801561103157600080fd5b5061067d6004803603602081101561104857600080fd5b50356001600160a01b03166139e3565b34801561106457600080fd5b506103b86004803603602081101561107b57600080fd5b50356139f8565b34801561108e57600080fd5b506103b8600480360360208110156110a557600080fd5b5035613bf6565b3480156110b857600080fd5b506107396140b7565b6104c460048036036101008110156110d857600080fd5b506001600160a01b038135811691602081013591604082013591606081013591608082013581169160a08101359160c0820135169060e001356140bd565b34801561112257600080fd5b50610739614622565b34801561113757600080fd5b5061073961463a565b34801561114c57600080fd5b5061116a6004803603602081101561116357600080fd5b5035614640565b604051808315151515815260200180602001828103825283818151815260200191508051906020019080838360005b838110156111b1578181015183820152602001611199565b50505050905090810190601f1680156111de5780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b6015602052600090815260409020805460018201546002830154600384015460048501546006860154600787015460088801546009890154600a8a0154600b8b0154600c8c0154600d8d0154600e909d01546001600160a01b039c8d169d9b8d169c9a8b169b998b169a9098169896979596949593949293919290918e565b60035481565b6001600160a01b038216600090815260186020526040812054600160a01b900460ff166001146112d3576040805162461bcd60e51b815260206004820152600760248201526610b6b2b6b132b960c91b604482015290519081900360640190fd5b6014548210611315576040805162461bcd60e51b8152602060048201526009602482015268085c1c9bdc1bdcd95960ba1b604482015290519081900360640190fd5b601560006014848154811061132657fe5b6000918252602080832090910154835282810193909352604091820181206001600160a01b0387168252600f0190925290205460ff1690505b92915050565b6040518060400160405280600a8152602001694d59535449432044414f60b01b81525081565b60006113b46004546113a860085442614a2e90919063ffffffff16565b9063ffffffff614a4316565b90505b90565b601860205260009081526040902080546001820154600283015460038401546004909401546001600160a01b03841694600160a01b90940460ff16939086565b600081158061142a57503360009081526010602090815260408083206001600160a01b0387168452909152902054155b61143357600080fd5b3360008181526010602090815260408083206001600160a01b03881680855290835292819020869055805186815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a350600192915050565b60005460ff166114df576040805162461bcd60e51b815260206004820152601f6024820152600080516020615f08833981519152604482015290519081900360640190fd5b6000805460ff191690556114f38282614a65565b50506000805460ff19166001179055565b60005460ff16611549576040805162461bcd60e51b815260206004820152601f6024820152600080516020615f08833981519152604482015290519081900360640190fd5b6000805460ff1916815533815260186020526040902054600160a01b900460ff166001146115a8576040805162461bcd60e51b815260206004820152600760248201526610b6b2b6b132b960c91b604482015290519081900360640190fd5b6114f3338383614b34565b60006113b4600c54600b54614e1890919063ffffffff16565b601281815481106115d957fe5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0383166000908152601060209081526040808320338452909152812054611627908363ffffffff614a2e16565b6001600160a01b03851660008181526010602090815260408083203384528252808320949094559181526018909152206002015461166b908363ffffffff614a2e16565b6001600160a01b0380861660009081526018602052604080822060029081019490945591861681522001546116a6908363ffffffff614e1816565b6001600160a01b038085166000908152601860209081526040808320600201949094559187168152600f90915220546116e5908363ffffffff614a2e16565b6001600160a01b038086166000908152600f6020526040808220939093559085168152205461171a908363ffffffff614e1816565b6001600160a01b038085166000818152600f60209081526040918290209490945580518681529051919392881692600080516020615f4883398151915292918290030190a35060015b9392505050565b336000908152601860205260409020600101546117c4576040805162461bcd60e51b815260206004820152601360248201527231b0b63632b91010b9b430b932b437b63232b960691b604482015290519081900360640190fd5b6001600160a01b038116611815576040805162461bcd60e51b815260206004820152601360248201527206e657744656c65676174654b6579203d3d203606c1b604482015290519081900360640190fd5b6001600160a01b0381163314611905576001600160a01b038116600090815260186020526040902054600160a01b900460ff161561188f576040805162461bcd60e51b8152602060048201526012602482015271216f7665727772697465206d656d6265727360701b604482015290519081900360640190fd5b6001600160a01b038181166000908152601960209081526040808320549093168252601890522054600160a01b900460ff1615611905576040805162461bcd60e51b815260206004820152600f60248201526e216f7665727772697465206b65797360881b604482015290519081900360640190fd5b33600081815260186020908152604080832080546001600160a01b0390811685526019845282852080546001600160a01b031990811690915590871680865294839020805482168717905581541684178155815193845290519093927fde7b64a369e10562cc2e71f0f1f944eaf144b75fead6ecb51fac9c4dd693488592908290030190a25050565b61deed81565b601281565b6119a281614e2a565b6000601482815481106119b157fe5b60009182526020808320919091015480835260159091526040909120600581015491925090600160201b900460ff16600114611a21576040805162461bcd60e51b815260206004820152600a602482015269085dda1a5d195b1a5cdd60b21b604482015290519081900360640190fd5b60058101805461ff0019166101001790556000611a3d846150f5565b60125490915061019011611a4f575060005b8015611ae05760058201805462ff00001916620100001790556003820180546001600160a01b039081166000908152601360205260408120805460ff1916600190811790915592546012805494850181559091527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34449092018054929091166001600160a01b03199092169190911790555b60038201546001600160a01b039081166000908152601660205260409020805460ff191690556002830154611b159116615298565b6040805182151581529051849186917f2094fc13d2ecb0acd6861e82bd006c7e5ab6f312ec0c6cdfe3d1a01ee54d885a9181900360200190a350505050565b600b5481565b60148181548110611b6757fe5b600091825260209091200154905081565b60176020526000908152604090205460ff1681565b6019602052600090815260409020546001600160a01b031681565b60005460ff16611bed576040805162461bcd60e51b815260206004820152601f6024820152600080516020615f08833981519152604482015290519081900360640190fd5b6000805460ff19169055838214611c3f576040805162461bcd60e51b8152602060048201526011602482015270746f6b656e7320213d20616d6f756e747360781b604482015290519081900360640190fd5b60005b84811015611ce5576000848483818110611c5857fe5b9050602002013590508215611cb75733600090815260116020526040812090888885818110611c8357fe5b905060200201356001600160a01b03166001600160a01b03166001600160a01b031681526020019081526020016000205490505b611cdc878784818110611cc657fe5b905060200201356001600160a01b031682614a65565b50600101611c42565b50506000805460ff1916600117905550505050565b6001546001600160a01b031681565b60005460ff16611d4e576040805162461bcd60e51b815260206004820152601f6024820152600080516020615f08833981519152604482015290519081900360640190fd5b6000805460ff19168155338152601960209081526040808320546001600160a01b031683526018909152902060010154611dbb576040805162461bcd60e51b81526020600482015260096024820152682164656c656761746560b81b604482015290519081900360640190fd5b6001600160a01b03811660008181527f57db7c30545d4d48d1c5d59f308748a14de480f9ecd985c3dc261a416ac0c623602090815260408083205481516370a0823160e01b815230600482015291519394611e6d94919390926370a082319260248083019392829003018186803b158015611e3557600080fd5b505afa158015611e49573d6000803e3d6000fd5b505050506040513d6020811015611e5f57600080fd5b50519063ffffffff614a2e16565b905060008111611eae576040805162461bcd60e51b815260206004820152600760248201526608585b5bdd5b9d60ca1b604482015290519081900360640190fd5b6001600160a01b03821660009081526013602052604090205460ff16611f0a576040805162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b604482015290519081900360640190fd5b6001600160a01b0382166000908152600080516020615f288339815191526020526040902054158015611f3f575060c8600d54105b15611f4e57600d805460010190555b611f5b61dead83836152e9565b6040805182815290516001600160a01b038416917f9381e53ffdc9733a6783a6f8665be3f89c231bb81a6771996ed553b4e75c0fe3919081900360200190a250506000805460ff19166001179055565b600c5481565b60065481565b6000611fc1615ca1565b506001600160a01b03838116600090815260186020908152604091829020825160c08101845281549485168152600160a01b90940460ff1691840191909152600181015491830182905260028101546060840152600381015460808401526004015460a0830152151580612039575060008160600151115b612079576040805162461bcd60e51b815260206004820152600c60248201526b085cda185c995f1f1b1bdbdd60a21b604482015290519081900360640190fd5b6001600160a01b038416600090815260186020526040902060040154156120d0576040805162461bcd60e51b81526020600482015260066024820152651a985a5b195960d21b604482015290519081900360640190fd5b6120d8615ce3565b600160a08201526040805160208101909152600080825261210991879190819081908190819081908c908a90615347565b5050600a54600019019392505050565b6001600160a01b03166000908152600f602052604090205490565b6001600160a01b03918216600090815260116020908152604080832093909416825291909152205490565b60136020526000908152604090205460ff1681565b60125490565b60145490565b60005460ff166121c5576040805162461bcd60e51b815260206004820152601f6024820152600080516020615f08833981519152604482015290519081900360640190fd5b6000805460ff19168155338152601860205260409020600101546121ef908263ffffffff614a2e16565b33600090815260186020526040902060018101919091556002015461221a908263ffffffff614e1816565b33600090815260186020526040902060020155600b54612240908263ffffffff614a2e16565b600b55600c54612256908263ffffffff614e1816565b600c55506000805460ff19166001179055565b60085481565b600e6020908152600091825260409182902080548351601f6002600019610100600186161502019093169290920491820184900484028101840190945280845290918301828280156123025780601f106122d757610100808354040283529160200191612302565b820191906000526020600020905b8154815290600101906020018083116122e557829003601f168201915b505050505081565b60055481565b600061231a615ce3565b6001816006602002019060ff16908160ff168152505061237a896000808960008c8e8c898d8d8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061534792505050565b5050600a5460001901979650505050505050565b60025481565b60006123ab60055483614e1890919063ffffffff16565b6123b361138b565b101592915050565b604051806040016040528060058152602001644d5844414f60d81b81525081565b60005460ff16612421576040805162461bcd60e51b815260206004820152601f6024820152600080516020615f08833981519152604482015290519081900360640190fd5b6000805460ff19168155338152601960209081526040808320546001600160a01b03168352601890915290206001015461248e576040805162461bcd60e51b81526020600482015260096024820152682164656c656761746560b81b604482015290519081900360640190fd5b6002546000546124b1916101009091046001600160a01b031690339030906156d0565b6124d561deaf600060019054906101000a90046001600160a01b03166002546152e9565b600081815260156020526040902060018101546001600160a01b031661252e576040805162461bcd60e51b8152602060048201526009602482015268085c1c9bdc1bdcd95960ba1b604482015290519081900360640190fd5b600581015460ff1615612574576040805162461bcd60e51b81526020600482015260096024820152681cdc1bdb9cdbdc995960ba1b604482015290519081900360640190fd5b60058101546301000000900460ff16156125c1576040805162461bcd60e51b815260206004820152600960248201526818d85b98d95b1b195960ba1b604482015290519081900360640190fd5b80546001600160a01b031660009081526018602052604090206004015415612623576040805162461bcd60e51b815260206004820152601060248201526f185c1c1b1a58d85b9d081a985a5b195960821b604482015290519081900360640190fd5b6000816009015411801561265e575060038101546001600160a01b03166000908152600080516020615f288339815191526020526040902054155b156126ac5760c8600d54106126ac576040805162461bcd60e51b815260206004820152600f60248201526e19dd5a5b1918985b9ac81b585e1959608a1b604482015290519081900360640190fd5b6005810154600160201b900460ff16600114156128005760038101546001600160a01b031660009081526013602052604090205460ff1615612723576040805162461bcd60e51b815260206004820152600b60248201526a1dda1a5d195b1a5cdd195960aa1b604482015290519081900360640190fd5b60038101546001600160a01b031660009081526016602052604090205460ff161561278a576040805162461bcd60e51b81526020600482015260126024820152711dda1a5d195b1a5cdd081c1c9bdc1bdcd95960721b604482015290519081900360640190fd5b601254610190116127d4576040805162461bcd60e51b815260206004820152600f60248201526e1dda1a5d195b1a5cdd081b585e1959608a1b604482015290519081900360640190fd5b60038101546001600160a01b03166000908152601660205260409020805460ff1916600117905561289d565b600581015465010000000000900460ff166001141561289d5780546001600160a01b031660009081526017602052604090205460ff1615612878576040805162461bcd60e51b815260206004820152600d60248201526c1ada58dac81c1c9bdc1bdcd959609a1b604482015290519081900360640190fd5b80546001600160a01b03166000908152601760205260409020805460ff191660011790555b60006128f46128aa61138b565b601454156128ec576014805460159160009160001981019081106128ca57fe5b90600052602060002001548152602001908152602001600020600a01546128ef565b60005b615730565b6001908101600a8401819055336000818152601960209081526040808320546002890180546001600160a01b0319166001600160a01b03909216918217905560058901805460ff191688179055601480549788018155938490527fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec9096018990559154825189815260001990910191810191909152808201849052905192945083927f2a383a979381335e3eb401ac01dd8083e024ff0256bf5338456ffc0063390bbd9181900360600190a350506000805460ff191660011790555050565b336000908152601960209081526040808320546001600160a01b031683526018909152902060010154612a39576040805162461bcd60e51b81526020600482015260096024820152682164656c656761746560b81b604482015290519081900360640190fd5b336000908152601960209081526040808320546001600160a01b031680845260189092529091206014548410612aa2576040805162461bcd60e51b8152602060048201526009602482015268085c1c9bdc1bdcd95960ba1b604482015290519081900360640190fd5b60006015600060148781548110612ab557fe5b90600052602060002001548152602001908152602001600020905060038460ff1610612b0e576040805162461bcd60e51b8152602060048201526003602482015262213c3360e81b604482015290519081900360640190fd5b60008460ff166002811115612b1f57fe5b905081600a0154612b2e61138b565b1015612b6b576040805162461bcd60e51b815260206004820152600760248201526670656e64696e6760c81b604482015290519081900360640190fd5b612b7882600a0154612394565b15612bb4576040805162461bcd60e51b8152602060048201526007602482015266195e1c1a5c995960ca1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600f8301602052604081205460ff166002811115612bdd57fe5b14612c17576040805162461bcd60e51b81526020600482015260056024820152641d9bdd195960da1b604482015290519081900360640190fd5b6001816002811115612c2557fe5b1480612c3c57506002816002811115612c3a57fe5b145b612c78576040805162461bcd60e51b8152602060048201526008602482015267215965737c7c4e6f60c01b604482015290519081900360640190fd5b6001600160a01b0384166000908152600f830160205260409020805482919060ff19166001836002811115612ca957fe5b02179055506001816002811115612cbc57fe5b1415612d0c576001830154600b8301805490910190556003830154861115612ce657600383018690555b81600d0154612cf36115b3565b1115612d0757612d016115b3565b600d8301555b612d31565b6002816002811115612d1a57fe5b1415612d31576001830154600c8301805490910190555b836001600160a01b0316336001600160a01b0316877f804f03797630bf8b8a46b9371608abbf7d78a20df720e477bab641957ca68a2060148a81548110612d7457fe5b906000526020600020015489604051808381526020018260ff1660ff1681526020019250505060405180910390a4505050505050565b600d5481565b6014546000908210612df5576040805162461bcd60e51b8152602060048201526009602482015268085c1c9bdc1bdcd85b60ba1b604482015290519081900360640190fd5b6015600060148481548110612e0657fe5b90600052602060002001548152602001908152602001600020600501600160078110612e2e57fe5b602091828204019190069054906101000a900460ff1660ff166001149050919050565b60095460ff1615612e97576040805162461bcd60e51b815260206004820152600b60248201526a1a5b9a5d1a585b1a5e995960aa1b604482015290519081900360640190fd5b8b6001600160a01b03168d6001600160a01b03161415612efe576040805162461bcd60e51b815260206004820152601a60248201527f6465706f736974546f6b656e203d3d207374616b65546f6b656e000000000000604482015290519081900360640190fd5b898814612f52576040805162461bcd60e51b815260206004820152601a60248201527f73756d6d6f6e657220213d2073756d6d6f6e6572536861726573000000000000604482015290519081900360640190fd5b84861015612f915760405162461bcd60e51b8152600401808060200182810382526024815260200180615f686024913960400191505060405180910390fd5b60005b8a81101561303c57612fd38c8c83818110612fab57fe5b905060200201356001600160a01b03168b8b84818110612fc757fe5b90506020020135615747565b61300a8c8c83818110612fe257fe5b905060200201356001600160a01b03168b8b84818110612ffe57fe5b90506020020135615879565b6130318a8a8381811061301957fe5b90506020020135600b54614e1890919063ffffffff16565b600b55600101612f94565b506ec097ce7bc90715b34b9f1000000000600b541115613091576040805162461bcd60e51b815260206004820152600b60248201526a19dd5a5b19081b585e195960aa1b604482015290519081900360640190fd5b6001600160a01b038d166000818152601360205260408120805460ff191660019081179091556012805491820181559091527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34440180546001600160a01b0319169091179055861561311257600d8054600101905561311261dead8e896152e9565b8c600060016101000a8154816001600160a01b0302191690836001600160a01b031602179055508b600160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550856002819055508460038190555083600481905550826005819055508160068190555080600781905550426008819055506001600960006101000a81548160ff0219169083151502179055506131b46158e8565b50505050505050505050505050565b60006001600160a01b038316613209576040805162461bcd60e51b815260206004820152600660248201526510ba37b5b2b760d11b604482015290519081900360640190fd5b6001546001600160a01b038481169116141561326c576040805162461bcd60e51b815260206004820152601e60248201527f746f6b656e546f57686974656c697374203d3d207374616b65546f6b656e0000604482015290519081900360640190fd5b6001600160a01b03831660009081526013602052604090205460ff16156132c8576040805162461bcd60e51b815260206004820152600b60248201526a1dda1a5d195b1a5cdd195960aa1b604482015290519081900360640190fd5b60125461019011613312576040805162461bcd60e51b815260206004820152600f60248201526e1dda1a5d195b1a5cdd081b585e1959608a1b604482015290519081900360640190fd5b61331a615ce3565b600160808201526040805160208101909152600080825261334a918190819081908990829081908b908a90615347565b5050600a546000190192915050565b3360009081526018602052604081206002015461337c908363ffffffff614a2e16565b336000908152601860205260408082206002908101939093556001600160a01b0386168252902001546133b5908363ffffffff614e1816565b6001600160a01b038416600090815260186020908152604080832060020193909355338252600f905220546133f0908363ffffffff614a2e16565b336000908152600f6020526040808220929092556001600160a01b03851681522054613422908363ffffffff614e1816565b6001600160a01b0384166000818152600f6020908152604091829020939093558051858152905191923392600080516020615f488339815191529281900390910190a350600192915050565b60075481565b61347c615ce3565b600082815260156020526040808220815160e0810192839052926005909101916007918390855b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116134a3575094979650505050505050565b60045481565b60005460ff16613527576040805162461bcd60e51b815260206004820152601f6024820152600080516020615f08833981519152604482015290519081900360640190fd5b6000805460ff1916905560015461354f906001600160a01b031633308463ffffffff6156d016565b33600090815260186020526040902054600160a01b900460ff16600114156135ac5733600090815260186020526040902060010154613594908263ffffffff614e1816565b336000908152601860205260409020600101556135b6565b6135b63382615747565b6135c03382615879565b600b546135d3908263ffffffff614e1816565b600b8190556ec097ce7bc90715b34b9f10000000001015613629576040805162461bcd60e51b815260206004820152600b60248201526a19dd5a5b19081b585e195960aa1b604482015290519081900360640190fd5b506000805460ff19166001179055565b60005461010090046001600160a01b031681565b600a5481565b6001600160a01b03918216600090815260106020908152604080832093909416825291909152205490565b60005460ff166136c3576040805162461bcd60e51b815260206004820152601f6024820152600080516020615f08833981519152604482015290519081900360640190fd5b6000805460ff19168155338152601960209081526040808320546001600160a01b031683526018909152902060010154613730576040805162461bcd60e51b81526020600482015260096024820152682164656c656761746560b81b604482015290519081900360640190fd5b6001600160a01b03811660009081526018602052604090206004810154613788576040805162461bcd60e51b8152602060048201526007602482015266085a985a5b195960ca1b604482015290519081900360640190fd5b60008160020154116137c9576040805162461bcd60e51b8152602060048201526005602482015264085b1bdbdd60da1b604482015290519081900360640190fd5b6137d68160030154612db0565b6138115760405162461bcd60e51b8152600401808060200182810382526041815260200180615ec76041913960600191505060405180910390fd5b6114f38260008360020154614b34565b60005460ff16613866576040805162461bcd60e51b815260206004820152601f6024820152600080516020615f08833981519152604482015290519081900360640190fd5b6000805460ff19168155818152601560205260409020600581015460ff16156138c2576040805162461bcd60e51b81526020600482015260096024820152681cdc1bdb9cdbdc995960ba1b604482015290519081900360640190fd5b60058101546301000000900460ff161561390f576040805162461bcd60e51b815260206004820152600960248201526818d85b98d95b1b195960ba1b604482015290519081900360640190fd5b60018101546001600160a01b0316331461395c576040805162461bcd60e51b815260206004820152600960248201526810b83937b837b9b2b960b91b604482015290519081900360640190fd5b60058101805463ff0000001916630100000017905560018101546003820154600983015461399c9261deaf926001600160a01b03918216929116906158f7565b60408051338152905183917fc215fed6680bb02d323dc3f8b8f85241572607538426059c9232601bd293c3be919081900360200190a250506000805460ff19166001179055565b60166020526000908152604090205460ff1681565b60005460ff16613a3d576040805162461bcd60e51b815260206004820152601f6024820152600080516020615f08833981519152604482015290519081900360640190fd5b6000805460ff19169055613a5081614e2a565b600060148281548110613a5f57fe5b6000918252602080832091909101548083526015909152604090912060058101549192509065010000000000900460ff16600114613acc576040805162461bcd60e51b8152602060048201526005602482015264216b69636b60d81b604482015290519081900360640190fd5b60058101805461ff0019166101001790556000613ae8846150f5565b90508015613b785760058201805462ff000019166201000017905581546001600160a01b031660009081526018602052604090206004810185905560018101546002820154613b3691614e18565b60028201556001810154600b54613b529163ffffffff614a2e16565b600b556001810154600c54613b6c9163ffffffff614e1816565b600c5560006001909101555b81546001600160a01b039081166000908152601760205260409020805460ff191690556002830154613baa9116615298565b6040805182151581529051849186917f0e347d00d3e9e6cdff9e6c09092c9ff1bd448f9b3dfb7091b30939ec5e7a3c739181900360200190a350506000805460ff191660011790555050565b60005460ff16613c3b576040805162461bcd60e51b815260206004820152601f6024820152600080516020615f08833981519152604482015290519081900360640190fd5b6000805460ff19169055613c4e81614e2a565b600060148281548110613c5d57fe5b60009182526020808320919091015480835260159091526040909120600581015491925090600160201b900460ff16158015613ca75750600581015465010000000000900460ff16155b8015613cc2575060058101546601000000000000900460ff16155b613cff576040805162461bcd60e51b8152602060048201526009602482015268085cdd185b99185c9960ba1b604482015290519081900360640190fd5b60058101805461ff0019166101001790556000613d1b846150f5565b90506ec097ce7bc90715b34b9f1000000000613d518360070154613d458560060154613d456115b3565b9063ffffffff614e1816565b1115613d5b575060005b60048201546001600160a01b03166000908152600080516020615f28833981519152602052604090205460088301541115613d94575060005b60008260090154118015613dcf575060038201546001600160a01b03166000908152600080516020615f288339815191526020526040902054155b8015613dde575060c8600d5410155b15613de7575060005b80156140295760058201805462ff000019166201000017905581546001600160a01b0316600090815260186020526040902054600160a01b900460ff1660011415613ec557600682015482546001600160a01b0316600090815260186020526040902060010154613e5d9163ffffffff614e1816565b82546001600160a01b03908116600090815260186020526040808220600101939093556007850154855490921681529190912060020154613ea39163ffffffff614e1816565b82546001600160a01b0316600090815260186020526040902060020155613edf565b81546006830154613edf916001600160a01b031690615747565b815460078301546006840154613f0e926001600160a01b031691613f09919063ffffffff614e1816565b615879565b6006820154600b54613f259163ffffffff614e1816565b600b556007820154600c54613f3f9163ffffffff614e1816565b600c5560038201546001600160a01b03166000908152600080516020615f288339815191526020526040902054158015613f7d575060008260090154115b15613f8c57600d805460010190555b60038201546009830154613fb19161deaf9161dead916001600160a01b0316906158f7565b815460048301546008840154613fd99261dead926001600160a01b03918216929116906158f7565b60048201546001600160a01b03166000908152600080516020615f288339815191526020526040902054158015614014575060008260080154115b1561402457600d80546000190190555b614054565b6001820154600383015460098401546140549261deaf926001600160a01b03918216929116906158f7565b600282015461406b906001600160a01b0316615298565b6040805182151581529051849186917f86f74240ecee9e4230d26ff92e17fee978460d9c0f78f5c88b2864c9e7a494279181900360200190a350506000805460ff191660011790555050565b61deaf81565b6000805460ff16614103576040805162461bcd60e51b815260206004820152601f6024820152600080516020615f08833981519152604482015290519081900360640190fd5b6000805460ff191690556ec097ce7bc90715b34b9f100000000061412d898963ffffffff614e1816565b111561416e576040805162461bcd60e51b815260206004820152600b60248201526a19dd5a5b19081b585e195960aa1b604482015290519081900360640190fd5b6001600160a01b03851660009081526013602052604090205460ff166141db576040805162461bcd60e51b815260206004820152601960248201527f74726962757465546f6b656e20213d2077686974656c69737400000000000000604482015290519081900360640190fd5b6001600160a01b03831660009081526013602052604090205460ff16614248576040805162461bcd60e51b815260206004820152601960248201527f7061796d656e74546f6b656e20213d2077686974656c69737400000000000000604482015290519081900360640190fd5b6001600160a01b03891661dead1480159061426e57506001600160a01b03891661deaf14155b801561428557506001600160a01b03891661deed14155b6142cf576040805162461bcd60e51b81526020600482015260166024820152756170706c6963616e7420756e72657365727661626c6560501b604482015290519081900360640190fd5b6001600160a01b03891660009081526018602052604090206004015415614330576040805162461bcd60e51b815260206004820152601060248201526f185c1c1b1a58d85b9d081a985a5b195960821b604482015290519081900360640190fd5b60008611801561436357506001600160a01b0385166000908152600080516020615f288339815191526020526040902054155b156143b15760c8600d54106143b1576040805162461bcd60e51b815260206004820152600f60248201526e19dd5a5b1918985b9ac81b585e1959608a1b604482015290519081900360640190fd5b6001600160a01b038516735b160edba6119828c5b065804e86111921323f9c1480156143dd5750600034115b156145af5785341461441f576040805162461bcd60e51b815260206004808301919091526024820152630428aa8960e31b604482015290519081900360640190fd5b735b160edba6119828c5b065804e86111921323f9c6001600160a01b031663d0e30db06040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561446e57600080fd5b505af1158015614482573d6000803e3d6000fd5b505060405160009250735b160edba6119828c5b065804e86111921323f9c915034908381818185875af1925050503d80600081146144dc576040519150601f19603f3d011682016040523d82523d6000602084013e6144e1565b606091505b5050905080614523576040805162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015290519081900360640190fd5b6040805163a9059cbb60e01b81523060048201523460248201529051735b160edba6119828c5b065804e86111921323f9c9163a9059cbb9160448083019260209291908290030181600087803b15801561457c57600080fd5b505af1158015614590573d6000803e3d6000fd5b505050506040513d60208110156145a657600080fd5b506145ca915050565b6145ca6001600160a01b03861633308963ffffffff6156d016565b6145d761deaf86886152e9565b6145df615ce3565b6146008a8a8a8a8a8a8a8a8960405180602001604052806000815250615347565b5050600a54600019016000805460ff1916600117905598975050505050505050565b735b160edba6119828c5b065804e86111921323f9c81565b61dead81565b6000805460609060ff16614689576040805162461bcd60e51b815260206004820152601f6024820152600080516020615f08833981519152604482015290519081900360640190fd5b6000805460ff1916905561469c83614e2a565b6000601484815481106146ab57fe5b600091825260208083209190910154808352600e825260408084206015909352909220600581015492935090916601000000000000900460ff16600114614723576040805162461bcd60e51b815260206004820152600760248201526610b0b1ba34b7b760c91b604482015290519081900360640190fd5b60058101805461ff001916610100179055600061473f876150f5565b60015460048401549192506001600160a01b0391821691161480156147dd5750600154604080516370a0823160e01b815230600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b1580156147aa57600080fd5b505afa1580156147be573d6000803e3d6000fd5b505050506040513d60208110156147d457600080fd5b50516008830154115b156147e6575060005b60048201546001600160a01b031660009081526013602052604090205460ff16801561483e575060048201546001600160a01b03166000908152600080516020615f2883398151915260205260409020546008830154115b15614847575060005b4782600901541115614857575060005b80156149dc5760058201805462ff00001916620100001790558154600983015460405185546000936060936001600160a01b03909116929091889190819083906002600019600183161561010002019091160480156148ed5780601f106148cb5761010080835404028352918201916148ed565b820191906000526020600020905b8154815290600101906020018083116148d9575b505091505060006040518083038185875af1925050503d806000811461492f576040519150601f19603f3d011682016040523d82523d6000602084013e614934565b606091505b5060048601546001600160a01b0316600090815260136020526040902054919350915060ff16156149cd57600484015460088501546149829161dead916001600160a01b039091169061590d565b60048401546001600160a01b03166000908152600080516020615f2883398151915260205260409020541580156149bd575060008460080154115b156149cd57600d80546000190190555b9096509450614a1a9350505050565b6040805182151581529051859189917f225ab65268ea3d2f5b1ed97e7d032147f17bba561ef01b819bfe3832bc05b0339181900360200190a3505050505b6000805460ff191660011790559092909150565b600082821115614a3d57600080fd5b50900390565b6000808211614a5157600080fd5b6000828481614a5c57fe5b04949350505050565b3360009081526011602090815260408083206001600160a01b0386168452909152902054811115614ac8576040805162461bcd60e51b81526020600482015260086024820152672162616c616e636560c01b604482015290519081900360640190fd5b614ae26001600160a01b038316338363ffffffff61596d16565b614aed33838361590d565b604080516001600160a01b038416815260208101839052815133927f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb928290030190a25050565b6000614b3e6115b3565b6001600160a01b0385166000908152601860205260409020600181015491925090841115614b9d576040805162461bcd60e51b81526020600482015260076024820152662173686172657360c81b604482015290519081900360640190fd5b8281600201541015614bde576040805162461bcd60e51b8152602060048201526005602482015264085b1bdbdd60da1b604482015290519081900360640190fd5b614beb8160030154612db0565b614c265760405162461bcd60e51b8152600401808060200182810382526041815260200180615ec76041913960600191505060405180910390fd5b6000614c38858563ffffffff614e1816565b9050614c4486826159c4565b6001820154614c59908663ffffffff614a2e16565b60018301556002820154614c73908563ffffffff614a2e16565b6002830155600b54614c8b908663ffffffff614a2e16565b600b55600c54614ca1908563ffffffff614a2e16565b600c5560005b601254811015614dcc5761dead6000908152601160205260128054614d0f91600080516020615f288339815191529184919086908110614ce357fe5b60009182526020808320909101546001600160a01b031683528201929092526040019020548487615a32565b90508015614dc35761dead60009081526011602052601280548392600080516020615f2883398151915292909186908110614d4657fe5b60009182526020808320909101546001600160a01b0390811684528382019490945260409283018220805495909503909455918b1682526011909252908120601280548493919086908110614d9757fe5b60009182526020808320909101546001600160a01b031683528201929092526040019020805490910190555b50600101614ca7565b50604080518681526020810186905281516001600160a01b038916927fcad1a1c68982832d9abc314de8a1e5d5e8c81b0588961e360766736d10c3be1a928290030190a2505050505050565b60008282018381101561176357600080fd5b6014548110614e6c576040805162461bcd60e51b8152602060048201526009602482015268085c1c9bdc1bdcd85b60ba1b604482015290519081900360640190fd5b614e74615d01565b6015600060148481548110614e8557fe5b6000918252602080832091909101548352828101939093526040918201812082516101e08101845281546001600160a01b0390811682526001830154811695820195909552600282015485168185015260038201548516606082015260048201549094166080850152825160e0810193849052909260a085019260058501916007918390855b825461010083900a900460ff16815260206001928301818104948501949093039092029101808411614f0b5790505050505050815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d8201548152602001600e820154815250509050614fbe600654613d45600554846101400151614e1890919063ffffffff16565b614fc661138b565b1015615002576040805162461bcd60e51b815260206004820152600660248201526521726561647960d01b604482015290519081900360640190fd5b60a08101516020015160ff161561504c576040805162461bcd60e51b81526020600482015260096024820152681c1c9bd8d95cdcd95960ba1b604482015290519081900360640190fd5b8115806150ad5750601560006014600185038154811061506857fe5b9060005260206000200154815260200190815260200160002060050160016007811061509057fe5b602091828204019190069054906101000a900460ff1660ff166001145b6150f1576040805162461bcd60e51b815260206004820152601060248201526f1c1c9a5bdc88085c1c9bd8d95cdcd95960821b604482015290519081900360640190fd5b5050565b60006150ff615d01565b601560006014858154811061511057fe5b6000918252602080832091909101548352828101939093526040918201812082516101e08101845281546001600160a01b0390811682526001830154811695820195909552600282015485168185015260038201548516606082015260048201549094166080850152825160e0810193849052909260a085019260058501916007918390855b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116151965790505050505050815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d8201548152602001600e820154815250509050806101800151816101600151111561524057600191505b806101a001516152606007546152546115b3565b9063ffffffff615a8616565b101561526b57600091505b80516001600160a01b03166000908152601860205260409020600401541561529257600091505b50919050565b6152bd61deaf33600060019054906101000a90046001600160a01b03166003546158f7565b6152e661deaf82600060019054906101000a90046001600160a01b0316600354600254036158f7565b50565b6001600160a01b0392831660009081526011602090815260408083209490951682529283528381208054830190557f57db7c30545d4d48d1c5d59f308748a14de480f9ecd985c3dc261a416ac0c62390925291902080549091019055565b61534f615d01565b604051806101e001604052808c6001600160a01b03168152602001336001600160a01b0316815260200160006001600160a01b03168152602001886001600160a01b03168152602001866001600160a01b031681526020018481526020018b81526020018a8152602001878152602001898152602001600081526020016000815260200160008152602001600081526020018581525090508060a001516006600781106153f857fe5b602002015160ff166001141561542c57600a546000908152600e60209081526040909120835161542a92850190615d81565b505b600a54600090815260156020908152604091829020835181546001600160a01b03199081166001600160a01b03928316178355928501516001830180548516918316919091179055928401516002820180548416918516919091179055606084015160038201805484169185169190911790556080840151600482018054909316931692909217905560a08201518291906154cd9060058301906007615dff565b5060c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e0155905050600060196000336001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03169050806001600160a01b0316336001600160a01b03168d6001600160a01b03167f698b6b5a7173505e04fab049527190ad00a5d40a2dfb3d6e811f0e9c47c00c058e8e8e8e8e8e8e8e8e600a54604051808b81526020018a8152602001898152602001886001600160a01b03166001600160a01b03168152602001878152602001866001600160a01b03166001600160a01b0316815260200185815260200184600760200280838360005b83811015615630578181015183820152602001615618565b5050505090500180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561567657818101518382015260200161565e565b50505050905090810190601f1680156156a35780820380516001836020036101000a031916815260200191505b509b50505050505050505050505060405180910390a45050600a8054600101905550505050505050505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b17905261572a908590615aad565b50505050565b6000818310156157405781611763565b5090919050565b6001600160a01b03808316600090815260196020908152604080832054909316825260189052205460ff600160a01b90910416600114156157cf576001600160a01b0380831660009081526019602090815260408083205490931680835283832080546001600160a01b03199081168317909155601890925292909120805490911690911790555b6040805160c0810182526001600160a01b03938416808252600160208084018281528486019687526000606086018181526080870182815260a088018381528784526018865289842098518954955160ff16600160a01b0260ff60a01b1991909d166001600160a01b031996871617169b909b1788559851948701949094559251600286015595516003850155955160049093019290925560199094522080549091169091179055565b6001600160a01b0382166000908152600f60205260409020546158a2908263ffffffff614e1816565b6001600160a01b0383166000818152600f60209081526040808320949094558351858152935192939192600080516020615f488339815191529281900390910190a35050565b6000805460ff19166001179055565b61590284838361590d565b61572a8383836152e9565b6001600160a01b039283166000908152601160209081526040808320949095168252928352838120805483900390557f57db7c30545d4d48d1c5d59f308748a14de480f9ecd985c3dc261a416ac0c6239092529190208054919091039055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526159bf908490615aad565b505050565b6001600160a01b0382166000908152600f60205260409020546159ed908263ffffffff614a2e16565b6001600160a01b0383166000818152600f6020908152604080832094909455835185815293519193600080516020615f48833981519152929081900390910190a35050565b600081615a3e57600080fd5b83615a4b57506000611763565b83830283858281615a5857fe5b041415615a7157828181615a6857fe5b04915050611763565b83838681615a7b57fe5b040295945050505050565b600082615a955750600061135f565b82820282848281615aa257fe5b041461176357600080fd5b615abf826001600160a01b0316615c65565b615b10576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310615b4e5780518252601f199092019160209182019101615b2f565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114615bb0576040519150601f19603f3d011682016040523d82523d6000602084013e615bb5565b606091505b509150915081615c0c576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b80511561572a57808060200190516020811015615c2857600080fd5b505161572a5760405162461bcd60e51b815260040180806020018281038252602a815260200180615f8c602a913960400191505060405180910390fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590615c9957508115155b949350505050565b6040518060c0016040528060006001600160a01b03168152602001600060ff168152602001600081526020016000815260200160008152602001600081525090565b6040518060e001604052806007906020820280388339509192915050565b604080516101e08101825260008082526020820181905291810182905260608101829052608081019190915260a08101615d39615ce3565b81526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600080191681525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615dc257805160ff1916838001178555615def565b82800160010185558215615def579182015b82811115615def578251825591602001919060010190615dd4565b50615dfb929150615e8e565b5090565b600183019183908215615e825791602002820160005b83821115615e5357835183826101000a81548160ff021916908360ff1602179055509260200192600101602081600001049283019260010302615e15565b8015615e805782816101000a81549060ff0219169055600101602081600001049283019260010302615e53565b505b50615dfb929150615ea8565b6113b791905b80821115615dfb5760008155600101615e94565b6113b791905b80821115615dfb57805460ff19168155600101615eae56fe21726167657175697420756e74696c206869676865737420696e6465782070726f706f73616c206d656d62657220766f746564205945532070726f6365737365735265656e7472616e637947756172643a207265656e7472616e742063616c6c0097847ee99463795296047093514439c3127772df3715e628aa85601cf8541716ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f70726f63657373696e67526577617264203e205f70726f706f73616c4465706f7369745361666545524332303a206572633230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a723158200b8abae2f67a1caa7965f7b3e41f771d7836833f64c89578691607576089312164736f6c63430005110032