Feature Tip: Add private address tag to any address under My Name Tag !
ERC-721
Overview
Max Total Supply
0 sFP
Holders
89
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
9 sFPLoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
Staking
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; /** _______ _______ _______ _ _ _______ _ _______ _ _ _______ ( ____ \( ____ )( ___ )( ( /|| \ /\( ____ \( ( /| ( ____ )|\ /|( ( /|| \ /\( ____ \ | ( \/| ( )|| ( ) || \ ( || \ / /| ( \/| \ ( | | ( )|| ) ( || \ ( || \ / /| ( \/ | (__ | (____)|| (___) || \ | || (_/ / | (__ | \ | | | (____)|| | | || \ | || (_/ / | (_____ | __) | __)| ___ || (\ \) || _ ( | __) | (\ \) | | _____)| | | || (\ \) || _ ( (_____ ) | ( | (\ ( | ( ) || | \ || ( \ \ | ( | | \ | | ( | | | || | \ || ( \ \ ) | | ) | ) \ \__| ) ( || ) \ || / \ \| (____/\| ) \ | | ) | (___) || ) \ || / \ \/\____) | |/ |/ \__/|/ \||/ )_)|_/ \/(_______/|/ )_) |/ (_______)|/ )_)|_/ \/\_______) */ import "solmate/tokens/ERC721.sol"; import "solmate/utils/LibString.sol"; import "./utils/SafeCast.sol"; import "./utils/Refundable.sol"; import "./utils/Admin.sol"; import "./interfaces/IERC721.sol"; import "./interfaces/IStaking.sol"; import "./interfaces/IGovernance.sol"; import "./interfaces/IExecutor.sol"; /// @title FrankenDAO Staking /// @author Zach Obront & Zakk Fleischmann /// @notice Users stake FrankenPunks & FrankenMonsters and get ERC721s in return /// @notice These ERC721s are used for voting power for FrankenDAO governance contract Staking is IStaking, ERC721, Admin, Refundable { using LibString for uint256; /// @notice The original ERC721 FrankenPunks contract IERC721 frankenpunks; /// @notice The original ERC721 FrankenMonsters contract IERC721 frankenmonsters; /// @notice The DAO governance contract (where voting occurs) IGovernance governance; /// @notice Base votes for holding a Frankenpunk token uint constant public BASE_VOTES = 20; /// @return maxStakeBonusTime The maxmimum time you will earn bonus votes for staking for /// @return maxStakeBonusAmount The amount of bonus votes you'll get if you stake for the max time StakingSettings public stakingSettings; /// @notice Multipliers (expressed as percentage) for calculating community voting power from user stats /// @return votes The multiplier for extra voting power earned per DAO vote cast /// @return proposalsCreated The multiplier for extra voting power earned per proposal created /// @return proposalsPassed The multiplier for extra voting power earned per proposal passed CommunityPowerMultipliers public communityPowerMultipliers; /// @notice Constant to calculate voting power based on multipliers above uint constant PERCENT = 100; /// @notice Are refunds turned on for staking? bool public stakingRefund; /// @notice The last timestamp at which a user used their staking refund mapping(address => uint256) public lastStakingRefund; /// @notice Are refunds turned on for delegating? bool public delegatingRefund; /// @notice The last timestamp at which a user used their delegating refund mapping(address => uint256) public lastDelegatingRefund; /// @notice How often can a user use their refund? uint256 public refundCooldown; /// @notice Is staking currently paused or open? bool public paused; /// @notice The staked time bonus for each staked token (tokenId => bonus votes) /// @dev This needs to be tracked because users will select how much time to lock for, so bonus is variable mapping(uint => uint) stakedTimeBonus; /// @notice The allowed unlock time for each staked token (tokenId => timestamp) /// @dev This remains at 0 if tokens are staked without locking mapping(uint => uint) public unlockTime; /// @notice Addresses that each user delegates votes to /// @dev This should only be accessed via getDelegate() function, which overrides address(0) with self mapping(address => address) private _delegates; /// @notice The total voting power earned by each user's staked tokens /// @dev In other words, this is the amount of voting power that would move if they redelegated /// @dev They don't necessarily have this many votes, because they may have delegated them mapping(address => uint) public votesFromOwnedTokens; /// @notice The total voting power each user has, after adjusting for delegation /// @dev This represents the actual token voting power of each user mapping(address => uint) public tokenVotingPower; /// @notice The total token voting power of the system uint totalTokenVotingPower; /// @notice Base token URI for the ERC721s representing the staked position string public baseTokenURI; /// @notice Contract URI for marketplace metadata string public contractURI; /// @notice The total supply of staked frankenpunks uint128 public stakedFrankenPunks; /// @notice The total supply of staked frankenmonsters uint128 public stakedFrankenMonsters; /// @notice Bitmaps representing whether each FrankenPunk has a sufficient "evil score" for a bonus. /// @dev 40 words * 256 bits = 10,240 bits, which is sufficient to hold values for 10k FrankenPunks uint[40] EVIL_BITMAPS = [ 883425322698150530263834307704826599123904599330160270537777278655401984, // 0 14488147225470816109160058996749687396265978336526515174837584423109802852352, // 1 38566513062215815139428642218823858442255833421860837338906624, // 2 105312291668557186697918027683670432324476705909712387428719788032, // 3 14474011154664524427946373126085988481660077311200856629730921422678596263936, // 4 3618502788692465607655909614339766499850336868450542774889103259212619972609, // 5 441711772776714745308416192199486840791445460561420424832198410539892736, // 6 6901746759773641161995257390185172072446268286034776944761674561224712, // 7 883423532414903565819785182543377466397133986207912949084155019599544320, // 8 14474011155086185177904289442148664541270784730116237084843513087002589265920, // 9 107839786668798718607898896909541540930351713584408019687362806153216, // 10 904625700641838402593673198335004289144275540958779302917589231213362556944, // 11 220859253090631447287862539909960206022391538433640386622889848771706880, // 12 1393839110204029063653915313866451565150208, // 13 784637716923340670665773318162647287385528792673206407169, // 14 107839786668602559178668060353525740564723109496935832847049186869248, // 15 51422802054004612152481822571560984362335820545231474237898784, // 16 6582018229284824169333500576582381960460086447259084614308728832, // 17 365732221255902219560809532335122355265736818688, // 18 445162639419413381705829464770174011933371831432841644599383048677490688, // 19 6935446280124502090171244984389489167294584349705235353545399909482504, // 20 452312848583266388373372050675839373643513806386188657447441353755011973120, // 21 51422023594160337932957247212003666383914706547133656225284128, // 22 2923003274661805998666646494941077336069228208128, // 23 215679573337205118357336126271343355406346657833909405071980653182976, // 24 26959946667150639794667015087041235820865508444839585222888876146720, // 25 3731581108651760187459529718884681603688140590625042088037390915407571845120, // 26 33372889303170710042455474178259135664197736114694375141005066752, // 27 28948022309329151699928351061631107912622119818910282538292189430411643863044, // 28 55214023430470347690952963241066788995217469738067023806554216123598848, // 29 55213971185700649632772712790212230970723509677757939395778641765335297, // 30 50216813883139118038214077107913983031541181002059654103040, // 31 45671926166601100787582220677640905906662146176, // 32 431359146674410260659915067596052074490887103277477952745659311325184, // 33 6741683593362397442763285474207733540211166501858783908538903166976, // 34 421249166674235107246797774824181756792478284093098635821743865856, // 35 53919893334350319447007114026840783409769671338355940037889148190720, // 36 401740641047276407850947922339698016834483256774579142524928, // 37 220855883097304318299647574273628650268020954052697685772267193358090240, // 38 0 // 39 ]; ///////////////////////////////// /////////// MODIFIERS /////////// ///////////////////////////////// /// @dev To avoid needing to checkpoint voting power, tokens are locked while users have active votes cast or proposals open /// @dev If a user creates a proposal or casts a vote, this modifier prevents them from unstaking or delegating /// @dev Once the proposal is completed, it is removed from getActiveProposals and their tokens are unlocked modifier lockedWhileVotesCast() { uint[] memory activeProposals = governance.getActiveProposals(); for (uint i = 0; i < activeProposals.length; i++) { if (governance.getReceipt(activeProposals[i], getDelegate(msg.sender)).hasVoted) revert TokenLocked(); (, address proposer,) = governance.getProposalData(activeProposals[i]); if (proposer == getDelegate(msg.sender)) revert TokenLocked(); } _; } ///////////////////////////////// ////////// CONSTRUCTOR ////////// ///////////////////////////////// /// @param _frankenpunks The address of the original ERC721 FrankenPunks contract /// @param _frankenmonsters The address of the original ERC721 FrankenMonsters contract /// @param _governance The address of the DAO governance contract /// @param _executor The address of the DAO executor contract /// @param _founders The address of the founder multisig for restricted functions /// @param _council The address of the council multisig for restricted functions /// @param _baseTokenURI Token URI for the Staking NFT contract /// @param _contractURI URI for the contract metadata constructor( address _frankenpunks, address _frankenmonsters, address _governance, address _executor, address _founders, address _council, string memory _baseTokenURI, string memory _contractURI ) ERC721("Staked FrankenPunks", "sFP") { frankenpunks = IERC721(_frankenpunks); frankenmonsters = IERC721(_frankenmonsters); governance = IGovernance( _governance ); executor = IExecutor(_executor); founders = _founders; council = _council; // Staking bonus increases linearly from 0 to 20 votes over 4 weeks stakingSettings = StakingSettings({ maxStakeBonusTime: uint128(4 weeks), maxStakeBonusAmount: uint128(20) }); // Users get a bonus 1 vote per vote, 2 votes per proposal created, and 2 votes per proposal passed communityPowerMultipliers = CommunityPowerMultipliers({ votes: uint64(100), proposalsCreated: uint64(200), proposalsPassed: uint64(200) }); // Refunds are initially turned on with 1 day cooldown. delegatingRefund = true; stakingRefund = true; refundCooldown = 1 days; // Set the base token URI. baseTokenURI = _baseTokenURI; // Set the contract URI. contractURI = _contractURI; } ///////////////////////////////// // OVERRIDE & REVERT TRANSFERS // ///////////////////////////////// /// @notice Transferring of staked tokens is prohibited, so all transfers will revert /// @dev This will also block safeTransferFrom, because of solmate's implementation function transferFrom(address, address, uint256) public pure override(ERC721) { revert StakedTokensCannotBeTransferred(); } ///////////////////////////////// /////// TOKEN URI FUNCTIONS ///// ///////////////////////////////// /// @notice Token URI to find metadata for each tokenId /// @dev The metadata will be a variation on the metadata of the underlying token function tokenURI(uint256 _tokenId) public view virtual override(ERC721) returns (string memory) { if (ownerOf(_tokenId) == address(0)) revert NonExistentToken(); string memory baseURI = baseTokenURI; return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, _tokenId.toString(), ".json")) : ""; } ///////////////////////////////// /////// DELEGATION LOGIC //////// ///////////////////////////////// /// @notice Return the address that a given address delegates to /// @param _delegator The address to check /// @return The address that the delegator has delegated to /// @dev If the delegator has not delegated, this function will return their own address function getDelegate(address _delegator) public view returns (address) { address current = _delegates[_delegator]; return current == address(0) ? _delegator : current; } /// @notice Delegate votes to another address /// @param _delegatee The address you wish to delegate to /// @dev Refunds gas if delegatingRefund is true and hasn't been used by this user in the past 24 hours function delegate(address _delegatee) public { if (_delegatee == address(0)) _delegatee = msg.sender; // Refunds gas if delegatingRefund is true and hasn't been used by this user in the past 24 hours if (delegatingRefund && lastDelegatingRefund[msg.sender] + refundCooldown <= block.timestamp) { uint256 startGas = gasleft(); _delegate(msg.sender, _delegatee); lastDelegatingRefund[msg.sender] = block.timestamp; _refundGas(startGas); } else { _delegate(msg.sender, _delegatee); } } /// @notice Delegates votes from the sender to the delegatee /// @param _delegator The address of the user who called the function and owns the votes being delegated /// @param _delegatee The address of the user who will receive the votes function _delegate(address _delegator, address _delegatee) internal lockedWhileVotesCast { address currentDelegate = getDelegate(_delegator); // If currentDelegate == _delegatee, then this function will not do anything if (currentDelegate == _delegatee) revert InvalidDelegation(); // Set the _delegates mapping to the correct address, subbing in address(0) if they are delegating to themselves _delegates[_delegator] = _delegatee == _delegator ? address(0) : _delegatee; uint amount = votesFromOwnedTokens[_delegator]; // If the delegator has no votes, then this function will not do anything // This is explicitly blocked to ensure that users without votes cannot abuse the refund mechanism if (amount == 0) revert InvalidDelegation(); // Move the votes from the currentDelegate to the new delegatee // Neither of these addresses can be address(0) because: // - currentDelegate calls getDelegate(), which replaces address(0) with the delegator's address // - delegatee is changed to msg.sender in the external functions if address(0) is passed tokenVotingPower[currentDelegate] -= amount; tokenVotingPower[_delegatee] += amount; // If this moved the current delegate down to zero voting power, then remove their community VP from the totals if (tokenVotingPower[currentDelegate] == 0) { _updateTotalCommunityVotingPower(currentDelegate, false); } // If the new delegate previously had zero voting power, then add their community VP to the totals if (tokenVotingPower[_delegatee] == amount) { _updateTotalCommunityVotingPower(_delegatee, true); } emit DelegateChanged(_delegator, currentDelegate, _delegatee); } /// @notice Updates the total community voting power totals /// @param _delegator The address of the user who called the function and owns the votes being delegated /// @param _increase Should we be increasing or decreasing the totals? /// @dev This function is called by _delegate, _stake, and _unstake function _updateTotalCommunityVotingPower(address _delegator, bool _increase) internal { (uint64 votes, uint64 proposalsCreated, uint64 proposalsPassed) = governance.userCommunityScoreData(_delegator); (uint64 totalVotes, uint64 totalProposalsCreated, uint64 totalProposalsPassed) = governance.totalCommunityScoreData(); if (_increase) { governance.updateTotalCommunityScoreData(totalVotes + votes, totalProposalsCreated + proposalsCreated, totalProposalsPassed + proposalsPassed); } else { governance.updateTotalCommunityScoreData(totalVotes - votes, totalProposalsCreated - proposalsCreated, totalProposalsPassed - proposalsPassed); } } ///////////////////////////////// /// STAKE & UNSTAKE FUNCTIONS /// ///////////////////////////////// /// @notice Stake your tokens to get voting power /// @param _tokenIds An array of the id of the token you wish to stake /// @param _unlockTime The timestamp of the time your tokens will be unlocked /// @dev unlockTime can be set to 0 to stake without locking (and earn no extra staked time bonus) function stake(uint[] calldata _tokenIds, uint _unlockTime) public { // Refunds gas if stakingRefund is true and hasn't been used by this user in the past 24 hours if (stakingRefund && lastStakingRefund[msg.sender] + refundCooldown <= block.timestamp) { uint256 startGas = gasleft(); _stake(_tokenIds, _unlockTime); lastStakingRefund[msg.sender] = block.timestamp; _refundGas(startGas); } else { _stake(_tokenIds, _unlockTime); } } /// @notice Internal function to stake tokens and get voting power /// @param _tokenIds An array of the id of the tokens being staked /// @param _unlockTime The timestamp of when the tokens will be unlocked function _stake(uint[] calldata _tokenIds, uint _unlockTime) internal { if (paused) revert Paused(); if (_unlockTime > 0 && _unlockTime < block.timestamp) revert InvalidParameter(); uint maxStakeTime = stakingSettings.maxStakeBonusTime; if (_unlockTime > 0 && _unlockTime - block.timestamp > maxStakeTime) { _unlockTime = block.timestamp + maxStakeTime; } uint numTokens = _tokenIds.length; // This is required to ensure the gas refunds are not abused if (numTokens == 0) revert InvalidParameter(); uint newVotingPower; for (uint i = 0; i < numTokens; i++) { newVotingPower += _stakeToken(_tokenIds[i], _unlockTime); } votesFromOwnedTokens[msg.sender] += newVotingPower; tokenVotingPower[getDelegate(msg.sender)] += newVotingPower; totalTokenVotingPower += newVotingPower; // If the delegate (including self) had no tokenVotingPower before, they just unlocked their community voting power if (tokenVotingPower[getDelegate(msg.sender)] == newVotingPower) { // The delegate's community voting power is reactivated, so we add it to the total community voting power _updateTotalCommunityVotingPower(getDelegate(msg.sender), true); } } /// @notice Internal function to stake a single token and get voting power /// @param _tokenId The id of the token being staked /// @param _unlockTime The timestamp of when the token will be unlocked function _stakeToken(uint _tokenId, uint _unlockTime) internal returns (uint) { if (_unlockTime > 0) { unlockTime[_tokenId] = _unlockTime; uint fullStakedTimeBonus = ((_unlockTime - block.timestamp) * stakingSettings.maxStakeBonusAmount) / stakingSettings.maxStakeBonusTime; stakedTimeBonus[_tokenId] = _tokenId < 10000 ? fullStakedTimeBonus : fullStakedTimeBonus / 2; } // Transfer the underlying token from the owner to this contract IERC721 collection; if (_tokenId < 10000) { collection = frankenpunks; stakedFrankenPunks++; } else { collection = frankenmonsters; stakedFrankenMonsters++; } address owner = collection.ownerOf(_tokenId); if (msg.sender != owner) revert NotAuthorized(); collection.transferFrom(owner, address(this), _tokenId); // Mint the staker a new ERC721 token representing their staked token _mint(msg.sender, _tokenId); // Return the voting power for this token based on staked time bonus and evil score return getTokenVotingPower(_tokenId); } /// @notice Unstake your tokens and surrender voting power /// @param _tokenIds An array of the ids of the tokens you wish to unstake /// @param _to The address to send the underlying NFT to function unstake(uint[] calldata _tokenIds, address _to) public { _unstake(_tokenIds, _to); } /// @notice Internal function to unstake tokens and surrender voting power /// @param _tokenIds An array of the ids of the tokens being unstaked /// @param _to The address to send the underlying NFT to function _unstake(uint[] calldata _tokenIds, address _to) internal lockedWhileVotesCast { uint numTokens = _tokenIds.length; if (numTokens == 0) revert InvalidParameter(); uint lostVotingPower; for (uint i = 0; i < numTokens; i++) { lostVotingPower += _unstakeToken(_tokenIds[i], _to); } votesFromOwnedTokens[msg.sender] -= lostVotingPower; // Since the delegate currently has the voting power, it must be removed from their balance // If the user doesn't delegate, delegates(msg.sender) will return self tokenVotingPower[getDelegate(msg.sender)] -= lostVotingPower; totalTokenVotingPower -= lostVotingPower; // If this unstaking reduced the user or their delegate's tokenVotingPower to 0, then someone just lost their community voting power // First, check if the user is their own delegate if (msg.sender == getDelegate(msg.sender)) { // Did their tokenVotingPower just become 0? if (tokenVotingPower[msg.sender] == 0) { // If so, reduce the total voting power to capture this decrease in the user's community voting power _updateTotalCommunityVotingPower(msg.sender, false); } // If they aren't their own delegate... } else { // If their delegate's tokenVotingPower reaches 0, that means they were the final unstake and the delegate loses community voting power if (tokenVotingPower[getDelegate(msg.sender)] == 0) { // The delegate's community voting power is forfeited, so we adjust total community power balances down _updateTotalCommunityVotingPower(getDelegate(msg.sender), false); } } } /// @notice Internal function to unstake a single token and surrender voting power /// @param _tokenId The id of the token being unstaked /// @param _to The address to send the underlying NFT to function _unstakeToken(uint _tokenId, address _to) internal returns(uint) { address owner = ownerOf(_tokenId); if (msg.sender != owner) revert NotAuthorized(); if (unlockTime[_tokenId] > block.timestamp) revert TokenLocked(); // Transfer the underlying token from the owner to this contract IERC721 collection; if (_tokenId < 10000) { collection = frankenpunks; --stakedFrankenPunks; } else { collection = frankenmonsters; --stakedFrankenMonsters; } collection.safeTransferFrom(address(this), _to, _tokenId); // Voting power needs to be calculated before staked time bonus is zero'd out, as it uses this value uint lostVotingPower = getTokenVotingPower(_tokenId); _burn(_tokenId); if (unlockTime[_tokenId] > 0) { delete unlockTime[_tokenId]; delete stakedTimeBonus[_tokenId]; } return lostVotingPower; } ////////////////////////////////////////////// ///// VOTING POWER CALCULATION FUNCTIONS ///// ////////////////////////////////////////////// /// @notice Get the total voting power (token + community) for an account /// @param _account The address of the account to get voting power for /// @return The total voting power for the account /// @dev This is used by governance to calculate the voting power of an account function getVotes(address _account) public view returns (uint) { return tokenVotingPower[_account] + getCommunityVotingPower(_account); } /// @notice Get the voting power for a specific token when staking or unstaking /// @param _tokenId The id of the token to get voting power for /// @return The voting power for the token /// @dev Voting power is calculated as baseVotes + staking bonus (0 to max staking bonus) + evil bonus (0 or 10) function getTokenVotingPower(uint _tokenId) public override view returns (uint) { if (ownerOf(_tokenId) == address(0)) revert NonExistentToken(); // If tokenId < 10000, it's a FrankenPunk, so BASE_VOTES, otherwise, divide by 2 for monsters uint baseVotes = _tokenId < 10_000 ? BASE_VOTES : BASE_VOTES / 2; // evilBonus will return 0 for all FrankenMonsters, as they are not eligible for the evil bonus return baseVotes + stakedTimeBonus[_tokenId] + evilBonus(_tokenId); } /// @notice Get the community voting power for a given user /// @param _voter The address of the account to get community voting power for /// @return The community voting power the user currently has function getCommunityVotingPower(address _voter) public override view returns (uint) { uint64 votes; uint64 proposalsCreated; uint64 proposalsPassed; // We allow this function to be called with the max uint value to get the total community voting power if (_voter == address(type(uint160).max)) { (votes, proposalsCreated, proposalsPassed) = governance.totalCommunityScoreData(); } else { // This is only the case if they are delegated or unstaked, both of which should zero out the result if (tokenVotingPower[_voter] == 0) return 0; (votes, proposalsCreated, proposalsPassed) = governance.userCommunityScoreData(_voter); } CommunityPowerMultipliers memory cpMultipliers = communityPowerMultipliers; return ( (votes * cpMultipliers.votes) + (proposalsCreated * cpMultipliers.proposalsCreated) + (proposalsPassed * cpMultipliers.proposalsPassed) ) / PERCENT; } /// @notice Get the total voting power of the entire system /// @return The total votes in the system /// @dev This is used to calculate the quorum and proposal thresholds function getTotalVotingPower() public view returns (uint) { return totalTokenVotingPower + getCommunityVotingPower(address(type(uint160).max)); } function getStakedTokenSupplies() public view returns (uint128, uint128) { return (stakedFrankenPunks, stakedFrankenMonsters); } /// @notice Get the evil bonus for a given token /// @param _tokenId The id of the token to get the evil bonus for /// @return The evil bonus for the token /// @dev The evil bonus is 10 if the token is sufficiently evil, 0 otherwise function evilBonus(uint _tokenId) public view returns (uint) { if (_tokenId >= 10000) return 0; return (EVIL_BITMAPS[_tokenId >> 8] >> (255 - (_tokenId & 255)) & 1) * 10; } ///////////////////////////////// //////// OWNER OPERATIONS /////// ///////////////////////////////// /// @notice Set the max staking time needed to get the max bonus /// @param _newMaxStakeBonusTime The new max staking time /// @dev This function can only be called by the executor based on a governance proposal function changeStakeTime(uint128 _newMaxStakeBonusTime) external onlyExecutor { if (_newMaxStakeBonusTime == 0) revert InvalidParameter(); emit StakeTimeChanged(stakingSettings.maxStakeBonusTime = _newMaxStakeBonusTime); } /// @notice Set the max staking bonus earned if a token is staked for the max time /// @param _newMaxStakeBonusAmount The new max staking bonus /// @dev This function can only be called by the executor based on a governance proposal function changeStakeAmount(uint128 _newMaxStakeBonusAmount) external onlyExecutor { emit StakeAmountChanged(stakingSettings.maxStakeBonusAmount = _newMaxStakeBonusAmount); } /// @notice Set the community power multiplier for votes /// @param _votesMultiplier The multiplier applied to community voting power based on past votes /// @dev This function can only be called by the executor based on a governance proposal function setVotesMultiplier(uint64 _votesMultiplier) external onlyExecutor { emit VotesMultiplierChanged(communityPowerMultipliers.votes = _votesMultiplier); } /// @notice Set the community power multiplier for proposals created /// @param _proposalsCreatedMultiplier The multiplier applied to community voting power based on proposals created /// @dev This function can only be called by the executor based on a governance proposal function setProposalsCreatedMultiplier(uint64 _proposalsCreatedMultiplier) external onlyExecutor { emit ProposalsCreatedMultiplierChanged(communityPowerMultipliers.proposalsCreated = _proposalsCreatedMultiplier); } /// @notice Set the community power multiplier for proposals passed /// @param _proposalsPassedMultiplier The multiplier applied to community voting power based on proposals passed /// @dev This function can only be called by the executor based on a governance proposal function setProposalsPassedMultiplier(uint64 _proposalsPassedMultiplier) external onlyExecutor { emit ProposalPassedMultiplierChanged(communityPowerMultipliers.proposalsPassed = _proposalsPassedMultiplier); } /// @notice Turn on or off gas refunds for staking and delegating /// @param _stakingRefund Should refunds for staking be on (true) or off (false)? /// @param _delegatingRefund Should refunds for delegating be on (true) or off (false)? /// @param _newCooldown The amount of time a user must wait between refunds of the same type function setRefunds(bool _stakingRefund, bool _delegatingRefund, uint _newCooldown) external onlyExecutor { emit RefundSettingsChanged( stakingRefund = _stakingRefund, delegatingRefund = _delegatingRefund, refundCooldown = _newCooldown ); } /// @notice Pause or unpause staking /// @param _paused Whether staking should be paused or not /// @dev This will be used to open and close staking windows to incentivize participation function setPause(bool _paused) external onlyPauserOrAdmins { emit StakingPause(paused = _paused); } /// @notice Set hte base URI for the metadata for the staked token /// @param _baseURI The new base URI function setBaseURI(string calldata _baseURI) external onlyAdmins { emit BaseURIChanged(baseTokenURI = _baseURI); } /// @notice Set the contract URI for marketplace metadata /// @param _newContractURI The new contract URI function setContractURI(string calldata _newContractURI) external onlyAdmins { emit ContractURIChanged(contractURI = _newContractURI); } /// @notice Check to confirm that this is a FrankenPunks staking contract /// @dev Used by governance when upgrading staking to ensure the correct contract /// @dev Used instead of an interface because interface may change function isFrankenPunksStakingContract() external pure returns (bool) { return true; } /// @notice Contract can receive ETH (will be used to pay for gas refunds) receive() external payable {} /// @notice Contract can receive ETH (will be used to pay for gas refunds) fallback() external payable {} }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern, minimalist, and gas efficient ERC-721 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 indexed id); event Approval(address indexed owner, address indexed spender, uint256 indexed id); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /*////////////////////////////////////////////////////////////// METADATA STORAGE/LOGIC //////////////////////////////////////////////////////////////*/ string public name; string public symbol; function tokenURI(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC721 BALANCE/OWNER STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) internal _ownerOf; mapping(address => uint256) internal _balanceOf; function ownerOf(uint256 id) public view virtual returns (address owner) { require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); } function balanceOf(address owner) public view virtual returns (uint256) { require(owner != address(0), "ZERO_ADDRESS"); return _balanceOf[owner]; } /*////////////////////////////////////////////////////////////// ERC721 APPROVAL STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) public getApproved; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(string memory _name, string memory _symbol) { name = _name; symbol = _symbol; } /*////////////////////////////////////////////////////////////// ERC721 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 id) public virtual { address owner = _ownerOf[id]; require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); getApproved[id] = spender; emit Approval(owner, spender, id); } function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function transferFrom( address from, address to, uint256 id ) public virtual { require(from == _ownerOf[id], "WRONG_FROM"); require(to != address(0), "INVALID_RECIPIENT"); require( msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id], "NOT_AUTHORIZED" ); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. unchecked { _balanceOf[from]--; _balanceOf[to]++; } _ownerOf[id] = to; delete getApproved[id]; emit Transfer(from, to, id); } function safeTransferFrom( address from, address to, uint256 id ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function safeTransferFrom( address from, address to, uint256 id, bytes calldata data ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721 interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 id) internal virtual { require(to != address(0), "INVALID_RECIPIENT"); require(_ownerOf[id] == address(0), "ALREADY_MINTED"); // Counter overflow is incredibly unrealistic. unchecked { _balanceOf[to]++; } _ownerOf[id] = to; emit Transfer(address(0), to, id); } function _burn(uint256 id) internal virtual { address owner = _ownerOf[id]; require(owner != address(0), "NOT_MINTED"); // Ownership check above ensures no underflow. unchecked { _balanceOf[owner]--; } delete _ownerOf[id]; delete getApproved[id]; emit Transfer(owner, address(0), id); } /*////////////////////////////////////////////////////////////// INTERNAL SAFE MINT LOGIC //////////////////////////////////////////////////////////////*/ function _safeMint(address to, uint256 id) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function _safeMint( address to, uint256 id, bytes memory data ) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } } /// @notice A generic interface for a contract which properly accepts ERC721 tokens. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721TokenReceiver { function onERC721Received( address, address, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC721TokenReceiver.onERC721Received.selector; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Efficient library for creating string representations of integers. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol) /// @author Modified from Solady (https://github.com/Vectorized/solady/blob/main/src/utils/LibString.sol) library LibString { function toString(uint256 value) internal pure returns (string memory str) { assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but we allocate 160 bytes // to keep the free memory pointer word aligned. We'll need 1 word for the length, 1 word for the // trailing zeros padding, and 3 other words for a max of 78 digits. In total: 5 * 32 = 160 bytes. let newFreeMemoryPointer := add(mload(0x40), 160) // Update the free memory pointer to avoid overriding our string. mstore(0x40, newFreeMemoryPointer) // Assign str to the end of the zone of newly allocated memory. str := sub(newFreeMemoryPointer, 32) // Clean the last word of memory it may not be overwritten. mstore(str, 0) // Cache the end of the memory to calculate the length later. let end := str // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. // prettier-ignore for { let temp := value } 1 {} { // Move the pointer 1 byte to the left. str := sub(str, 1) // Write the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) // Keep dividing temp until zero. temp := div(temp, 10) // prettier-ignore if iszero(temp) { break } } // Compute and cache the final total length of the string. let length := sub(end, str) // Move the pointer 32 bytes leftwards to make room for the length. str := sub(str, 32) // Store the string's length at the start of memory allocated for our string. mstore(str, length) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; contract FrankenDAOErrors { // General purpose error NotAuthorized(); // Staking error NonExistentToken(); error InvalidDelegation(); error Paused(); error InvalidParameter(); error TokenLocked(); error StakedTokensCannotBeTransferred(); // Governance error ZeroAddress(); error AlreadyInitialized(); error ParameterOutOfBounds(); error InvalidId(); error InvalidProposal(); error InvalidStatus(); error InvalidInput(); error AlreadyVoted(); error NotEligible(); error NotInActiveProposals(); error NotStakingContract(); // Executor error DelayNotSatisfied(); error IdenticalTransactionAlreadyQueued(); error TransactionNotQueued(); error TimelockNotMet(); error TransactionReverted(); }
pragma solidity ^0.8.10; import {IExecutor} from "./IExecutor.sol"; interface IAdmin { //////////////////// ////// Events ////// //////////////////// /// @notice Emited when a new address is set for the Council event NewCouncil(address oldCouncil, address newCouncil); /// @notice Emited when a new address is set for the Founders event NewFounders(address oldFounders, address newFounders); /// @notice Emited when a new address is set for the Pauser event NewPauser(address oldPauser, address newPauser); /// @notice Emited when a new address is set for the Verifier event NewVerifier(address oldVerifier, address newVerifier); /// @notice Emitted when pendingFounders is changed event NewPendingFounders(address oldPendingFounders, address newPendingFounders); ///////////////////// ////// Methods ////// ///////////////////// function acceptFounders() external; function council() external view returns (address); function executor() external view returns (IExecutor); function founders() external view returns (address); function pauser() external view returns (address); function pendingFounders() external view returns (address); function revokeFounders() external; function setCouncil(address _newCouncil) external; function setPauser(address _newPauser) external; function setPendingFounders(address _newPendingFounders) external; }
pragma solidity ^0.8.13; interface IERC721 { function approve(address spender, uint id) external; function transferFrom(address from, address to, uint256 tokenId) external; function safeTransferFrom(address from, address to, uint256 tokenId) external; function ownerOf(uint256 tokenId) external view returns (address); function balanceOf(address owner) external view returns (uint256); function isApprovedForAll(address owner, address operator) external view returns (bool); function getApproved(uint256 tokenId) external view returns (address); }
pragma solidity ^0.8.10; interface IExecutor { //////////////////// ////// Events ////// //////////////////// /// @notice Emited when a transaction is cancelled event CancelTransaction(bytes32 indexed txHash, uint256 id, address indexed target, uint256 value, string signature, bytes data, uint256 eta); /// @notice Emited when a transaction is executed event ExecuteTransaction(bytes32 indexed txHash, uint256 id, address indexed target, uint256 value, string signature, bytes data, uint256 eta); /// @notice Emited when a new delay value is set event NewDelay(uint256 indexed newDelay); /// @notice Emited when a transaction is queued event QueueTransaction(bytes32 indexed txHash, uint256 id, address indexed target, uint256 value, string signature, bytes data, uint256 eta); ///////////////////// ////// Methods ////// ///////////////////// function DELAY() external view returns (uint256); function GRACE_PERIOD() external view returns (uint256); function cancelTransaction(uint256 _id, address _target, uint256 _value, string memory _signature, bytes memory _data, uint256 _eta) external; function executeTransaction(uint256 _id, address _target, uint256 _value, string memory _signature, bytes memory _data, uint256 _eta) external returns (bytes memory); function queueTransaction(uint256 _id, address _target, uint256 _value, string memory _signature, bytes memory _data, uint256 _eta) external returns (bytes32 txHash); function queuedTransactions(bytes32) external view returns (bool); }
pragma solidity ^0.8.10; import {IStaking} from "./IStaking.sol"; interface IGovernance { //////////////////// ////// Events ////// //////////////////// /// @notice Emited when a proposal is canceled event ProposalCanceled(uint256 id); /// @notice Emited when a proposal is created event ProposalCreated( uint256 id, address proposer, address[] targets, uint256[] values, string[] signatures, bytes[] calldatas, uint32 startTime, uint32 endTime, uint24 quorumVotes, string description); /// @notice Emited when a proposal is executed event ProposalExecuted(uint256 id); /// @notice Emited when a proposal is queued event ProposalQueued(uint256 id, uint256 eta); /// @notice Emited when a proposal is vetoed event ProposalVetoed(uint256 id); /// @notice Emited when a new proposal threshold BPS is set event ProposalThresholdBPSSet(uint256 oldProposalThresholdBPS, uint256 newProposalThresholdBPS); /// @notice Emited when a new quorum votes BPS is set event QuorumVotesBPSSet(uint256 oldQuorumVotesBPS, uint256 newQuorumVotesBPS); /// @notice Emited when the refund status changes event RefundSet(bool isProposingRefund, bool oldStatus, bool newStatus); /// @notice Emited when the total community score data is updated event TotalCommunityScoreDataUpdated(uint64 proposalsCreated, uint64 proposalsPassed, uint64 votes); /// @notice Emited when a vote is cast event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 votes); /// @notice Emited when the voting delay is updated event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay); /// @notice Emited when the voting period is updated event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod); /// @notice Emited when the staking contract is changed. event NewStakingContract(address stakingContract); ///////////////////// ////// Storage ////// ///////////////////// struct CommunityScoreData { uint64 votes; uint64 proposalsCreated; uint64 proposalsPassed; } struct Proposal { /// @notice Unique id for looking up a proposal uint96 id; /// @notice Creator of the proposal address proposer; /// @notice the ordered list of target addresses for calls to be made address[] targets; /// @notice The ordered list of values (i.e. msg.value) to be passed to the calls to be made uint256[] values; /// @notice The ordered list of function signatures to be called string[] signatures; /// @notice The ordered list of calldata to be passed to each call bytes[] calldatas; /// @notice The number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed at the time of proposal creation. uint24 quorumVotes; /// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds uint32 eta; /// @notice The block at which voting begins: holders must delegate their votes prior to this block uint32 startTime; /// @notice The block at which voting ends: votes must be cast prior to this block uint32 endTime; /// @notice Current number of votes in favor of this proposal uint24 forVotes; /// @notice Current number of votes in opposition to this proposal uint24 againstVotes; /// @notice Current number of votes for abstaining for this proposal uint24 abstainVotes; /// @notice Flag marking whether a proposal has been verified bool verified; /// @notice Flag marking whether the proposal has been canceled bool canceled; /// @notice Flag marking whether the proposal has been vetoed bool vetoed; /// @notice Flag marking whether the proposal has been executed bool executed; /// @notice Receipts of ballots for the entire set of voters mapping(address => Receipt) receipts; } /// @notice Ballot receipt record for a voter struct Receipt { /// @notice Whether or not a vote has been cast bool hasVoted; /// @notice Whether or not the voter supports the proposal or abstains uint8 support; /// @notice The number of votes the voter had, which were cast uint24 votes; } /// @notice Possible states that a proposal may be in enum ProposalState { Pending, Active, Canceled, Defeated, Succeeded, Queued, Expired, Executed, Vetoed } ///////////////////// ////// Methods ////// ///////////////////// function MAX_PROPOSAL_THRESHOLD_BPS() external view returns (uint256); function MAX_QUORUM_VOTES_BPS() external view returns (uint256); function MAX_VOTING_DELAY() external view returns (uint256); function MAX_VOTING_PERIOD() external view returns (uint256); function MIN_PROPOSAL_THRESHOLD_BPS() external view returns (uint256); function MIN_QUORUM_VOTES_BPS() external view returns (uint256); function MIN_VOTING_DELAY() external view returns (uint256); function MIN_VOTING_PERIOD() external view returns (uint256); function PROPOSAL_MAX_OPERATIONS() external view returns (uint256); function activeProposals(uint256) external view returns (uint256); function cancel(uint256 _proposalId) external; function castVote(uint256 _proposalId, uint8 _support) external; function clear(uint256 _proposalId) external; function execute(uint256 _proposalId) external; function getActions(uint256 _proposalId) external view returns ( address[] memory targets, uint256[] memory values, string[] memory signatures, bytes[] memory calldatas ); function getActiveProposals() external view returns (uint256[] memory); function getProposalData(uint256 _proposalId) external view returns (uint256, address, uint256); function getProposalStatus(uint256 _proposalId) external view returns (bool, bool, bool, bool); function getProposalVotes(uint256 _proposalId) external view returns (uint256, uint256, uint256); function getReceipt(uint256 _proposalId, address _voter) external view returns (Receipt memory); function initialize( address _staking, address _executor, address _founders, address _council, uint256 _votingPeriod, uint256 _votingDelay, uint256 _proposalThresholdBPS, uint256 _quorumVotesBPS ) external; function latestProposalIds(address) external view returns (uint256); function name() external view returns (string memory); function proposalCount() external view returns (uint256); function proposalRefund() external view returns (bool); function proposalThreshold() external view returns (uint256); function proposalThresholdBPS() external view returns (uint256); function proposals(uint256) external view returns ( uint96 id, address proposer, uint24 quorumVotes, uint32 eta, uint32 startTime, uint32 endTime, uint24 forVotes, uint24 againstVotes, uint24 abstainVotes, bool verified, bool canceled, bool vetoed, bool executed ); function propose( address[] memory _targets, uint256[] memory _values, string[] memory _signatures, bytes[] memory _calldatas, string memory _description ) external returns (uint256); function queue(uint256 _proposalId) external; function quorumVotes() external view returns (uint256); function quorumVotesBPS() external view returns (uint256); function setProposalThresholdBPS(uint256 _newProposalThresholdBPS) external; function setQuorumVotesBPS(uint256 _newQuorumVotesBPS) external; function setRefunds(bool _votingRefund, bool _proposalRefund) external; function setStakingAddress(IStaking _newStaking) external; function setVotingDelay(uint256 _newVotingDelay) external; function setVotingPeriod(uint256 _newVotingPeriod) external; function staking() external view returns (IStaking); function state(uint256 _proposalId) external view returns (ProposalState); function totalCommunityScoreData() external view returns (uint64 votes, uint64 proposalsCreated, uint64 proposalsPassed); function updateTotalCommunityScoreData(uint64 _votes, uint64 _proposalsCreated, uint64 _proposalsPassed) external; function userCommunityScoreData(address) external view returns (uint64 votes, uint64 proposalsCreated, uint64 proposalsPassed); function verifyProposal(uint256 _proposalId) external; function veto(uint256 _proposalId) external; function votingDelay() external view returns (uint256); function votingPeriod() external view returns (uint256); function votingRefund() external view returns (bool); }
pragma solidity ^0.8.10; interface IRefundable { //////////////////// ////// Events ////// //////////////////// /// @notice Emitted when a refund is issued event IssueRefund(address refunded, uint256 amount, bool sent, uint256 remainingBalance); /// @notice Emited when we're not able to refund the full amount event InsufficientFundsForRefund(address refunded, uint256 intendedAmount, uint256 sentAmount); ///////////////////// ////// Methods ////// ///////////////////// function MAX_REFUND_PRIORITY_FEE() external view returns (uint256); function REFUND_BASE_GAS() external view returns (uint256); }
pragma solidity ^0.8.10; interface IStaking { //////////////////// ////// Events ////// //////////////////// /// @notice Emited a staker changes who they're delegating to event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); /// @notice Emited when staking is paused/unpaused event StakingPause(bool status); /// @notice Emited when admins change the token's base URI event BaseURIChanged(string _baseURI); /// @notice Emited when the contract URI is updated event ContractURIChanged(string _contractURI); /// @notice Emited when refund settings are updated event RefundSettingsChanged(bool _stakingRefund, bool _delegatingRefund, uint256 _newCooldown); /// @notice Emited when FrankenMonster voting multiplier is changed event MonsterMultiplierChanged(uint256 _monsterMultiplier); /// @notice Emited when the voting multiplier for passed proposals is changed event ProposalPassedMultiplierChanged(uint64 _proposalPassedMultiplier); /// @notice Emited when the stake time multiplier is changed event StakeTimeChanged(uint128 _stakeTime); /// @notice Emited when the staking multiplier is changed event StakeAmountChanged(uint128 _stakeAmount); /// @notice Emited when the voting multiplier for voting is changed event VotesMultiplierChanged(uint64 _votesMultiplier); /// @notice Emited when the voting multiplier for creating proposals is changed event ProposalsCreatedMultiplierChanged(uint64 _proposalsCreatedMultiplier); /// @notice Emited when the base votes for a token is changed event BaseVotesChanged(uint256 _baseVotes); ///////////////////// ////// Storage ////// ///////////////////// struct CommunityPowerMultipliers { uint64 votes; uint64 proposalsCreated; uint64 proposalsPassed; } struct StakingSettings { uint128 maxStakeBonusTime; uint128 maxStakeBonusAmount; } enum RefundStatus { StakingAndDelegatingRefund, StakingRefund, DelegatingRefund, NoRefunds } ///////////////////// ////// Methods ////// ///////////////////// function baseTokenURI() external view returns (string memory); function BASE_VOTES() external view returns (uint256); function changeStakeAmount(uint128 _newMaxStakeBonusAmount) external; function changeStakeTime(uint128 _newMaxStakeBonusTime) external; function communityPowerMultipliers() external view returns (uint64 votes, uint64 proposalsCreated, uint64 proposalsPassed); function delegate(address _delegatee) external; function delegatingRefund() external view returns (bool); function evilBonus(uint256 _tokenId) external view returns (uint256); function getCommunityVotingPower(address _voter) external view returns (uint256); function getDelegate(address _delegator) external view returns (address); function getStakedTokenSupplies() external view returns (uint128, uint128); function getTokenVotingPower(uint256 _tokenId) external view returns (uint256); function getTotalVotingPower() external view returns (uint256); function getVotes(address _account) external view returns (uint256); function isFrankenPunksStakingContract() external pure returns (bool); function lastDelegatingRefund(address) external view returns (uint256); function lastStakingRefund(address) external view returns (uint256); function paused() external view returns (bool); function setBaseURI(string memory _baseURI) external; function setPause(bool _paused) external; function setProposalsCreatedMultiplier(uint64 _proposalsCreatedMultiplier) external; function setProposalsPassedMultiplier(uint64 _proposalsPassedMultiplier) external; function setRefunds(bool _stakingRefund, bool _delegatingRefund, uint256 _newCooldown) external; function setVotesMultiplier(uint64 _votesmultiplier) external; function stake(uint256[] memory _tokenIds, uint256 _unlockTime) external; function stakedFrankenMonsters() external view returns (uint128); function stakedFrankenPunks() external view returns (uint128); function stakingRefund() external view returns (bool); function stakingSettings() external view returns (uint128 maxStakeBonusTime, uint128 maxStakeBonusAmount); function tokenVotingPower(address) external view returns (uint256); function unlockTime(uint256) external view returns (uint256); function unstake(uint256[] memory _tokenIds, address _to) external; function votesFromOwnedTokens(address) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import "../interfaces/IAdmin.sol"; import "../interfaces/IExecutor.sol"; import { FrankenDAOErrors } from "../errors/FrankenDAOErrors.sol"; /// @notice Custom access control manager for FrankenDAO /// @dev This functionality is inherited by Governance.sol and Staking.sol abstract contract Admin is IAdmin, FrankenDAOErrors { /// @notice Founder multisig address public founders; /// @notice Council multisig address public council; /// @notice Executor contract address for passed governance proposals IExecutor public executor; /// @notice Admin that only has the power to pause and unpause staking /// @dev This will be a EOA used by the team for easy pausing and unpausing /// @dev This address is changeable by governance if the community thinks the team is misusing this power address public pauser; /// @notice Admin that only has the power to verify contracts /// @dev This will be an EOA used by the team for contract verification address public verifier; /// @notice Pending founder addresses for this contract /// @dev Only founders is two-step, because errors in transferring other admin addresses can be corrected by founders address public pendingFounders; ///////////////////////////// ///////// MODIFIERS ///////// ///////////////////////////// /// @notice Modifier for functions that can only be called by the Executor contract /// @dev This is for functions that only Governance is able to call modifier onlyExecutor() { if(msg.sender != address(executor)) revert NotAuthorized(); _; } /// @notice Modifier for functions that can only be called by the Council or Founder multisigs modifier onlyAdmins() { if(msg.sender != founders && msg.sender != council) revert NotAuthorized(); _; } /// @notice Modifier for functions that can only be called by the Pauser or either multisig modifier onlyPauserOrAdmins() { if(msg.sender != founders && msg.sender != council && msg.sender != pauser) revert NotAuthorized(); _; } modifier onlyVerifierOrAdmins() { if(msg.sender != founders && msg.sender != council && msg.sender != verifier) revert NotAuthorized(); _; } /// @notice Modifier for functions that can only be called by either multisig or the Executor contract modifier onlyExecutorOrAdmins() { if ( msg.sender != address(executor) && msg.sender != council && msg.sender != founders ) revert NotAuthorized(); _; } ///////////////////////////// ////// ADMIN TRANSFERS ////// ///////////////////////////// /// @notice Begins transfer of founder rights. The newPendingFounders must call `_acceptFounders` to finalize the transfer. /// @param _newPendingFounders New pending founder. /// @dev This doesn't use onlyAdmins because only Founders have the right to set new Founders. function setPendingFounders(address _newPendingFounders) external { if (msg.sender != founders) revert NotAuthorized(); emit NewPendingFounders(pendingFounders, _newPendingFounders); pendingFounders = _newPendingFounders; } /// @notice Accepts transfer of founder rights. msg.sender must be pendingFounders function acceptFounders() external { if (msg.sender != pendingFounders) revert NotAuthorized(); emit NewFounders(founders, pendingFounders); founders = pendingFounders; pendingFounders = address(0); } /// @notice Revokes permissions for the founder multisig /// @dev Only the founders can call this, as nobody else should be able to revoke this permission /// @dev Used for eventual decentralization, as otherwise founders cannot be set to address(0) because of two-step /// @dev This also ensures that pendingFounders is set to address(0), to ensure they can't re-accept it later function revokeFounders() external { if (msg.sender != founders) revert NotAuthorized(); emit NewFounders(founders, address(0)); founders = address(0); pendingFounders = address(0); } /// @notice Transfers council address to a new multisig /// @param _newCouncil New address for council /// @dev This uses onlyAdmin because either the Council or the Founders can set a new Council. function setCouncil(address _newCouncil) external onlyAdmins { emit NewCouncil(council, _newCouncil); council = _newCouncil; } /// @notice Transfers verifier role to a new address. /// @param _newVerifier New address for verifier function setVerifier(address _newVerifier) external onlyAdmins { emit NewVerifier(verifier, _newVerifier); verifier = _newVerifier; } /// @notice Transfers pauser role to a new address. /// @param _newPauser New address for pauser function setPauser(address _newPauser) external onlyExecutorOrAdmins { emit NewPauser(pauser, _newPauser); pauser = _newPauser; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import "../interfaces/IRefundable.sol"; import { FrankenDAOErrors } from "../errors/FrankenDAOErrors.sol"; /// @notice Provides a _refundGas() function that can be used for inhering contracts to refund user gas cost /// @dev This functionality is inherited by Governance.sol (for proposing and voting) and Staking.sol (for staking and delegating) contract Refundable is IRefundable, FrankenDAOErrors { /// @notice The maximum priority fee used to cap gas refunds uint256 public constant MAX_REFUND_PRIORITY_FEE = 2 gwei; /// @notice Gas used before _startGas or after refund /// @dev Includes 21K TX base, 3.7K for other overhead, and 2.3K for ETH transfer /** @dev This will be slightly different depending on which function is used, but all are within a few thousand gas, so approximation is fine. */ uint256 public constant REFUND_BASE_GAS = 27_000; /// @notice Calculate the amount spent on gas and send that to msg.sender from the contract's balance /// @param _startGas gasleft() at the start of the transaction, used to calculate gas spent /// @dev Forked from NounsDAO: https://github.com/nounsDAO/nouns-monorepo/blob/master/packages/nouns-contracts/contracts/governance/NounsDAOLogicV2.sol#L1033-L1046 function _refundGas(uint256 _startGas) internal { unchecked { uint256 gasPrice = _min(tx.gasprice, block.basefee + MAX_REFUND_PRIORITY_FEE); uint256 gasUsed = _startGas - gasleft() + REFUND_BASE_GAS; uint refundAmount = gasPrice * gasUsed; // If gas fund runs out, pay out as much as possible and emit warning event. if (address(this).balance < refundAmount) { emit InsufficientFundsForRefund(msg.sender, refundAmount, address(this).balance); refundAmount = address(this).balance; } // There shouldn't be any reentrancy risk, as this is called last at all times. // They also can't exploit the refund by wasting gas before we've already finalized amount. (bool refundSent, ) = msg.sender.call{ value: refundAmount }(''); // Includes current balance in event so team can listen and filter to know when to propose refill. emit IssueRefund(msg.sender, refundAmount, refundSent, address(this).balance); } } /// @notice Returns the lower value of two uints /// @param a First uint /// @param b Second uint function _min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.2._ */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v2.5._ */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toUint24(uint256 value) internal pure returns (uint24) { require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); return uint24(value); } }
{ "remappings": [ "@openzeppelin/=lib/openzeppelin-contracts/contracts/", "ds-test/=lib/solmate/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "solmate/=lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_frankenpunks","type":"address"},{"internalType":"address","name":"_frankenmonsters","type":"address"},{"internalType":"address","name":"_governance","type":"address"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"address","name":"_founders","type":"address"},{"internalType":"address","name":"_council","type":"address"},{"internalType":"string","name":"_baseTokenURI","type":"string"},{"internalType":"string","name":"_contractURI","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"AlreadyVoted","type":"error"},{"inputs":[],"name":"DelayNotSatisfied","type":"error"},{"inputs":[],"name":"IdenticalTransactionAlreadyQueued","type":"error"},{"inputs":[],"name":"InvalidDelegation","type":"error"},{"inputs":[],"name":"InvalidId","type":"error"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[],"name":"InvalidParameter","type":"error"},{"inputs":[],"name":"InvalidProposal","type":"error"},{"inputs":[],"name":"InvalidStatus","type":"error"},{"inputs":[],"name":"NonExistentToken","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"NotEligible","type":"error"},{"inputs":[],"name":"NotInActiveProposals","type":"error"},{"inputs":[],"name":"NotStakingContract","type":"error"},{"inputs":[],"name":"ParameterOutOfBounds","type":"error"},{"inputs":[],"name":"Paused","type":"error"},{"inputs":[],"name":"StakedTokensCannotBeTransferred","type":"error"},{"inputs":[],"name":"TimelockNotMet","type":"error"},{"inputs":[],"name":"TokenLocked","type":"error"},{"inputs":[],"name":"TransactionNotQueued","type":"error"},{"inputs":[],"name":"TransactionReverted","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"_baseURI","type":"string"}],"name":"BaseURIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_baseVotes","type":"uint256"}],"name":"BaseVotesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"_contractURI","type":"string"}],"name":"ContractURIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"refunded","type":"address"},{"indexed":false,"internalType":"uint256","name":"intendedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sentAmount","type":"uint256"}],"name":"InsufficientFundsForRefund","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"refunded","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"sent","type":"bool"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"}],"name":"IssueRefund","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_monsterMultiplier","type":"uint256"}],"name":"MonsterMultiplierChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldCouncil","type":"address"},{"indexed":false,"internalType":"address","name":"newCouncil","type":"address"}],"name":"NewCouncil","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldFounders","type":"address"},{"indexed":false,"internalType":"address","name":"newFounders","type":"address"}],"name":"NewFounders","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPauser","type":"address"},{"indexed":false,"internalType":"address","name":"newPauser","type":"address"}],"name":"NewPauser","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPendingFounders","type":"address"},{"indexed":false,"internalType":"address","name":"newPendingFounders","type":"address"}],"name":"NewPendingFounders","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldVerifier","type":"address"},{"indexed":false,"internalType":"address","name":"newVerifier","type":"address"}],"name":"NewVerifier","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"_proposalPassedMultiplier","type":"uint64"}],"name":"ProposalPassedMultiplierChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"_proposalsCreatedMultiplier","type":"uint64"}],"name":"ProposalsCreatedMultiplierChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"_stakingRefund","type":"bool"},{"indexed":false,"internalType":"bool","name":"_delegatingRefund","type":"bool"},{"indexed":false,"internalType":"uint256","name":"_newCooldown","type":"uint256"}],"name":"RefundSettingsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"_stakeAmount","type":"uint128"}],"name":"StakeAmountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"_stakeTime","type":"uint128"}],"name":"StakeTimeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"StakingPause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"_votesMultiplier","type":"uint64"}],"name":"VotesMultiplierChanged","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"BASE_VOTES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REFUND_PRIORITY_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFUND_BASE_GAS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptFounders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"_newMaxStakeBonusAmount","type":"uint128"}],"name":"changeStakeAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_newMaxStakeBonusTime","type":"uint128"}],"name":"changeStakeTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"communityPowerMultipliers","outputs":[{"internalType":"uint64","name":"votes","type":"uint64"},{"internalType":"uint64","name":"proposalsCreated","type":"uint64"},{"internalType":"uint64","name":"proposalsPassed","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"council","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_delegatee","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"delegatingRefund","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"evilBonus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"executor","outputs":[{"internalType":"contract IExecutor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"founders","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_voter","type":"address"}],"name":"getCommunityVotingPower","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_delegator","type":"address"}],"name":"getDelegate","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakedTokenSupplies","outputs":[{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getTokenVotingPower","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalVotingPower","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isFrankenPunksStakingContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastDelegatingRefund","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastStakingRefund","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauser","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingFounders","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refundCooldown","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"revokeFounders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newContractURI","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newCouncil","type":"address"}],"name":"setCouncil","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newPauser","type":"address"}],"name":"setPauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newPendingFounders","type":"address"}],"name":"setPendingFounders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_proposalsCreatedMultiplier","type":"uint64"}],"name":"setProposalsCreatedMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_proposalsPassedMultiplier","type":"uint64"}],"name":"setProposalsPassedMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_stakingRefund","type":"bool"},{"internalType":"bool","name":"_delegatingRefund","type":"bool"},{"internalType":"uint256","name":"_newCooldown","type":"uint256"}],"name":"setRefunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newVerifier","type":"address"}],"name":"setVerifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_votesMultiplier","type":"uint64"}],"name":"setVotesMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"uint256","name":"_unlockTime","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakedFrankenMonsters","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakedFrankenPunks","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingRefund","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingSettings","outputs":[{"internalType":"uint128","name":"maxStakeBonusTime","type":"uint128"},{"internalType":"uint128","name":"maxStakeBonusAmount","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenVotingPower","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"unlockTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"address","name":"_to","type":"address"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"verifier","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"votesFromOwnedTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6105806040527d80001100000000000008002002000080008000400000400020000000100060809081527f200800300200000000600000000000030000000000000000000000000008000060a05279180000000000088000000000000000000000040008000200000060c0527b0100000000000000000000000000000012090000000900000000000060e0527f2000000000000000000000000000000001000000000100000000000000002000610100527f0800000000400400000000002000000000000080080000000000000000040001610120527d400000100010000000010000004000000000000200800000000000000000610140527d010000010100000000000020000020000200000000000000000000000008610160527d800000001000100003080025000800000000080000010000050000000000610180527f20000000040100210000000000000000008000020000000000000000000000006101a0527c04000000000800000000002000000000000003000004000000000000006101c0527f02000000210000002000000000000000000120000000140000000000000030106101e0527d20002000000000800008000000000000000000000000010001040004000061020052618001607d1b610220527720000000000040000000006000000004000a000000101001610240527c040000000000000000000000100208004008000000110000000040000061026052792000200000000000008000000000000000000000004100000020610280527a1000000000000000200000000000000000000000001000200010006102a0527340100000000000008008000000008000000040006102c0527d4080000020000000000004000000000000000820000000000000000000006102e0527d010140000000000008000000000000000100000000040004000102000008610300527f0100000000000000000080000000020100000000000000100002000008020000610320527920000040800000000000000000002000000000000000000000206103405274020000000000000800000000100000000000002000610360527c0800000000000000000000400000020000000000000000001001000000610380527c01000000000000000000000000104100000000800400020000002000206103a0527f08400004000010108800000800040000001000000000000200000100000000006103c0527a5120000000000000000010000000000001000000000000000002006103e0527f4000000000004000000810000010000000010000400000000800000000004004610400527d080000800000002080000000000000000000800002000000000400000800610420527d08000001000000000800000000002000000000000000000002010008010161044052780800000000080000040008000000880120120008002000000061046052730800000000020000000000000000008000000080610480527c10000000000000400000000200000000000000000000000020000000006104a0527b400420000000000040084000020800200020100000000000000000006104c0527b040000000000110000000000000000402000000000000000040000006104e0527c0200000000020000004000000001000001021000000000000000020000610500527840004000004000000208080200000004100000100400100000610520527d200000000001000000000000000000000800000000000400000000000000610540526000610560526200051a906020906028620006da565b503480156200052857600080fd5b50604051620046a9380380620046a98339810160408190526200054b9162000816565b6040518060400160405280601381526020017f5374616b6564204672616e6b656e50756e6b73000000000000000000000000008152506040518060400160405280600381526020016207346560ec1b8152508160009081620005ae919062000980565b506001620005bd828262000980565b5050600c80546001600160a01b03199081166001600160a01b038c811691909117909255600d805482168b8416179055600e805482168a841617905560088054821689841617905560068054821688841617905560078054909116918616919091179055506040805180820182526224ea008152601460209182015270140000000000000000000000000024ea00600f5581516060810183526064815260c891810182905290910152601080546001600160c01b03191670c800000000000000c800000000000000641790556013805460ff19908116600190811790925560118054909116909117905562015180601555601d620006bc838262000980565b50601e620006cb828262000980565b50505050505050505062000a4c565b82602881019282156200070b579160200282015b828111156200070b578251825591602001919060010190620006ee565b50620007199291506200071d565b5090565b5b808211156200071957600081556001016200071e565b80516001600160a01b03811681146200074c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200077957600080fd5b81516001600160401b038082111562000796576200079662000751565b604051601f8301601f19908116603f01168101908282118183101715620007c157620007c162000751565b81604052838152602092508683858801011115620007de57600080fd5b600091505b83821015620008025785820183015181830184015290820190620007e3565b600093810190920192909252949350505050565b600080600080600080600080610100898b0312156200083457600080fd5b6200083f8962000734565b97506200084f60208a0162000734565b96506200085f60408a0162000734565b95506200086f60608a0162000734565b94506200087f60808a0162000734565b93506200088f60a08a0162000734565b60c08a01519093506001600160401b0380821115620008ad57600080fd5b620008bb8c838d0162000767565b935060e08b0151915080821115620008d257600080fd5b50620008e18b828c0162000767565b9150509295985092959890939650565b600181811c908216806200090657607f821691505b6020821081036200092757634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200097b57600081815260208120601f850160051c81016020861015620009565750805b601f850160051c820191505b81811015620009775782815560010162000962565b5050505b505050565b81516001600160401b038111156200099c576200099c62000751565b620009b481620009ad8454620008f1565b846200092d565b602080601f831160018114620009ec5760008415620009d35750858301515b600019600386901b1c1916600185901b17855562000977565b600085815260208120601f198616915b8281101562000a1d57888601518255948401946001909101908401620009fc565b508582101562000a3c5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b613c4d8062000a5c6000396000f3fe60806040526004361061038c5760003560e01c80635c975abb116101da578063a2510dae11610101578063d547cfb71161009a578063e8a3d4851161006c578063e8a3d48514610ba4578063e985e9c514610bb9578063eb3ab52414610bf4578063fbfee87614610c1457005b8063d547cfb714610b35578063df864c2314610b4a578063e2c6d41c14610b6a578063e838e56514610b8a57005b8063c34c08e5116100d3578063c34c08e514610ab3578063c87b56dd14610ad3578063d2a3250714610af3578063d340df1d14610b2057005b8063a2510dae14610a33578063a6d80a2714610a53578063b88d4fde14610a73578063bedb86fb14610a9357005b80638f228f93116101735780639ab24eb0116101455780639ab24eb0146109b35780639fd0506d146109d3578063a113607d146109f3578063a22cb46514610a1357005b80638f228f931461093c578063938e3d7b1461096957806394f38e8c1461098957806395d89b411461099e57005b806370a08231116101ac57806370a08231146108af57806376cb22e8146108cf578063857b767b146108ef5780638e4237981461090f57005b80635c975abb1461082a5780636352211e146108445780636d7ae837146108645780636f0ddd221461088f57005b806337a8a0dc116102be5780634d8e60461161025757806358f739e41161022957806358f739e4146107b05780635913f96d146107d05780635bb71b34146107f05780635c19a95c1461080a57005b80634d8e60461461070b5780635437988d14610750578063544d85641461077057806355f804b31461079057005b806342842e0e1161029057806342842e0e1461065f57806345bba9401461067f578063472b884d146106ac57806347e00ebc146106eb57005b806337a8a0dc146105e95780633be8ef3f146106095780633c7b1cd41461061f578063411b007e1461063f57005b806323b872dd116103305780632d88af4a116103025780632d88af4a146105755780632dc4a01714610595578063325b2d96146105b557806336331521146105c957005b806323b872dd146104bf578063285adddd146104df5780632b7ac3f31461053f5780632d3e8c931461055f57005b8063081812fc11610369578063081812fc1461040f578063095ea7b31461045d57806311acc1a71461047d5780631797c84c1461049257005b806301ffc9a71461039557806302e93ec1146103ca57806306fdde03146103ed57005b3661039357005b005b3480156103a157600080fd5b506103b56103b0366004613213565b610c2c565b60405190151581526020015b60405180910390f35b3480156103d657600080fd5b506103df601481565b6040519081526020016103c1565b3480156103f957600080fd5b50610402610c7e565b6040516103c19190613254565b34801561041b57600080fd5b5061044561042a366004613287565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016103c1565b34801561046957600080fd5b506103936104783660046132b5565b610d0c565b34801561048957600080fd5b506103df610df3565b34801561049e57600080fd5b506103df6104ad366004613287565b60186020526000908152604090205481565b3480156104cb57600080fd5b506103936104da3660046132e1565b610e17565b3480156104eb57600080fd5b50601054610515906001600160401b0380821691600160401b8104821691600160801b9091041683565b604080516001600160401b03948516815292841660208401529216918101919091526060016103c1565b34801561054b57600080fd5b50600a54610445906001600160a01b031681565b34801561056b57600080fd5b506103df60155481565b34801561058157600080fd5b50610393610590366004613322565b610e30565b3480156105a157600080fd5b506103936105b0366004613354565b610ef4565b3480156105c157600080fd5b5060016103b5565b3480156105d557600080fd5b506103936105e43660046133bc565b610f75565b3480156105f557600080fd5b50610393610604366004613420565b610f85565b34801561061557600080fd5b506103df61697881565b34801561062b57600080fd5b5061039361063a366004613450565b61101a565b34801561064b57600080fd5b50600654610445906001600160a01b031681565b34801561066b57600080fd5b5061039361067a3660046132e1565b6110c6565b34801561068b57600080fd5b506103df61069a366004613322565b601a6020526000908152604090205481565b3480156106b857600080fd5b50601f546106d390600160801b90046001600160801b031681565b6040516001600160801b0390911681526020016103c1565b3480156106f757600080fd5b50600b54610445906001600160a01b031681565b34801561071757600080fd5b50601f546001600160801b0380821691600160801b9004165b604080516001600160801b039384168152929091166020830152016103c1565b34801561075c57600080fd5b5061039361076b366004613322565b6111b9565b34801561077c57600080fd5b5061044561078b366004613322565b611266565b34801561079c57600080fd5b506103936107ab3660046134ba565b611298565b3480156107bc57600080fd5b506103936107cb366004613354565b611323565b3480156107dc57600080fd5b506103936107eb366004613354565b6113a9565b3480156107fc57600080fd5b506013546103b59060ff1681565b34801561081657600080fd5b50610393610825366004613322565b611434565b34801561083657600080fd5b506016546103b59060ff1681565b34801561085057600080fd5b5061044561085f366004613287565b6114b3565b34801561087057600080fd5b50600f54610730906001600160801b0380821691600160801b90041682565b34801561089b57600080fd5b506103df6108aa366004613287565b61150a565b3480156108bb57600080fd5b506103df6108ca366004613322565b611555565b3480156108db57600080fd5b506103936108ea366004613322565b6115b8565b3480156108fb57600080fd5b5061039361090a3660046134fb565b61164c565b34801561091b57600080fd5b506103df61092a366004613322565b60146020526000908152604090205481565b34801561094857600080fd5b506103df610957366004613322565b60126020526000908152604090205481565b34801561097557600080fd5b506103936109843660046134ba565b6116bb565b34801561099557600080fd5b5061039361172d565b3480156109aa57600080fd5b506104026117bc565b3480156109bf57600080fd5b506103df6109ce366004613322565b6117c9565b3480156109df57600080fd5b50600954610445906001600160a01b031681565b3480156109ff57600080fd5b506103df610a0e366004613287565b6117f7565b348015610a1f57600080fd5b50610393610a2e366004613546565b611877565b348015610a3f57600080fd5b50610393610a4e366004613450565b6118e3565b348015610a5f57600080fd5b50610393610a6e366004613322565b61195c565b348015610a7f57600080fd5b50610393610a8e36600461357f565b611a09565b348015610a9f57600080fd5b50610393610aae3660046135f1565b611af1565b348015610abf57600080fd5b50600854610445906001600160a01b031681565b348015610adf57600080fd5b50610402610aee366004613287565b611b8d565b348015610aff57600080fd5b506103df610b0e366004613322565b601b6020526000908152604090205481565b348015610b2c57600080fd5b50610393611c9f565b348015610b4157600080fd5b50610402611d3c565b348015610b5657600080fd5b506103df610b65366004613322565b611d49565b348015610b7657600080fd5b50600754610445906001600160a01b031681565b348015610b9657600080fd5b506011546103b59060ff1681565b348015610bb057600080fd5b50610402611f1a565b348015610bc557600080fd5b506103b5610bd436600461360e565b600560209081526000928352604080842090915290825290205460ff1681565b348015610c0057600080fd5b50601f546106d3906001600160801b031681565b348015610c2057600080fd5b506103df637735940081565b60006301ffc9a760e01b6001600160e01b031983161480610c5d57506380ac58cd60e01b6001600160e01b03198316145b80610c785750635b5e139f60e01b6001600160e01b03198316145b92915050565b60008054610c8b9061363c565b80601f0160208091040260200160405190810160405280929190818152602001828054610cb79061363c565b8015610d045780601f10610cd957610100808354040283529160200191610d04565b820191906000526020600020905b815481529060010190602001808311610ce757829003601f168201915b505050505081565b6000818152600260205260409020546001600160a01b031633811480610d5557506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b610d975760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064015b60405180910390fd5b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000610e056001600160a01b03611d49565b601c54610e12919061368c565b905090565b604051630517a52360e41b815260040160405180910390fd5b6008546001600160a01b03163314801590610e5657506007546001600160a01b03163314155b8015610e6d57506006546001600160a01b03163314155b15610e8b5760405163ea8e4eb560e01b815260040160405180910390fd5b600954604080516001600160a01b03928316815291831660208301527fce932f997de7d15c38f57fe533bddcd74b6560acb995bdd231da68ed3af22dfe910160405180910390a1600980546001600160a01b0319166001600160a01b0392909216919091179055565b6008546001600160a01b03163314610f1f5760405163ea8e4eb560e01b815260040160405180910390fd5b6010805467ffffffffffffffff19166001600160401b0383169081179091556040519081527fbcf22ad7361f78458cd162cd291861a99c58be848cff080f08d1f6991f8aa49e906020015b60405180910390a150565b610f80838383611f27565b505050565b6008546001600160a01b03163314610fb05760405163ea8e4eb560e01b815260040160405180910390fd5b6011805484151560ff19918216811790925560138054851515921682179055601583905560408051928352602083019190915281018290527fbe343bfc5b51c0897197b9607c9e9a5116528d9a0156e4df5f146d39a020e5219060600160405180910390a1505050565b6008546001600160a01b031633146110455760405163ea8e4eb560e01b815260040160405180910390fd5b806001600160801b031660000361106f57604051630309cb8760e51b815260040160405180910390fd5b600f80546fffffffffffffffffffffffffffffffff19166001600160801b0383169081179091556040519081527fc73c2a2bcffa7fa8054797c5e4f48a83008619e351a32b7ac7f48a8ab2c84c7e90602001610f6a565b6110d1838383610e17565b6001600160a01b0382163b158061117a5750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af115801561114a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116e919061369f565b6001600160e01b031916145b610f805760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606401610d8e565b6006546001600160a01b031633148015906111df57506007546001600160a01b03163314155b156111fd5760405163ea8e4eb560e01b815260040160405180910390fd5b600a54604080516001600160a01b03928316815291831660208301527f2ff4895c300d6993c27f2bb507b4b59d29464dc640af727383451365631ba8b2910160405180910390a1600a80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03808216600090815260196020526040812054909116801561128f5780611291565b825b9392505050565b6006546001600160a01b031633148015906112be57506007546001600160a01b03163314155b156112dc5760405163ea8e4eb560e01b815260040160405180910390fd5b7f5411e8ebf1636d9e83d5fc4900bf80cbac82e8790da2a4c94db4895e889eedf6601d61130a838583613718565b60405161131791906137d7565b60405180910390a15050565b6008546001600160a01b0316331461134e5760405163ea8e4eb560e01b815260040160405180910390fd5b6010805467ffffffffffffffff60801b1916600160801b6001600160401b038416908102919091179091556040519081527ff869d8acf2c70483110d4a26b89c5d2a66debd3c29df24c1000a3be12d2d86d990602001610f6a565b6008546001600160a01b031633146113d45760405163ea8e4eb560e01b815260040160405180910390fd5b601080546fffffffffffffffff00000000000000001916600160401b6001600160401b038416908102919091179091556040519081527f57586600c57c1d016eefd84f76fe9697155dc45acbce61da494952312882381890602001610f6a565b6001600160a01b0381166114455750335b60135460ff16801561147357506015543360009081526014602052604090205442916114709161368c565b11155b156114a65760005a905061148733836122cf565b3360009081526014602052604090204290556114a2816126b6565b5050565b6114b033826122cf565b50565b6000818152600260205260409020546001600160a01b0316806115055760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b6044820152606401610d8e565b919050565b6000612710821061151d57506000919050565b61152b60ff80841690613862565b6020600884901c6028811061154257611542613875565b0154901c600116600a610c78919061388b565b60006001600160a01b03821661159c5760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606401610d8e565b506001600160a01b031660009081526003602052604090205490565b6006546001600160a01b031633146115e35760405163ea8e4eb560e01b815260040160405180910390fd5b600b54604080516001600160a01b03928316815291831660208301527fb81319a9bb8b17fae110bb40da7c54c734732f52530117d5700894fb45e388bf910160405180910390a1600b80546001600160a01b0319166001600160a01b0392909216919091179055565b60115460ff16801561167a57506015543360009081526012602052604090205442916116779161368c565b11155b156116b05760005a905061168f8484846127bd565b3360009081526012602052604090204290556116aa816126b6565b50505050565b610f808383836127bd565b6006546001600160a01b031633148015906116e157506007546001600160a01b03163314155b156116ff5760405163ea8e4eb560e01b815260040160405180910390fd5b7fd5ee5eaf65263bab5d569890714d123ad48a9e54409d35e71d374f3dd300bba0601e61130a838583613718565b6006546001600160a01b031633146117585760405163ea8e4eb560e01b815260040160405180910390fd5b600654604080516001600160a01b039092168252600060208301527fdb8dcc8712c6b41e8da769643922645a1221ad9c79beaf28920e2a5d5a893a62910160405180910390a1600680546001600160a01b0319908116909155600b80549091169055565b60018054610c8b9061363c565b60006117d482611d49565b6001600160a01b0383166000908152601b6020526040902054610c78919061368c565b600080611803836114b3565b6001600160a01b03160361182a57604051634a1850bf60e11b815260040160405180910390fd5b6000612710831061184657611841600260146138a2565b611849565b60145b90506118548361150a565b60008481526017602052604090205461186d908361368c565b611291919061368c565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6008546001600160a01b0316331461190e5760405163ea8e4eb560e01b815260040160405180910390fd5b600f80546001600160801b03908116600160801b918416918202179091556040519081527fe213d3449d5ab338ffd40007fe5a97d45d0418c1f0dc502f7925cda3fc78c8af90602001610f6a565b6006546001600160a01b0316331480159061198257506007546001600160a01b03163314155b156119a05760405163ea8e4eb560e01b815260040160405180910390fd5b600754604080516001600160a01b03928316815291831660208301527f66a019a63262ba85572d64812414a277be4e9069feaf5b182f95e4b6e529c3a4910160405180910390a1600780546001600160a01b0319166001600160a01b0392909216919091179055565b611a14858585610e17565b6001600160a01b0384163b1580611aab5750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a0290611a5c9033908a908990899089906004016138c4565b6020604051808303816000875af1158015611a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9f919061369f565b6001600160e01b031916145b611aea5760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606401610d8e565b5050505050565b6006546001600160a01b03163314801590611b1757506007546001600160a01b03163314155b8015611b2e57506009546001600160a01b03163314155b15611b4c5760405163ea8e4eb560e01b815260040160405180910390fd5b6016805460ff19168215159081179091556040519081527f608c68cec60453b4c976616f2c75d7dc520288e1fcf03656b57f7d7bddc8492090602001610f6a565b60606000611b9a836114b3565b6001600160a01b031603611bc157604051634a1850bf60e11b815260040160405180910390fd5b6000601d8054611bd09061363c565b80601f0160208091040260200160405190810160405280929190818152602001828054611bfc9061363c565b8015611c495780601f10611c1e57610100808354040283529160200191611c49565b820191906000526020600020905b815481529060010190602001808311611c2c57829003601f168201915b505050505090506000815111611c6e5760405180602001604052806000815250611291565b80611c788461297b565b604051602001611c89929190613918565b6040516020818303038152906040529392505050565b600b546001600160a01b03163314611cca5760405163ea8e4eb560e01b815260040160405180910390fd5b600654600b54604080516001600160a01b0393841681529290911660208301527fdb8dcc8712c6b41e8da769643922645a1221ad9c79beaf28920e2a5d5a893a62910160405180910390a1600b8054600680546001600160a01b03199081166001600160a01b03841617909155169055565b601d8054610c8b9061363c565b60008080806002600160a01b03196001600160a01b03861601611de957600e60009054906101000a90046001600160a01b03166001600160a01b031663afb417616040518163ffffffff1660e01b8152600401606060405180830381865afa158015611db9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ddd9190613957565b91945092509050611e89565b6001600160a01b0385166000908152601b60205260408120549003611e1357506000949350505050565b600e546040516331b7e5d760e11b81526001600160a01b0387811660048301529091169063636fcbae90602401606060405180830381865afa158015611e5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e819190613957565b919450925090505b604080516060810182526010546001600160401b038082168352600160401b820481166020840152600160801b9091041691810182905290606490611ece9084613999565b6020830151611edd9086613999565b8351611ee99088613999565b611ef391906139c4565b611efd91906139c4565b6001600160401b0316611f1091906138a2565b9695505050505050565b601e8054610c8b9061363c565b600e5460408051635584c4f960e01b815290516000926001600160a01b031691635584c4f991600480830192869291908290030181865afa158015611f70573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611f989190810190613a1b565b905060005b815181101561214f57600e5482516001600160a01b039091169063e23a9a5290849084908110611fcf57611fcf613875565b6020026020010151611fe033611266565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b03166024820152604401606060405180830381865afa15801561202a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204e9190613ac0565b511561206d57604051635a8181f760e01b815260040160405180910390fd5b600e5482516000916001600160a01b031690636e7685309085908590811061209757612097613875565b60200260200101516040518263ffffffff1660e01b81526004016120bd91815260200190565b606060405180830381865afa1580156120da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120fe9190613b3f565b5091505061210b33611266565b6001600160a01b0316816001600160a01b03160361213c57604051635a8181f760e01b815260040160405180910390fd5b508061214781613b78565b915050611f9d565b5082600081900361217357604051630309cb8760e51b815260040160405180910390fd5b6000805b828110156121bf576121a187878381811061219457612194613875565b90506020020135866129bf565b6121ab908361368c565b9150806121b781613b78565b915050612177565b50336000908152601a6020526040812080548392906121df908490613862565b90915550819050601b60006121f333611266565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546122229190613862565b9250508190555080601c600082825461223b9190613862565b9091555061224a905033611266565b6001600160a01b0316330361227f57336000908152601b6020526040812054900361227a5761227a336000612b90565b6122c7565b601b600061228c33611266565b6001600160a01b03166001600160a01b03168152602001908152602001600020546000036122c7576122c76122c033611266565b6000612b90565b505050505050565b600e5460408051635584c4f960e01b815290516000926001600160a01b031691635584c4f991600480830192869291908290030181865afa158015612318573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526123409190810190613a1b565b905060005b81518110156124f757600e5482516001600160a01b039091169063e23a9a529084908490811061237757612377613875565b602002602001015161238833611266565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b03166024820152604401606060405180830381865afa1580156123d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123f69190613ac0565b511561241557604051635a8181f760e01b815260040160405180910390fd5b600e5482516000916001600160a01b031690636e7685309085908590811061243f5761243f613875565b60200260200101516040518263ffffffff1660e01b815260040161246591815260200190565b606060405180830381865afa158015612482573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a69190613b3f565b509150506124b333611266565b6001600160a01b0316816001600160a01b0316036124e457604051635a8181f760e01b815260040160405180910390fd5b50806124ef81613b78565b915050612345565b50600061250384611266565b9050826001600160a01b0316816001600160a01b0316036125375760405163a9e649e960e01b815260040160405180910390fd5b836001600160a01b0316836001600160a01b0316146125565782612559565b60005b6001600160a01b03858116600090815260196020908152604080832080546001600160a01b0319169590941694909417909255601a90915290812054908190036125b65760405163a9e649e960e01b815260040160405180910390fd5b6001600160a01b0382166000908152601b6020526040812080548392906125de908490613862565b90915550506001600160a01b0384166000908152601b60205260408120805483929061260b90849061368c565b90915550506001600160a01b0382166000908152601b6020526040812054900361263a5761263a826000612b90565b6001600160a01b0384166000908152601b602052604090205481900361266557612665846001612b90565b836001600160a01b0316826001600160a01b0316866001600160a01b03167f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f60405160405180910390a45050505050565b60006126c83a63773594004801612dd3565b905060006169785a840301905081810247811115612722576040805133815260208101839052478183015290517fe243285251dce839836e2f4e8bda33b6d0e646af39e99b141e3a211afb1910e59181900360600190a150475b604051600090339083908381818185875af1925050503d8060008114612764576040519150601f19603f3d011682016040523d82523d6000602084013e612769565b606091505b505060408051338152602081018590528215158183015247606082015290519192507fc279025f2293c0e6ca359933c1757bef4d673f2aced8f49ad6facea3a3e623a6919081900360800190a15050505050565b60165460ff16156127e1576040516313d0ff5960e31b815260040160405180910390fd5b6000811180156127f057504281105b1561280e57604051630309cb8760e51b815260040160405180910390fd5b600f546001600160801b0316811580159061283157508061282f4284613862565b115b1561284357612840814261368c565b91505b82600081900361286657604051630309cb8760e51b815260040160405180910390fd5b6000805b828110156128b25761289487878381811061288757612887613875565b9050602002013586612de2565b61289e908361368c565b9150806128aa81613b78565b91505061286a565b50336000908152601a6020526040812080548392906128d290849061368c565b90915550819050601b60006128e633611266565b6001600160a01b03166001600160a01b031681526020019081526020016000206000828254612915919061368c565b9250508190555080601c600082825461292e919061368c565b90915550819050601b600061294233611266565b6001600160a01b03166001600160a01b0316815260200190815260200160002054036122c7576122c761297433611266565b6001612b90565b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a9004806129955750819003601f19909101908152919050565b6000806129cb846114b3565b9050336001600160a01b038216146129f65760405163ea8e4eb560e01b815260040160405180910390fd5b600084815260186020526040902054421015612a2557604051635a8181f760e01b815260040160405180910390fd5b6000612710851015612a835750600c54601f80546001600160a01b0390921691600090612a5a906001600160801b0316613b91565b91906101000a8154816001600160801b0302191690836001600160801b03160217905550612ad8565b50600d54601f80546001600160a01b0390921691601090612ab390600160801b90046001600160801b0316613b91565b91906101000a8154816001600160801b0302191690836001600160801b031602179055505b604051632142170760e11b81523060048201526001600160a01b038581166024830152604482018790528216906342842e0e90606401600060405180830381600087803b158015612b2857600080fd5b505af1158015612b3c573d6000803e3d6000fd5b505050506000612b4b866117f7565b9050612b5686613025565b60008681526018602052604090205415612b8757600086815260186020908152604080832083905560179091528120555b95945050505050565b600e546040516331b7e5d760e11b81526001600160a01b038481166004830152600092839283929091169063636fcbae90602401606060405180830381865afa158015612be1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c059190613957565b9250925092506000806000600e60009054906101000a90046001600160a01b03166001600160a01b031663afb417616040518163ffffffff1660e01b8152600401606060405180830381865afa158015612c63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c879190613957565b9250925092508615612d3057600e546001600160a01b0316635753f769612cae88866139c4565b612cb888866139c4565b612cc288866139c4565b60405160e085901b6001600160e01b03191681526001600160401b03938416600482015291831660248301529091166044820152606401600060405180830381600087803b158015612d1357600080fd5b505af1158015612d27573d6000803e3d6000fd5b50505050612dc9565b600e546001600160a01b0316635753f769612d4b8886613bb4565b612d558886613bb4565b612d5f8886613bb4565b60405160e085901b6001600160e01b03191681526001600160401b03938416600482015291831660248301529091166044820152606401600060405180830381600087803b158015612db057600080fd5b505af1158015612dc4573d6000803e3d6000fd5b505050505b5050505050505050565b600081831061128f5781611291565b60008115612e5e576000838152601860205260408120839055600f546001600160801b0380821691600160801b900416612e1c4286613862565b612e26919061388b565b612e3091906138a2565b90506127108410612e4b57612e466002826138a2565b612e4d565b805b600085815260176020526040902055505b6000612710841015612ebd5750600c54601f80546001600160a01b03909216916001600160801b0316906000612e9383613bd4565b91906101000a8154816001600160801b0302191690836001600160801b0316021790555050612f13565b50600d54601f80546001600160a01b0390921691600160801b90046001600160801b0316906010612eed83613bd4565b91906101000a8154816001600160801b0302191690836001600160801b03160217905550505b6040516331a9108f60e11b8152600481018590526000906001600160a01b03831690636352211e90602401602060405180830381865afa158015612f5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f7f9190613bfa565b9050336001600160a01b03821614612faa5760405163ea8e4eb560e01b815260040160405180910390fd5b6040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018790528316906323b872dd90606401600060405180830381600087803b158015612ffa57600080fd5b505af115801561300e573d6000803e3d6000fd5b5050505061301c33866130f2565b612b87856117f7565b6000818152600260205260409020546001600160a01b0316806130775760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b6044820152606401610d8e565b6001600160a01b038116600081815260036020908152604080832080546000190190558583526002825280832080546001600160a01b031990811690915560049092528083208054909216909155518492907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6001600160a01b03821661313c5760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610d8e565b6000818152600260205260409020546001600160a01b0316156131925760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b6044820152606401610d8e565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6001600160e01b0319811681146114b057600080fd5b60006020828403121561322557600080fd5b8135611291816131fd565b60005b8381101561324b578181015183820152602001613233565b50506000910152565b6020815260008251806020840152613273816040850160208701613230565b601f01601f19169190910160400192915050565b60006020828403121561329957600080fd5b5035919050565b6001600160a01b03811681146114b057600080fd5b600080604083850312156132c857600080fd5b82356132d3816132a0565b946020939093013593505050565b6000806000606084860312156132f657600080fd5b8335613301816132a0565b92506020840135613311816132a0565b929592945050506040919091013590565b60006020828403121561333457600080fd5b8135611291816132a0565b6001600160401b03811681146114b057600080fd5b60006020828403121561336657600080fd5b81356112918161333f565b60008083601f84011261338357600080fd5b5081356001600160401b0381111561339a57600080fd5b6020830191508360208260051b85010111156133b557600080fd5b9250929050565b6000806000604084860312156133d157600080fd5b83356001600160401b038111156133e757600080fd5b6133f386828701613371565b9094509250506020840135613407816132a0565b809150509250925092565b80151581146114b057600080fd5b60008060006060848603121561343557600080fd5b833561344081613412565b9250602084013561331181613412565b60006020828403121561346257600080fd5b81356001600160801b038116811461129157600080fd5b60008083601f84011261348b57600080fd5b5081356001600160401b038111156134a257600080fd5b6020830191508360208285010111156133b557600080fd5b600080602083850312156134cd57600080fd5b82356001600160401b038111156134e357600080fd5b6134ef85828601613479565b90969095509350505050565b60008060006040848603121561351057600080fd5b83356001600160401b0381111561352657600080fd5b61353286828701613371565b909790965060209590950135949350505050565b6000806040838503121561355957600080fd5b8235613564816132a0565b9150602083013561357481613412565b809150509250929050565b60008060008060006080868803121561359757600080fd5b85356135a2816132a0565b945060208601356135b2816132a0565b93506040860135925060608601356001600160401b038111156135d457600080fd5b6135e088828901613479565b969995985093965092949392505050565b60006020828403121561360357600080fd5b813561129181613412565b6000806040838503121561362157600080fd5b823561362c816132a0565b91506020830135613574816132a0565b600181811c9082168061365057607f821691505b60208210810361367057634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610c7857610c78613676565b6000602082840312156136b157600080fd5b8151611291816131fd565b634e487b7160e01b600052604160045260246000fd5b601f821115610f8057600081815260208120601f850160051c810160208610156136f95750805b601f850160051c820191505b818110156122c757828155600101613705565b6001600160401b0383111561372f5761372f6136bc565b6137438361373d835461363c565b836136d2565b6000601f841160018114613777576000851561375f5750838201355b600019600387901b1c1916600186901b178355611aea565b600083815260209020601f19861690835b828110156137a85786850135825560209485019460019092019101613788565b50868210156137c55760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60006020808352600084546137eb8161363c565b8084870152604060018084166000811461380c576001811461382657613854565b60ff1985168984015283151560051b890183019550613854565b896000528660002060005b8581101561384c5781548b8201860152908301908801613831565b8a0184019650505b509398975050505050505050565b81810381811115610c7857610c78613676565b634e487b7160e01b600052603260045260246000fd5b8082028115828204841417610c7857610c78613676565b6000826138bf57634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b038681168252851660208201526040810184905260806060820181905281018290526000828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b6000835161392a818460208801613230565b83519083019061393e818360208801613230565b64173539b7b760d91b9101908152600501949350505050565b60008060006060848603121561396c57600080fd5b83516139778161333f565b60208501519093506139888161333f565b60408501519092506134078161333f565b6001600160401b038181168382160280821691908281146139bc576139bc613676565b505092915050565b6001600160401b038181168382160190808211156139e4576139e4613676565b5092915050565b604051601f8201601f191681016001600160401b0381118282101715613a1357613a136136bc565b604052919050565b60006020808385031215613a2e57600080fd5b82516001600160401b0380821115613a4557600080fd5b818501915085601f830112613a5957600080fd5b815181811115613a6b57613a6b6136bc565b8060051b9150613a7c8483016139eb565b8181529183018401918481019088841115613a9657600080fd5b938501935b83851015613ab457845182529385019390850190613a9b565b98975050505050505050565b600060608284031215613ad257600080fd5b604051606081018181106001600160401b0382111715613af457613af46136bc565b6040528251613b0281613412565b8152602083015160ff81168114613b1857600080fd5b6020820152604083015162ffffff81168114613b3357600080fd5b60408201529392505050565b600080600060608486031215613b5457600080fd5b835192506020840151613b66816132a0565b80925050604084015190509250925092565b600060018201613b8a57613b8a613676565b5060010190565b60006001600160801b03821680613baa57613baa613676565b6000190192915050565b6001600160401b038281168282160390808211156139e4576139e4613676565b60006001600160801b03808316818103613bf057613bf0613676565b6001019392505050565b600060208284031215613c0c57600080fd5b8151611291816132a056fea2646970667358221220d89063dda8c1849b792890900b569e220384c433db58c6e6223685c6dfeec3a064736f6c634300081100330000000000000000000000001fec856e25f757fed06eb90548b0224e910957380000000000000000000000002cfbcb9e9c3d1ab06ef332f535266444aa8d9570000000000000000000000000053d938a4d2a6df86d837d66a037444d7bacf3b90000000000000000000000003c43e86c4c3ba4d2b6c15439d2d97556985814a2000000000000000000000000b7ccb0ee5c06562282048f95e27c73b148dcb6d20000000000000000000000002630ef1e79e38ec1e42db2a891ce1b62542a236200000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000002168747470733a2f2f70756e6b732e33646672616e6b656e70756e6b732e636f6d2f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005168747470733a2f2f676174657761792e70696e6174612e636c6f75642f697066732f516d53464e765a466d5367766b65425a6150646f48586e55346e364243694b783734776257636a376245466153742f000000000000000000000000000000
Deployed Bytecode
0x60806040526004361061038c5760003560e01c80635c975abb116101da578063a2510dae11610101578063d547cfb71161009a578063e8a3d4851161006c578063e8a3d48514610ba4578063e985e9c514610bb9578063eb3ab52414610bf4578063fbfee87614610c1457005b8063d547cfb714610b35578063df864c2314610b4a578063e2c6d41c14610b6a578063e838e56514610b8a57005b8063c34c08e5116100d3578063c34c08e514610ab3578063c87b56dd14610ad3578063d2a3250714610af3578063d340df1d14610b2057005b8063a2510dae14610a33578063a6d80a2714610a53578063b88d4fde14610a73578063bedb86fb14610a9357005b80638f228f93116101735780639ab24eb0116101455780639ab24eb0146109b35780639fd0506d146109d3578063a113607d146109f3578063a22cb46514610a1357005b80638f228f931461093c578063938e3d7b1461096957806394f38e8c1461098957806395d89b411461099e57005b806370a08231116101ac57806370a08231146108af57806376cb22e8146108cf578063857b767b146108ef5780638e4237981461090f57005b80635c975abb1461082a5780636352211e146108445780636d7ae837146108645780636f0ddd221461088f57005b806337a8a0dc116102be5780634d8e60461161025757806358f739e41161022957806358f739e4146107b05780635913f96d146107d05780635bb71b34146107f05780635c19a95c1461080a57005b80634d8e60461461070b5780635437988d14610750578063544d85641461077057806355f804b31461079057005b806342842e0e1161029057806342842e0e1461065f57806345bba9401461067f578063472b884d146106ac57806347e00ebc146106eb57005b806337a8a0dc146105e95780633be8ef3f146106095780633c7b1cd41461061f578063411b007e1461063f57005b806323b872dd116103305780632d88af4a116103025780632d88af4a146105755780632dc4a01714610595578063325b2d96146105b557806336331521146105c957005b806323b872dd146104bf578063285adddd146104df5780632b7ac3f31461053f5780632d3e8c931461055f57005b8063081812fc11610369578063081812fc1461040f578063095ea7b31461045d57806311acc1a71461047d5780631797c84c1461049257005b806301ffc9a71461039557806302e93ec1146103ca57806306fdde03146103ed57005b3661039357005b005b3480156103a157600080fd5b506103b56103b0366004613213565b610c2c565b60405190151581526020015b60405180910390f35b3480156103d657600080fd5b506103df601481565b6040519081526020016103c1565b3480156103f957600080fd5b50610402610c7e565b6040516103c19190613254565b34801561041b57600080fd5b5061044561042a366004613287565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016103c1565b34801561046957600080fd5b506103936104783660046132b5565b610d0c565b34801561048957600080fd5b506103df610df3565b34801561049e57600080fd5b506103df6104ad366004613287565b60186020526000908152604090205481565b3480156104cb57600080fd5b506103936104da3660046132e1565b610e17565b3480156104eb57600080fd5b50601054610515906001600160401b0380821691600160401b8104821691600160801b9091041683565b604080516001600160401b03948516815292841660208401529216918101919091526060016103c1565b34801561054b57600080fd5b50600a54610445906001600160a01b031681565b34801561056b57600080fd5b506103df60155481565b34801561058157600080fd5b50610393610590366004613322565b610e30565b3480156105a157600080fd5b506103936105b0366004613354565b610ef4565b3480156105c157600080fd5b5060016103b5565b3480156105d557600080fd5b506103936105e43660046133bc565b610f75565b3480156105f557600080fd5b50610393610604366004613420565b610f85565b34801561061557600080fd5b506103df61697881565b34801561062b57600080fd5b5061039361063a366004613450565b61101a565b34801561064b57600080fd5b50600654610445906001600160a01b031681565b34801561066b57600080fd5b5061039361067a3660046132e1565b6110c6565b34801561068b57600080fd5b506103df61069a366004613322565b601a6020526000908152604090205481565b3480156106b857600080fd5b50601f546106d390600160801b90046001600160801b031681565b6040516001600160801b0390911681526020016103c1565b3480156106f757600080fd5b50600b54610445906001600160a01b031681565b34801561071757600080fd5b50601f546001600160801b0380821691600160801b9004165b604080516001600160801b039384168152929091166020830152016103c1565b34801561075c57600080fd5b5061039361076b366004613322565b6111b9565b34801561077c57600080fd5b5061044561078b366004613322565b611266565b34801561079c57600080fd5b506103936107ab3660046134ba565b611298565b3480156107bc57600080fd5b506103936107cb366004613354565b611323565b3480156107dc57600080fd5b506103936107eb366004613354565b6113a9565b3480156107fc57600080fd5b506013546103b59060ff1681565b34801561081657600080fd5b50610393610825366004613322565b611434565b34801561083657600080fd5b506016546103b59060ff1681565b34801561085057600080fd5b5061044561085f366004613287565b6114b3565b34801561087057600080fd5b50600f54610730906001600160801b0380821691600160801b90041682565b34801561089b57600080fd5b506103df6108aa366004613287565b61150a565b3480156108bb57600080fd5b506103df6108ca366004613322565b611555565b3480156108db57600080fd5b506103936108ea366004613322565b6115b8565b3480156108fb57600080fd5b5061039361090a3660046134fb565b61164c565b34801561091b57600080fd5b506103df61092a366004613322565b60146020526000908152604090205481565b34801561094857600080fd5b506103df610957366004613322565b60126020526000908152604090205481565b34801561097557600080fd5b506103936109843660046134ba565b6116bb565b34801561099557600080fd5b5061039361172d565b3480156109aa57600080fd5b506104026117bc565b3480156109bf57600080fd5b506103df6109ce366004613322565b6117c9565b3480156109df57600080fd5b50600954610445906001600160a01b031681565b3480156109ff57600080fd5b506103df610a0e366004613287565b6117f7565b348015610a1f57600080fd5b50610393610a2e366004613546565b611877565b348015610a3f57600080fd5b50610393610a4e366004613450565b6118e3565b348015610a5f57600080fd5b50610393610a6e366004613322565b61195c565b348015610a7f57600080fd5b50610393610a8e36600461357f565b611a09565b348015610a9f57600080fd5b50610393610aae3660046135f1565b611af1565b348015610abf57600080fd5b50600854610445906001600160a01b031681565b348015610adf57600080fd5b50610402610aee366004613287565b611b8d565b348015610aff57600080fd5b506103df610b0e366004613322565b601b6020526000908152604090205481565b348015610b2c57600080fd5b50610393611c9f565b348015610b4157600080fd5b50610402611d3c565b348015610b5657600080fd5b506103df610b65366004613322565b611d49565b348015610b7657600080fd5b50600754610445906001600160a01b031681565b348015610b9657600080fd5b506011546103b59060ff1681565b348015610bb057600080fd5b50610402611f1a565b348015610bc557600080fd5b506103b5610bd436600461360e565b600560209081526000928352604080842090915290825290205460ff1681565b348015610c0057600080fd5b50601f546106d3906001600160801b031681565b348015610c2057600080fd5b506103df637735940081565b60006301ffc9a760e01b6001600160e01b031983161480610c5d57506380ac58cd60e01b6001600160e01b03198316145b80610c785750635b5e139f60e01b6001600160e01b03198316145b92915050565b60008054610c8b9061363c565b80601f0160208091040260200160405190810160405280929190818152602001828054610cb79061363c565b8015610d045780601f10610cd957610100808354040283529160200191610d04565b820191906000526020600020905b815481529060010190602001808311610ce757829003601f168201915b505050505081565b6000818152600260205260409020546001600160a01b031633811480610d5557506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b610d975760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064015b60405180910390fd5b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000610e056001600160a01b03611d49565b601c54610e12919061368c565b905090565b604051630517a52360e41b815260040160405180910390fd5b6008546001600160a01b03163314801590610e5657506007546001600160a01b03163314155b8015610e6d57506006546001600160a01b03163314155b15610e8b5760405163ea8e4eb560e01b815260040160405180910390fd5b600954604080516001600160a01b03928316815291831660208301527fce932f997de7d15c38f57fe533bddcd74b6560acb995bdd231da68ed3af22dfe910160405180910390a1600980546001600160a01b0319166001600160a01b0392909216919091179055565b6008546001600160a01b03163314610f1f5760405163ea8e4eb560e01b815260040160405180910390fd5b6010805467ffffffffffffffff19166001600160401b0383169081179091556040519081527fbcf22ad7361f78458cd162cd291861a99c58be848cff080f08d1f6991f8aa49e906020015b60405180910390a150565b610f80838383611f27565b505050565b6008546001600160a01b03163314610fb05760405163ea8e4eb560e01b815260040160405180910390fd5b6011805484151560ff19918216811790925560138054851515921682179055601583905560408051928352602083019190915281018290527fbe343bfc5b51c0897197b9607c9e9a5116528d9a0156e4df5f146d39a020e5219060600160405180910390a1505050565b6008546001600160a01b031633146110455760405163ea8e4eb560e01b815260040160405180910390fd5b806001600160801b031660000361106f57604051630309cb8760e51b815260040160405180910390fd5b600f80546fffffffffffffffffffffffffffffffff19166001600160801b0383169081179091556040519081527fc73c2a2bcffa7fa8054797c5e4f48a83008619e351a32b7ac7f48a8ab2c84c7e90602001610f6a565b6110d1838383610e17565b6001600160a01b0382163b158061117a5750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af115801561114a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116e919061369f565b6001600160e01b031916145b610f805760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606401610d8e565b6006546001600160a01b031633148015906111df57506007546001600160a01b03163314155b156111fd5760405163ea8e4eb560e01b815260040160405180910390fd5b600a54604080516001600160a01b03928316815291831660208301527f2ff4895c300d6993c27f2bb507b4b59d29464dc640af727383451365631ba8b2910160405180910390a1600a80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03808216600090815260196020526040812054909116801561128f5780611291565b825b9392505050565b6006546001600160a01b031633148015906112be57506007546001600160a01b03163314155b156112dc5760405163ea8e4eb560e01b815260040160405180910390fd5b7f5411e8ebf1636d9e83d5fc4900bf80cbac82e8790da2a4c94db4895e889eedf6601d61130a838583613718565b60405161131791906137d7565b60405180910390a15050565b6008546001600160a01b0316331461134e5760405163ea8e4eb560e01b815260040160405180910390fd5b6010805467ffffffffffffffff60801b1916600160801b6001600160401b038416908102919091179091556040519081527ff869d8acf2c70483110d4a26b89c5d2a66debd3c29df24c1000a3be12d2d86d990602001610f6a565b6008546001600160a01b031633146113d45760405163ea8e4eb560e01b815260040160405180910390fd5b601080546fffffffffffffffff00000000000000001916600160401b6001600160401b038416908102919091179091556040519081527f57586600c57c1d016eefd84f76fe9697155dc45acbce61da494952312882381890602001610f6a565b6001600160a01b0381166114455750335b60135460ff16801561147357506015543360009081526014602052604090205442916114709161368c565b11155b156114a65760005a905061148733836122cf565b3360009081526014602052604090204290556114a2816126b6565b5050565b6114b033826122cf565b50565b6000818152600260205260409020546001600160a01b0316806115055760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b6044820152606401610d8e565b919050565b6000612710821061151d57506000919050565b61152b60ff80841690613862565b6020600884901c6028811061154257611542613875565b0154901c600116600a610c78919061388b565b60006001600160a01b03821661159c5760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606401610d8e565b506001600160a01b031660009081526003602052604090205490565b6006546001600160a01b031633146115e35760405163ea8e4eb560e01b815260040160405180910390fd5b600b54604080516001600160a01b03928316815291831660208301527fb81319a9bb8b17fae110bb40da7c54c734732f52530117d5700894fb45e388bf910160405180910390a1600b80546001600160a01b0319166001600160a01b0392909216919091179055565b60115460ff16801561167a57506015543360009081526012602052604090205442916116779161368c565b11155b156116b05760005a905061168f8484846127bd565b3360009081526012602052604090204290556116aa816126b6565b50505050565b610f808383836127bd565b6006546001600160a01b031633148015906116e157506007546001600160a01b03163314155b156116ff5760405163ea8e4eb560e01b815260040160405180910390fd5b7fd5ee5eaf65263bab5d569890714d123ad48a9e54409d35e71d374f3dd300bba0601e61130a838583613718565b6006546001600160a01b031633146117585760405163ea8e4eb560e01b815260040160405180910390fd5b600654604080516001600160a01b039092168252600060208301527fdb8dcc8712c6b41e8da769643922645a1221ad9c79beaf28920e2a5d5a893a62910160405180910390a1600680546001600160a01b0319908116909155600b80549091169055565b60018054610c8b9061363c565b60006117d482611d49565b6001600160a01b0383166000908152601b6020526040902054610c78919061368c565b600080611803836114b3565b6001600160a01b03160361182a57604051634a1850bf60e11b815260040160405180910390fd5b6000612710831061184657611841600260146138a2565b611849565b60145b90506118548361150a565b60008481526017602052604090205461186d908361368c565b611291919061368c565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6008546001600160a01b0316331461190e5760405163ea8e4eb560e01b815260040160405180910390fd5b600f80546001600160801b03908116600160801b918416918202179091556040519081527fe213d3449d5ab338ffd40007fe5a97d45d0418c1f0dc502f7925cda3fc78c8af90602001610f6a565b6006546001600160a01b0316331480159061198257506007546001600160a01b03163314155b156119a05760405163ea8e4eb560e01b815260040160405180910390fd5b600754604080516001600160a01b03928316815291831660208301527f66a019a63262ba85572d64812414a277be4e9069feaf5b182f95e4b6e529c3a4910160405180910390a1600780546001600160a01b0319166001600160a01b0392909216919091179055565b611a14858585610e17565b6001600160a01b0384163b1580611aab5750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a0290611a5c9033908a908990899089906004016138c4565b6020604051808303816000875af1158015611a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9f919061369f565b6001600160e01b031916145b611aea5760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606401610d8e565b5050505050565b6006546001600160a01b03163314801590611b1757506007546001600160a01b03163314155b8015611b2e57506009546001600160a01b03163314155b15611b4c5760405163ea8e4eb560e01b815260040160405180910390fd5b6016805460ff19168215159081179091556040519081527f608c68cec60453b4c976616f2c75d7dc520288e1fcf03656b57f7d7bddc8492090602001610f6a565b60606000611b9a836114b3565b6001600160a01b031603611bc157604051634a1850bf60e11b815260040160405180910390fd5b6000601d8054611bd09061363c565b80601f0160208091040260200160405190810160405280929190818152602001828054611bfc9061363c565b8015611c495780601f10611c1e57610100808354040283529160200191611c49565b820191906000526020600020905b815481529060010190602001808311611c2c57829003601f168201915b505050505090506000815111611c6e5760405180602001604052806000815250611291565b80611c788461297b565b604051602001611c89929190613918565b6040516020818303038152906040529392505050565b600b546001600160a01b03163314611cca5760405163ea8e4eb560e01b815260040160405180910390fd5b600654600b54604080516001600160a01b0393841681529290911660208301527fdb8dcc8712c6b41e8da769643922645a1221ad9c79beaf28920e2a5d5a893a62910160405180910390a1600b8054600680546001600160a01b03199081166001600160a01b03841617909155169055565b601d8054610c8b9061363c565b60008080806002600160a01b03196001600160a01b03861601611de957600e60009054906101000a90046001600160a01b03166001600160a01b031663afb417616040518163ffffffff1660e01b8152600401606060405180830381865afa158015611db9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ddd9190613957565b91945092509050611e89565b6001600160a01b0385166000908152601b60205260408120549003611e1357506000949350505050565b600e546040516331b7e5d760e11b81526001600160a01b0387811660048301529091169063636fcbae90602401606060405180830381865afa158015611e5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e819190613957565b919450925090505b604080516060810182526010546001600160401b038082168352600160401b820481166020840152600160801b9091041691810182905290606490611ece9084613999565b6020830151611edd9086613999565b8351611ee99088613999565b611ef391906139c4565b611efd91906139c4565b6001600160401b0316611f1091906138a2565b9695505050505050565b601e8054610c8b9061363c565b600e5460408051635584c4f960e01b815290516000926001600160a01b031691635584c4f991600480830192869291908290030181865afa158015611f70573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611f989190810190613a1b565b905060005b815181101561214f57600e5482516001600160a01b039091169063e23a9a5290849084908110611fcf57611fcf613875565b6020026020010151611fe033611266565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b03166024820152604401606060405180830381865afa15801561202a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204e9190613ac0565b511561206d57604051635a8181f760e01b815260040160405180910390fd5b600e5482516000916001600160a01b031690636e7685309085908590811061209757612097613875565b60200260200101516040518263ffffffff1660e01b81526004016120bd91815260200190565b606060405180830381865afa1580156120da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120fe9190613b3f565b5091505061210b33611266565b6001600160a01b0316816001600160a01b03160361213c57604051635a8181f760e01b815260040160405180910390fd5b508061214781613b78565b915050611f9d565b5082600081900361217357604051630309cb8760e51b815260040160405180910390fd5b6000805b828110156121bf576121a187878381811061219457612194613875565b90506020020135866129bf565b6121ab908361368c565b9150806121b781613b78565b915050612177565b50336000908152601a6020526040812080548392906121df908490613862565b90915550819050601b60006121f333611266565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546122229190613862565b9250508190555080601c600082825461223b9190613862565b9091555061224a905033611266565b6001600160a01b0316330361227f57336000908152601b6020526040812054900361227a5761227a336000612b90565b6122c7565b601b600061228c33611266565b6001600160a01b03166001600160a01b03168152602001908152602001600020546000036122c7576122c76122c033611266565b6000612b90565b505050505050565b600e5460408051635584c4f960e01b815290516000926001600160a01b031691635584c4f991600480830192869291908290030181865afa158015612318573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526123409190810190613a1b565b905060005b81518110156124f757600e5482516001600160a01b039091169063e23a9a529084908490811061237757612377613875565b602002602001015161238833611266565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b03166024820152604401606060405180830381865afa1580156123d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123f69190613ac0565b511561241557604051635a8181f760e01b815260040160405180910390fd5b600e5482516000916001600160a01b031690636e7685309085908590811061243f5761243f613875565b60200260200101516040518263ffffffff1660e01b815260040161246591815260200190565b606060405180830381865afa158015612482573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a69190613b3f565b509150506124b333611266565b6001600160a01b0316816001600160a01b0316036124e457604051635a8181f760e01b815260040160405180910390fd5b50806124ef81613b78565b915050612345565b50600061250384611266565b9050826001600160a01b0316816001600160a01b0316036125375760405163a9e649e960e01b815260040160405180910390fd5b836001600160a01b0316836001600160a01b0316146125565782612559565b60005b6001600160a01b03858116600090815260196020908152604080832080546001600160a01b0319169590941694909417909255601a90915290812054908190036125b65760405163a9e649e960e01b815260040160405180910390fd5b6001600160a01b0382166000908152601b6020526040812080548392906125de908490613862565b90915550506001600160a01b0384166000908152601b60205260408120805483929061260b90849061368c565b90915550506001600160a01b0382166000908152601b6020526040812054900361263a5761263a826000612b90565b6001600160a01b0384166000908152601b602052604090205481900361266557612665846001612b90565b836001600160a01b0316826001600160a01b0316866001600160a01b03167f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f60405160405180910390a45050505050565b60006126c83a63773594004801612dd3565b905060006169785a840301905081810247811115612722576040805133815260208101839052478183015290517fe243285251dce839836e2f4e8bda33b6d0e646af39e99b141e3a211afb1910e59181900360600190a150475b604051600090339083908381818185875af1925050503d8060008114612764576040519150601f19603f3d011682016040523d82523d6000602084013e612769565b606091505b505060408051338152602081018590528215158183015247606082015290519192507fc279025f2293c0e6ca359933c1757bef4d673f2aced8f49ad6facea3a3e623a6919081900360800190a15050505050565b60165460ff16156127e1576040516313d0ff5960e31b815260040160405180910390fd5b6000811180156127f057504281105b1561280e57604051630309cb8760e51b815260040160405180910390fd5b600f546001600160801b0316811580159061283157508061282f4284613862565b115b1561284357612840814261368c565b91505b82600081900361286657604051630309cb8760e51b815260040160405180910390fd5b6000805b828110156128b25761289487878381811061288757612887613875565b9050602002013586612de2565b61289e908361368c565b9150806128aa81613b78565b91505061286a565b50336000908152601a6020526040812080548392906128d290849061368c565b90915550819050601b60006128e633611266565b6001600160a01b03166001600160a01b031681526020019081526020016000206000828254612915919061368c565b9250508190555080601c600082825461292e919061368c565b90915550819050601b600061294233611266565b6001600160a01b03166001600160a01b0316815260200190815260200160002054036122c7576122c761297433611266565b6001612b90565b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a9004806129955750819003601f19909101908152919050565b6000806129cb846114b3565b9050336001600160a01b038216146129f65760405163ea8e4eb560e01b815260040160405180910390fd5b600084815260186020526040902054421015612a2557604051635a8181f760e01b815260040160405180910390fd5b6000612710851015612a835750600c54601f80546001600160a01b0390921691600090612a5a906001600160801b0316613b91565b91906101000a8154816001600160801b0302191690836001600160801b03160217905550612ad8565b50600d54601f80546001600160a01b0390921691601090612ab390600160801b90046001600160801b0316613b91565b91906101000a8154816001600160801b0302191690836001600160801b031602179055505b604051632142170760e11b81523060048201526001600160a01b038581166024830152604482018790528216906342842e0e90606401600060405180830381600087803b158015612b2857600080fd5b505af1158015612b3c573d6000803e3d6000fd5b505050506000612b4b866117f7565b9050612b5686613025565b60008681526018602052604090205415612b8757600086815260186020908152604080832083905560179091528120555b95945050505050565b600e546040516331b7e5d760e11b81526001600160a01b038481166004830152600092839283929091169063636fcbae90602401606060405180830381865afa158015612be1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c059190613957565b9250925092506000806000600e60009054906101000a90046001600160a01b03166001600160a01b031663afb417616040518163ffffffff1660e01b8152600401606060405180830381865afa158015612c63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c879190613957565b9250925092508615612d3057600e546001600160a01b0316635753f769612cae88866139c4565b612cb888866139c4565b612cc288866139c4565b60405160e085901b6001600160e01b03191681526001600160401b03938416600482015291831660248301529091166044820152606401600060405180830381600087803b158015612d1357600080fd5b505af1158015612d27573d6000803e3d6000fd5b50505050612dc9565b600e546001600160a01b0316635753f769612d4b8886613bb4565b612d558886613bb4565b612d5f8886613bb4565b60405160e085901b6001600160e01b03191681526001600160401b03938416600482015291831660248301529091166044820152606401600060405180830381600087803b158015612db057600080fd5b505af1158015612dc4573d6000803e3d6000fd5b505050505b5050505050505050565b600081831061128f5781611291565b60008115612e5e576000838152601860205260408120839055600f546001600160801b0380821691600160801b900416612e1c4286613862565b612e26919061388b565b612e3091906138a2565b90506127108410612e4b57612e466002826138a2565b612e4d565b805b600085815260176020526040902055505b6000612710841015612ebd5750600c54601f80546001600160a01b03909216916001600160801b0316906000612e9383613bd4565b91906101000a8154816001600160801b0302191690836001600160801b0316021790555050612f13565b50600d54601f80546001600160a01b0390921691600160801b90046001600160801b0316906010612eed83613bd4565b91906101000a8154816001600160801b0302191690836001600160801b03160217905550505b6040516331a9108f60e11b8152600481018590526000906001600160a01b03831690636352211e90602401602060405180830381865afa158015612f5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f7f9190613bfa565b9050336001600160a01b03821614612faa5760405163ea8e4eb560e01b815260040160405180910390fd5b6040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018790528316906323b872dd90606401600060405180830381600087803b158015612ffa57600080fd5b505af115801561300e573d6000803e3d6000fd5b5050505061301c33866130f2565b612b87856117f7565b6000818152600260205260409020546001600160a01b0316806130775760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b6044820152606401610d8e565b6001600160a01b038116600081815260036020908152604080832080546000190190558583526002825280832080546001600160a01b031990811690915560049092528083208054909216909155518492907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6001600160a01b03821661313c5760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610d8e565b6000818152600260205260409020546001600160a01b0316156131925760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b6044820152606401610d8e565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6001600160e01b0319811681146114b057600080fd5b60006020828403121561322557600080fd5b8135611291816131fd565b60005b8381101561324b578181015183820152602001613233565b50506000910152565b6020815260008251806020840152613273816040850160208701613230565b601f01601f19169190910160400192915050565b60006020828403121561329957600080fd5b5035919050565b6001600160a01b03811681146114b057600080fd5b600080604083850312156132c857600080fd5b82356132d3816132a0565b946020939093013593505050565b6000806000606084860312156132f657600080fd5b8335613301816132a0565b92506020840135613311816132a0565b929592945050506040919091013590565b60006020828403121561333457600080fd5b8135611291816132a0565b6001600160401b03811681146114b057600080fd5b60006020828403121561336657600080fd5b81356112918161333f565b60008083601f84011261338357600080fd5b5081356001600160401b0381111561339a57600080fd5b6020830191508360208260051b85010111156133b557600080fd5b9250929050565b6000806000604084860312156133d157600080fd5b83356001600160401b038111156133e757600080fd5b6133f386828701613371565b9094509250506020840135613407816132a0565b809150509250925092565b80151581146114b057600080fd5b60008060006060848603121561343557600080fd5b833561344081613412565b9250602084013561331181613412565b60006020828403121561346257600080fd5b81356001600160801b038116811461129157600080fd5b60008083601f84011261348b57600080fd5b5081356001600160401b038111156134a257600080fd5b6020830191508360208285010111156133b557600080fd5b600080602083850312156134cd57600080fd5b82356001600160401b038111156134e357600080fd5b6134ef85828601613479565b90969095509350505050565b60008060006040848603121561351057600080fd5b83356001600160401b0381111561352657600080fd5b61353286828701613371565b909790965060209590950135949350505050565b6000806040838503121561355957600080fd5b8235613564816132a0565b9150602083013561357481613412565b809150509250929050565b60008060008060006080868803121561359757600080fd5b85356135a2816132a0565b945060208601356135b2816132a0565b93506040860135925060608601356001600160401b038111156135d457600080fd5b6135e088828901613479565b969995985093965092949392505050565b60006020828403121561360357600080fd5b813561129181613412565b6000806040838503121561362157600080fd5b823561362c816132a0565b91506020830135613574816132a0565b600181811c9082168061365057607f821691505b60208210810361367057634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610c7857610c78613676565b6000602082840312156136b157600080fd5b8151611291816131fd565b634e487b7160e01b600052604160045260246000fd5b601f821115610f8057600081815260208120601f850160051c810160208610156136f95750805b601f850160051c820191505b818110156122c757828155600101613705565b6001600160401b0383111561372f5761372f6136bc565b6137438361373d835461363c565b836136d2565b6000601f841160018114613777576000851561375f5750838201355b600019600387901b1c1916600186901b178355611aea565b600083815260209020601f19861690835b828110156137a85786850135825560209485019460019092019101613788565b50868210156137c55760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60006020808352600084546137eb8161363c565b8084870152604060018084166000811461380c576001811461382657613854565b60ff1985168984015283151560051b890183019550613854565b896000528660002060005b8581101561384c5781548b8201860152908301908801613831565b8a0184019650505b509398975050505050505050565b81810381811115610c7857610c78613676565b634e487b7160e01b600052603260045260246000fd5b8082028115828204841417610c7857610c78613676565b6000826138bf57634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b038681168252851660208201526040810184905260806060820181905281018290526000828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b6000835161392a818460208801613230565b83519083019061393e818360208801613230565b64173539b7b760d91b9101908152600501949350505050565b60008060006060848603121561396c57600080fd5b83516139778161333f565b60208501519093506139888161333f565b60408501519092506134078161333f565b6001600160401b038181168382160280821691908281146139bc576139bc613676565b505092915050565b6001600160401b038181168382160190808211156139e4576139e4613676565b5092915050565b604051601f8201601f191681016001600160401b0381118282101715613a1357613a136136bc565b604052919050565b60006020808385031215613a2e57600080fd5b82516001600160401b0380821115613a4557600080fd5b818501915085601f830112613a5957600080fd5b815181811115613a6b57613a6b6136bc565b8060051b9150613a7c8483016139eb565b8181529183018401918481019088841115613a9657600080fd5b938501935b83851015613ab457845182529385019390850190613a9b565b98975050505050505050565b600060608284031215613ad257600080fd5b604051606081018181106001600160401b0382111715613af457613af46136bc565b6040528251613b0281613412565b8152602083015160ff81168114613b1857600080fd5b6020820152604083015162ffffff81168114613b3357600080fd5b60408201529392505050565b600080600060608486031215613b5457600080fd5b835192506020840151613b66816132a0565b80925050604084015190509250925092565b600060018201613b8a57613b8a613676565b5060010190565b60006001600160801b03821680613baa57613baa613676565b6000190192915050565b6001600160401b038281168282160390808211156139e4576139e4613676565b60006001600160801b03808316818103613bf057613bf0613676565b6001019392505050565b600060208284031215613c0c57600080fd5b8151611291816132a056fea2646970667358221220d89063dda8c1849b792890900b569e220384c433db58c6e6223685c6dfeec3a064736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001fec856e25f757fed06eb90548b0224e910957380000000000000000000000002cfbcb9e9c3d1ab06ef332f535266444aa8d9570000000000000000000000000053d938a4d2a6df86d837d66a037444d7bacf3b90000000000000000000000003c43e86c4c3ba4d2b6c15439d2d97556985814a2000000000000000000000000b7ccb0ee5c06562282048f95e27c73b148dcb6d20000000000000000000000002630ef1e79e38ec1e42db2a891ce1b62542a236200000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000002168747470733a2f2f70756e6b732e33646672616e6b656e70756e6b732e636f6d2f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005168747470733a2f2f676174657761792e70696e6174612e636c6f75642f697066732f516d53464e765a466d5367766b65425a6150646f48586e55346e364243694b783734776257636a376245466153742f000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _frankenpunks (address): 0x1FEC856e25F757FeD06eB90548B0224E91095738
Arg [1] : _frankenmonsters (address): 0x2cfBCB9e9C3D1ab06eF332f535266444aa8d9570
Arg [2] : _governance (address): 0x053d938a4d2A6DF86D837D66a037444D7bACF3B9
Arg [3] : _executor (address): 0x3c43e86C4C3ba4D2b6C15439D2d97556985814a2
Arg [4] : _founders (address): 0xb7cCB0Ee5C06562282048F95e27C73b148Dcb6d2
Arg [5] : _council (address): 0x2630eF1E79E38Ec1E42db2a891CE1b62542A2362
Arg [6] : _baseTokenURI (string): https://punks.3dfrankenpunks.com/
Arg [7] : _contractURI (string): https://gateway.pinata.cloud/ipfs/QmSFNvZFmSgvkeBZaPdoHXnU4n6BCiKx74wbWcj7bEFaSt/
-----Encoded View---------------
15 Constructor Arguments found :
Arg [0] : 0000000000000000000000001fec856e25f757fed06eb90548b0224e91095738
Arg [1] : 0000000000000000000000002cfbcb9e9c3d1ab06ef332f535266444aa8d9570
Arg [2] : 000000000000000000000000053d938a4d2a6df86d837d66a037444d7bacf3b9
Arg [3] : 0000000000000000000000003c43e86c4c3ba4d2b6c15439d2d97556985814a2
Arg [4] : 000000000000000000000000b7ccb0ee5c06562282048f95e27c73b148dcb6d2
Arg [5] : 0000000000000000000000002630ef1e79e38ec1e42db2a891ce1b62542a2362
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000021
Arg [9] : 68747470733a2f2f70756e6b732e33646672616e6b656e70756e6b732e636f6d
Arg [10] : 2f00000000000000000000000000000000000000000000000000000000000000
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000051
Arg [12] : 68747470733a2f2f676174657761792e70696e6174612e636c6f75642f697066
Arg [13] : 732f516d53464e765a466d5367766b65425a6150646f48586e55346e36424369
Arg [14] : 4b783734776257636a376245466153742f000000000000000000000000000000
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.