Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
There are no matching entriesUpdate your filters to view other transactions | |||||||||
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Rewards
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0
/// @title The client incentives rewards logic
/*********************************
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░█████████░░█████████░░░ *
* ░░░░░░██░░░████░░██░░░████░░░ *
* ░░██████░░░████████░░░████░░░ *
* ░░██░░██░░░████░░██░░░████░░░ *
* ░░██░░██░░░████░░██░░░████░░░ *
* ░░░░░░█████████░░█████████░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
*********************************/
pragma solidity ^0.8.19;
import { INounsDAOLogic } from '../interfaces/INounsDAOLogic.sol';
import { INounsAuctionHouseV2 } from '../interfaces/INounsAuctionHouseV2.sol';
import { NounsDAOTypes } from '../governance/NounsDAOInterfaces.sol';
import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import { UUPSUpgradeable } from '@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol';
import { SafeERC20 } from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import { PausableUpgradeable } from '@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol';
import { ClientRewardsMemoryMapping } from '../libs/ClientRewardsMemoryMapping.sol';
import { GasRefund } from '../libs/GasRefund.sol';
import { INounsClientTokenDescriptor } from './INounsClientTokenDescriptor.sol';
import { INounsClientTokenTypes } from './INounsClientTokenTypes.sol';
import { OwnableUpgradeable } from '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol';
import { ERC721Upgradeable } from '@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol';
import { SafeCast } from '@openzeppelin/contracts/utils/math/SafeCast.sol';
contract Rewards is
UUPSUpgradeable,
PausableUpgradeable,
OwnableUpgradeable,
ERC721Upgradeable,
INounsClientTokenTypes
{
using SafeERC20 for IERC20;
using ClientRewardsMemoryMapping for ClientRewardsMemoryMapping.Mapping;
error RewardsDisabled();
error OnlyOwnerOrAdmin();
error OnlyNFTOwner();
error LastNounIdMustBeSettled();
error LastNounIdMustBeHigher();
/**
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
* EVENTS
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
*/
event ClientRegistered(uint32 indexed clientId, string name, string description);
event ClientUpdated(uint32 indexed clientId, string name, string description);
event ClientRewarded(uint32 indexed clientId, uint256 amount);
event ClientBalanceWithdrawal(uint32 indexed clientId, uint256 amount, address to);
event AuctionRewardsUpdated(uint256 firstAuctionId, uint256 lastAuctionId);
event ProposalRewardsUpdated(
uint32 firstProposalId,
uint32 lastProposalId,
uint256 firstAuctionIdForRevenue,
uint256 lastAuctionIdForRevenue,
uint256 auctionRevenue,
uint256 rewardPerProposal,
uint256 rewardPerVote
);
event ClientApprovalSet(uint32 indexed clientId, bool approved);
event AuctionRewardsEnabled(uint32 nextAuctionIdToReward);
event AuctionRewardsDisabled();
event ProposalRewardsEnabled(uint32 nextProposalIdToReward, uint32 nextProposalRewardFirstAuctionId);
event ProposalRewardsDisabled();
/**
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
* IMMUTABLES
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
*/
/// @notice Nouns DAO proxy contract
INounsDAOLogic public immutable nounsDAO;
/// @notice Nouns Auction House proxy contract
INounsAuctionHouseV2 public immutable auctionHouse;
/**
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
* STORAGE VARIABLES
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
*/
struct ProposalRewardParams {
/// @dev The minimum reward period for proposal updates if number of proposals is below `numProposalsEnoughForReward`
uint32 minimumRewardPeriod;
/// @dev The number of proposals required for an update before `minimumRewardPeriod` has passed
uint8 numProposalsEnoughForReward;
/// @dev How much bips out of the auction revenue during this period to use for rewarding proposal creation
uint16 proposalRewardBps;
/// @dev How much bips out of the auction revenue during this period to use for rewarding proposal voting
uint16 votingRewardBps;
/// @dev How many (in bips) FOR votes out of total votes are required for a proposal to be eligible for rewards
uint16 proposalEligibilityQuorumBps;
}
struct AuctionRewardParams {
/// @dev How much bips out of auction revnue to use for rewarding auction bidding
uint16 auctionRewardBps;
/// @dev Minimum number of auctions between updates. Zero means 1 auction is enough.
uint8 minimumAuctionsBetweenUpdates;
}
/// @custom:storage-location erc7201:nouns.rewards
struct RewardsStorage {
/// @dev The next client token id to be minted
uint32 nextTokenId;
/// @dev Flag controlling if auction rewards are enabled
bool auctionRewardsEnabled;
/// @dev Used for auction rewards state
uint32 nextAuctionIdToReward;
/// @dev Flag controlling if proposal rewards are enabled
bool proposalRewardsEnabled;
/// @dev Used for proposal rewards state
uint32 nextProposalIdToReward;
/// @dev The first auction id to consider for revenue tracking on the next proposal rewards update
uint32 nextProposalRewardFirstAuctionId;
/// @dev Last time the proposal rewards update was performed
uint40 lastProposalRewardsUpdate;
/// @dev Params for both proposal rewards
ProposalRewardParams proposalRewardParams;
/// @dev Params for auction rewards
AuctionRewardParams auctionRewardParams;
/// @dev An ETH pegged ERC20 token to use for rewarding
IERC20 ethToken;
/// @dev admin account able to pause/unpause the contract in case of a quick response is needed
address admin;
/// @dev client metadata per clientId, including rewards balances, name, description
mapping(uint32 clientId => ClientMetadata) _clientMetadata;
/// @dev The client NFT descriptor
address descriptor;
}
/// @dev This is a ERC-7201 storage location, calculated using:
/// @dev keccak256(abi.encode(uint256(keccak256("nouns.rewards")) - 1)) & ~bytes32(uint256(0xff));
bytes32 public constant RewardsStorageLocation = 0x9a06af3161ac5b0c3de4e6c981ab9d9f60b530386f5eaae00d541393fbecd700;
function _getRewardsStorage() private pure returns (RewardsStorage storage $) {
assembly {
$.slot := RewardsStorageLocation
}
}
/**
* @dev Reverts if called by any account other than the owner or admin.
*/
modifier onlyOwnerOrAdmin() {
RewardsStorage storage $ = _getRewardsStorage();
if (!(owner() == _msgSender() || $.admin == _msgSender())) revert OnlyOwnerOrAdmin();
_;
}
constructor(address nounsDAO_, address auctionHouse_) initializer {
nounsDAO = INounsDAOLogic(nounsDAO_);
auctionHouse = INounsAuctionHouseV2(auctionHouse_);
}
/**
* @param owner Address of the owner who has administration permissions as well as contract upgrade permissions
* @param admin_ Address which has permissions to pause and unpause
* @param ethToken_ An ETH pegged token (e.g. WETH) which will be used for rewards and gas refunds
* @param descriptor_ Address of a INounsClientTokenDescriptor contract to provide tokenURI for the NFTs
*/
function initialize(address owner, address admin_, address ethToken_, address descriptor_) public initializer {
__Pausable_init_unchained();
__ERC721_init('Nouns Client Token', 'NOUNSCLIENT');
RewardsStorage storage $ = _getRewardsStorage();
$.nextTokenId = 1;
_transferOwnership(owner);
$.admin = admin_;
$.ethToken = IERC20(ethToken_);
$.descriptor = descriptor_;
}
/**
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
* PUBLIC WRITE
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
*/
/**
* @notice Register a client, mints an NFT and assigns a clientId
* @param name a short name identifying the client
* @param description a longer description for the client, ideally a URL
* @return uint32 the newly assigned clientId
*/
function registerClient(string calldata name, string calldata description) external whenNotPaused returns (uint32) {
RewardsStorage storage $ = _getRewardsStorage();
uint32 tokenId = $.nextTokenId;
$.nextTokenId = tokenId + 1;
_mint(msg.sender, tokenId);
ClientMetadata storage md = $._clientMetadata[tokenId];
md.name = name;
md.description = description;
emit ClientRegistered(tokenId, name, description);
return tokenId;
}
/**
* @notice Update the metadata of a client
* @dev Only the owner of the client token can update the metadata.
* @param tokenId The token ID of the client
* @param name The new name of the client
* @param description The new description of the client
*/
function updateClientMetadata(uint32 tokenId, string calldata name, string calldata description) external {
RewardsStorage storage $ = _getRewardsStorage();
if (ownerOf(tokenId) != msg.sender) revert OnlyNFTOwner();
ClientMetadata storage md = $._clientMetadata[tokenId];
md.name = name;
md.description = description;
emit ClientUpdated(tokenId, name, description);
}
/**
* @notice Distribute rewards for auction bidding since the last update until auction with id `lastNounId`
* If an auction's winning bid was called with a clientId, that client will be reward with `params.auctionRewardBps`
* bips of the auction's settlement amount.
* At least `minimumAuctionsBetweenUpdates` must happen between updates.
* Gas spent is refunded in `ethToken`.
* @param lastNounId the last auction id to reward client for. must be already settled.
* @dev Gas is refunded if at least one auction was rewarded
*/
function updateRewardsForAuctions(uint32 lastNounId) public whenNotPaused {
uint256 startGas = gasleft();
RewardsStorage storage $ = _getRewardsStorage();
if (!$.auctionRewardsEnabled) revert RewardsDisabled();
bool sawValidClientId = false;
uint256 nextAuctionIdToReward_ = $.nextAuctionIdToReward;
if (lastNounId < nextAuctionIdToReward_ + $.auctionRewardParams.minimumAuctionsBetweenUpdates)
revert LastNounIdMustBeHigher();
$.nextAuctionIdToReward = lastNounId + 1;
INounsAuctionHouseV2.Settlement[] memory settlements = auctionHouse.getSettlements(
nextAuctionIdToReward_,
lastNounId + 1,
true
);
INounsAuctionHouseV2.Settlement memory lastSettlement = settlements[settlements.length - 1];
if (!(lastSettlement.nounId == lastNounId && lastSettlement.blockTimestamp > 1))
revert LastNounIdMustBeSettled();
uint32 maxClientId = nextTokenId() - 1;
ClientRewardsMemoryMapping.Mapping memory m = ClientRewardsMemoryMapping.createMapping({
maxClientId: maxClientId
});
for (uint256 i; i < settlements.length; ++i) {
INounsAuctionHouseV2.Settlement memory settlement = settlements[i];
if (settlement.clientId != 0 && settlement.clientId <= maxClientId) {
sawValidClientId = true;
m.inc(settlement.clientId, settlement.amount);
}
}
uint16 auctionRewardBps = $.auctionRewardParams.auctionRewardBps;
uint256 numValues = m.numValues();
for (uint32 i = 0; i < numValues; ++i) {
ClientRewardsMemoryMapping.ClientBalance memory cb = m.getValue(i);
uint256 reward = (cb.balance * auctionRewardBps) / 10_000;
$._clientMetadata[cb.clientId].rewarded += SafeCast.toUint96(reward);
emit ClientRewarded(cb.clientId, reward);
}
emit AuctionRewardsUpdated(nextAuctionIdToReward_, lastNounId);
if (sawValidClientId) {
// refund gas only if we're actually rewarding a client, not just moving the pointer
GasRefund.refundGas($.ethToken, startGas);
}
}
/// @dev struct used to avoid stack-too-deep errors
struct Temp {
uint32 maxClientId;
uint256 numEligibleVotes;
uint256 rewardPerProposal;
uint256 rewardPerVote;
uint256 proposalRewardForPeriod;
uint256 votingRewardForPeriod;
uint256 firstAuctionIdForRevenue;
NounsDAOTypes.ProposalForRewards lastProposal;
}
/**
* @notice Distribute rewards for proposal creation and voting from the last update until `lastProposalId`.
* A proposal is eligible for rewards if it wasn't canceled and for-votes/total-votes >= params.proposalEligibilityQuorumBps.
* Rewards are calculated by the auctions revenue during the period between the creation time of last processed
* eligible proposal in until the current last eligible proposal with id <= `lastProposalId`.
* One of two conditions must be true in order for rewards to be distributed:
* 1. There are at least `numProposalsEnoughForReward` proposals in this update
* 2. At least `minimumRewardPeriod` time has passed since the last update until the creation time of the last
* eligible proposal in this update.
* Gas spent is refunded in `ethToken`.
* @param lastProposalId id of the last proposal to include in the rewards distribution. all proposals up to and
* including this id must have ended voting.
* @param votingClientIds array of sorted client ids that were used to vote on the eligible proposals in
* this rewards distribution. Reverts if it contains duplicates. Reverts if it's not sorted. Reverts if a clientId
* had zero votes on all eligible proposals from this update.
* You may use `getVotingClientIds` as a convenience function to get the correct `votingClientIds`.
*/
function updateRewardsForProposalWritingAndVoting(
uint32 lastProposalId,
uint32[] calldata votingClientIds
) public whenNotPaused {
uint256 startGas = gasleft();
RewardsStorage storage $ = _getRewardsStorage();
if (!$.proposalRewardsEnabled) revert RewardsDisabled();
Temp memory t;
t.maxClientId = nextTokenId() - 1;
uint32 nextProposalIdToReward_ = $.nextProposalIdToReward;
require(
(lastProposalId <= nounsDAO.proposalCount()) && (lastProposalId >= nextProposalIdToReward_),
'bad lastProposalId'
);
require(isSortedAndNoDuplicates(votingClientIds), 'must be sorted & unique');
NounsDAOTypes.ProposalForRewards[] memory proposals = nounsDAO.proposalDataForRewards({
firstProposalId: nextProposalIdToReward_,
lastProposalId: lastProposalId,
proposalEligibilityQuorumBps: $.proposalRewardParams.proposalEligibilityQuorumBps,
excludeCanceled: true,
requireVotingEnded: true,
votingClientIds: votingClientIds
});
require(proposals.length > 0, 'at least one eligible proposal');
$.nextProposalIdToReward = lastProposalId + 1;
t.lastProposal = proposals[proposals.length - 1];
t.firstAuctionIdForRevenue = $.nextProposalRewardFirstAuctionId;
(uint256 auctionRevenue, uint256 lastAuctionIdForRevenue) = getAuctionRevenue({
firstNounId: t.firstAuctionIdForRevenue,
endTimestamp: t.lastProposal.creationTimestamp
});
$.nextProposalRewardFirstAuctionId = uint32(lastAuctionIdForRevenue) + 1;
require(auctionRevenue > 0, 'auctionRevenue must be > 0');
t.proposalRewardForPeriod = (auctionRevenue * $.proposalRewardParams.proposalRewardBps) / 10_000;
t.votingRewardForPeriod = (auctionRevenue * $.proposalRewardParams.votingRewardBps) / 10_000;
//// First loop over the proposals:
//// 1. Count the number of votes in eligible proposals.
for (uint256 i; i < proposals.length; ++i) {
uint256 votesInProposal = proposals[i].forVotes + proposals[i].againstVotes + proposals[i].abstainVotes;
t.numEligibleVotes += votesInProposal;
}
//// Check that distribution is allowed:
//// 1. One of the two conditions must be true:
//// 1.a. Number of eligible proposals is at least `numProposalsEnoughForReward`.
//// 1.b. At least `minimumRewardPeriod` seconds have passed since the last update.
if (proposals.length < $.proposalRewardParams.numProposalsEnoughForReward) {
require(
t.lastProposal.creationTimestamp >
$.lastProposalRewardsUpdate + $.proposalRewardParams.minimumRewardPeriod,
'not enough time passed'
);
}
$.lastProposalRewardsUpdate = uint40(t.lastProposal.creationTimestamp);
// Calculate the reward per proposal and per vote
t.rewardPerProposal = t.proposalRewardForPeriod / proposals.length;
t.rewardPerVote = t.votingRewardForPeriod / t.numEligibleVotes;
emit ProposalRewardsUpdated(
nextProposalIdToReward_,
lastProposalId,
t.firstAuctionIdForRevenue,
lastAuctionIdForRevenue,
auctionRevenue,
t.rewardPerProposal,
t.rewardPerVote
);
//// Second loop over the proposals:
//// 1. Reward proposal's clientId.
//// 2. Reward the clientIds that faciliated voting.
//// 3. Make sure all voting clientIds were included. This is meant to avoid griefing. Otherwises one could pass
//// a large array of votingClientIds, spend a lot of gas, and have that gas refunded.
ClientRewardsMemoryMapping.Mapping memory m = ClientRewardsMemoryMapping.createMapping({
maxClientId: t.maxClientId
});
bool[] memory didClientIdHaveVotes = new bool[](votingClientIds.length);
for (uint256 i; i < proposals.length; ++i) {
uint32 clientId = proposals[i].clientId;
if (clientId != 0 && clientId <= t.maxClientId) {
m.inc(clientId, t.rewardPerProposal);
}
uint256 votesInProposal;
NounsDAOTypes.ClientVoteData[] memory voteData = proposals[i].voteData;
for (uint256 j; j < votingClientIds.length; ++j) {
clientId = votingClientIds[j];
uint256 votes = voteData[j].votes;
didClientIdHaveVotes[j] = didClientIdHaveVotes[j] || votes > 0;
if (clientId != 0 && clientId <= t.maxClientId) {
m.inc(clientId, votes * t.rewardPerVote);
}
votesInProposal += votes;
}
require(
votesInProposal == proposals[i].forVotes + proposals[i].againstVotes + proposals[i].abstainVotes,
'not all votes accounted'
);
}
for (uint256 i = 0; i < didClientIdHaveVotes.length; ++i) {
require(didClientIdHaveVotes[i], 'all clientId must have votes');
}
uint256 numValues = m.numValues();
for (uint32 i = 0; i < numValues; ++i) {
ClientRewardsMemoryMapping.ClientBalance memory cb = m.getValue(i);
$._clientMetadata[cb.clientId].rewarded += SafeCast.toUint96(cb.balance);
emit ClientRewarded(cb.clientId, cb.balance);
}
GasRefund.refundGas($.ethToken, startGas);
}
/**
* @notice Withdraws the balance of a client
* @dev The caller must be the owner of the NFT with id `clientId` and the client must be approved by the DAO.
* @param clientId Which client balance to withdraw
* @param to the address to withdraw to
* @param amount amount to withdraw
*/
function withdrawClientBalance(uint32 clientId, address to, uint96 amount) public whenNotPaused {
RewardsStorage storage $ = _getRewardsStorage();
ClientMetadata storage md = $._clientMetadata[clientId];
if (ownerOf(clientId) != msg.sender) revert OnlyNFTOwner();
require(md.approved, 'not approved');
uint96 withdrawnCache = md.withdrawn;
require(amount <= md.rewarded - withdrawnCache, 'amount too large');
md.withdrawn = withdrawnCache + amount;
emit ClientBalanceWithdrawal(clientId, amount, to);
$.ethToken.safeTransfer(to, amount);
}
/**
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
* PUBLIC READ
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
*/
/**
* @notice Returns the withdrawable balance of client with id `clientId`
*/
function clientBalance(uint32 clientId) public view returns (uint96) {
RewardsStorage storage $ = _getRewardsStorage();
ClientMetadata storage md = $._clientMetadata[clientId];
return md.rewarded - md.withdrawn;
}
/**
* @notice Returns the clientIds that are needed to be passed as a parameter to updateRewardsForProposalWritingAndVoting
* @dev This is not meant to be called onchain because it may be very gas intensive.
*/
function getVotingClientIds(uint32 lastProposalId) public view returns (uint32[] memory) {
RewardsStorage storage $ = _getRewardsStorage();
uint256 numClientIds = nextTokenId();
uint32[] memory allClientIds = new uint32[](numClientIds);
for (uint32 i; i < numClientIds; ++i) {
allClientIds[i] = i;
}
NounsDAOTypes.ProposalForRewards[] memory proposals = nounsDAO.proposalDataForRewards({
firstProposalId: $.nextProposalIdToReward,
lastProposalId: lastProposalId,
proposalEligibilityQuorumBps: $.proposalRewardParams.proposalEligibilityQuorumBps,
excludeCanceled: true,
requireVotingEnded: true,
votingClientIds: allClientIds
});
uint32[] memory sumVotes = new uint32[](numClientIds);
for (uint256 i; i < proposals.length; ++i) {
for (uint256 j; j < numClientIds; ++j) {
sumVotes[j] += proposals[i].voteData[j].votes;
}
}
uint256 idx;
uint32[] memory nonZeroClientIds = new uint32[](numClientIds);
for (uint32 i; i < numClientIds; ++i) {
if (sumVotes[i] > 0) nonZeroClientIds[idx++] = i;
}
assembly {
mstore(nonZeroClientIds, idx)
}
return nonZeroClientIds;
}
/**
* @notice Returns the sum of revenue via auctions from auctioning noun with id `firstNounId` until timestamp of `endTimestamp
*/
function getAuctionRevenue(
uint256 firstNounId,
uint256 endTimestamp
) public view returns (uint256 sumRevenue, uint256 lastAuctionId) {
INounsAuctionHouseV2.Settlement[] memory s = auctionHouse.getSettlementsFromIdtoTimestamp(
firstNounId,
endTimestamp,
true
);
sumRevenue = sumAuctions(s);
lastAuctionId = s[s.length - 1].nounId;
}
/**
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
* PUBLIC READ - STORAGE GETTERS
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
*/
function nextAuctionIdToReward() public view returns (uint256) {
return _getRewardsStorage().nextAuctionIdToReward;
}
function nextProposalIdToReward() public view returns (uint32) {
return _getRewardsStorage().nextProposalIdToReward;
}
function nextProposalRewardFirstAuctionId() public view returns (uint256) {
return _getRewardsStorage().nextProposalRewardFirstAuctionId;
}
function lastProposalRewardsUpdate() public view returns (uint256) {
return _getRewardsStorage().lastProposalRewardsUpdate;
}
function getAuctionRewardParams() public view returns (AuctionRewardParams memory) {
return _getRewardsStorage().auctionRewardParams;
}
function getProposalRewardParams() public view returns (ProposalRewardParams memory) {
return _getRewardsStorage().proposalRewardParams;
}
function auctionRewardsEnabled() public view returns (bool) {
return _getRewardsStorage().auctionRewardsEnabled;
}
function proposalRewardsEnabled() public view returns (bool) {
return _getRewardsStorage().proposalRewardsEnabled;
}
function ethToken() public view returns (IERC20) {
return _getRewardsStorage().ethToken;
}
function admin() public view returns (address) {
return _getRewardsStorage().admin;
}
/**
* @notice Get the metadata of a client
*/
function clientMetadata(uint32 tokenId) public view returns (ClientMetadata memory) {
return _getRewardsStorage()._clientMetadata[tokenId];
}
/**
* @notice Get the URI of a client token
*/
function tokenURI(uint256 tokenId) public view override returns (string memory) {
RewardsStorage storage $ = _getRewardsStorage();
return INounsClientTokenDescriptor($.descriptor).tokenURI(tokenId, $._clientMetadata[uint32(tokenId)]);
}
/**
* @notice Get the descriptor for the client token
*/
function descriptor() public view returns (address) {
return _getRewardsStorage().descriptor;
}
/**
* @notice Get the next token ID
*/
function nextTokenId() public view returns (uint32) {
return _getRewardsStorage().nextTokenId;
}
/**
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
* ADMIN
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
*/
/**
* @notice Set whether the client is approved to withdraw their reward balance.
* Anyone can mint a client NFT and start earning rewards, but only approved clients can withdraw.
* This way the DAO helps mitigate abuse.
* @dev Only `owner` can call this function
*/
function setClientApproval(uint32 clientId, bool approved) public onlyOwner {
RewardsStorage storage $ = _getRewardsStorage();
$._clientMetadata[clientId].approved = approved;
emit ClientApprovalSet(clientId, approved);
}
/**
* @notice Updates the auction rewards params
* @dev Only `owner` can call this function
*/
function setAuctionRewardParams(AuctionRewardParams calldata newParams) public onlyOwner {
_getRewardsStorage().auctionRewardParams = newParams;
}
/**
* @notice Enables auction rewards and sets the next auction id to reward to be the current noun on auction
* @dev Only `owner` can call this function
*/
function enableAuctionRewards() public onlyOwner {
RewardsStorage storage $ = _getRewardsStorage();
uint32 nextAuctionIdToReward = SafeCast.toUint32(auctionHouse.auction().nounId);
$.nextAuctionIdToReward = nextAuctionIdToReward;
$.auctionRewardsEnabled = true;
emit AuctionRewardsEnabled(nextAuctionIdToReward);
}
/**
* @notice Disables auction rewards
* @dev Only `owner` can call this function
*/
function disableAuctionRewards() public onlyOwner {
_getRewardsStorage().auctionRewardsEnabled = false;
emit AuctionRewardsDisabled();
}
/**
* @notice Updates the proposal rewards params
* @dev Only `owner` can call this function
*/
function setProposalRewardParams(ProposalRewardParams calldata newParams) public onlyOwner {
_getRewardsStorage().proposalRewardParams = newParams;
}
/**
* @notice Enables proposal rewards and sets the next proposal ID to reward to be the next proposal to be created.
* The first auction ID to be considered for revenue calculation is set to be the current noun in auction.
* @dev Only `owner` can call this function
*/
function enableProposalRewards() public onlyOwner {
RewardsStorage storage $ = _getRewardsStorage();
uint32 nextProposalIdToReward = SafeCast.toUint32(nounsDAO.proposalCount() + 1);
uint32 nextProposalRewardFirstAuctionId = SafeCast.toUint32(auctionHouse.auction().nounId);
$.nextProposalIdToReward = nextProposalIdToReward;
$.nextProposalRewardFirstAuctionId = nextProposalRewardFirstAuctionId;
$.lastProposalRewardsUpdate = uint40(block.timestamp);
$.proposalRewardsEnabled = true;
emit ProposalRewardsEnabled(nextProposalIdToReward, nextProposalRewardFirstAuctionId);
}
/**
* @notice Disables proposal rewards
* @dev Only `owner` can call this function
*/
function disableProposalRewards() public onlyOwner {
_getRewardsStorage().proposalRewardsEnabled = false;
emit ProposalRewardsDisabled();
}
/**
* @dev Only `owner` can call this function
*/
function setAdmin(address newAdmin) public onlyOwner {
_getRewardsStorage().admin = newAdmin;
}
/**
* @dev Only `owner` can call this function
*/
function setETHToken(address newToken) public onlyOwner {
_getRewardsStorage().ethToken = IERC20(newToken);
}
/**
* @notice Withdraws any ERC20 token held by the contract
* @param token Address of ERC20 token
* @param to Address to send tokens to
* @param amount Amount of tokens to withdraw
* @dev Only `owner` can call this function
*/
function withdrawToken(address token, address to, uint256 amount) public onlyOwner {
IERC20(token).safeTransfer(to, amount);
}
/**
* @notice Pauses reward distributes, client registration and withdrawals
* @dev Only `owner` or `admin` can call this function
*/
function pause() public onlyOwnerOrAdmin {
_pause();
}
/**
* @notice Unpauses reward distributes, client registration and withdrawals
* @dev Only `owner` or `admin` can call this function
*/
function unpause() public onlyOwnerOrAdmin {
_unpause();
}
/**
* @notice Set the descriptor for the client token
* @dev Only `owner` or `admin` can call this function
*/
function setDescriptor(address descriptor_) public onlyOwnerOrAdmin {
_getRewardsStorage().descriptor = descriptor_;
}
/**
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
* INTERNAL
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
*/
function sumAuctions(INounsAuctionHouseV2.Settlement[] memory s) internal pure returns (uint256 sum) {
for (uint256 i = 0; i < s.length; ++i) {
sum += s[i].amount;
}
}
/**
* @dev returns true if ids is an array of increasing unique values, i.e. sorted ascending and no duplicates
*/
function isSortedAndNoDuplicates(uint32[] memory ids) internal pure returns (bool) {
uint256 len = ids.length;
uint32 prevValue = ids[0];
for (uint256 i = 1; i < len; ++i) {
uint32 nextValue = ids[i];
if (nextValue <= prevValue) return false;
prevValue = nextValue;
}
return true;
}
/**
* Only `owner` can perform an upgrade
*/
function _authorizeUpgrade(address) internal view override onlyOwner {}
}// SPDX-License-Identifier: GPL-3.0
/// @title Interface for Noun Auction Houses
/*********************************
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░█████████░░█████████░░░ *
* ░░░░░░██░░░████░░██░░░████░░░ *
* ░░██████░░░████████░░░████░░░ *
* ░░██░░██░░░████░░██░░░████░░░ *
* ░░██░░██░░░████░░██░░░████░░░ *
* ░░░░░░█████████░░█████████░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
*********************************/
pragma solidity ^0.8.6;
import '../governance/NounsDAOInterfaces.sol';
interface INounsDAOLogic {
/**
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
* PROPOSALS
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
*/
/**
* @notice Function used to propose a new proposal. Sender must have delegates above the proposal threshold
* @param targets Target addresses for proposal calls
* @param values Eth values for proposal calls
* @param signatures Function signatures for proposal calls
* @param calldatas Calldatas for proposal calls
* @param description String description of the proposal
* @return uint256 Proposal id of new proposal
*/
function propose(
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas,
string memory description
) external returns (uint256);
function propose(
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas,
string memory description,
uint32 clientId
) external returns (uint256);
/**
* @notice Function used to propose a new proposal. Sender must have delegates above the proposal threshold.
* This proposal would be executed via the timelockV1 contract. This is meant to be used in case timelockV1
* is still holding funds or has special permissions to execute on certain contracts.
* @param targets Target addresses for proposal calls
* @param values Eth values for proposal calls
* @param signatures Function signatures for proposal calls
* @param calldatas Calldatas for proposal calls
* @param description String description of the proposal
* @return uint256 Proposal id of new proposal
*/
function proposeOnTimelockV1(
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas,
string memory description
) external returns (uint256);
function proposeBySigs(
NounsDAOTypes.ProposerSignature[] memory proposerSignatures,
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas,
string memory description,
uint32 clientId
) external returns (uint256);
/**
* @notice Function used to propose a new proposal. Sender and signers must have delegates above the proposal threshold
* Signers are regarded as co-proposers, and therefore have the ability to cancel the proposal at any time.
* @param proposerSignatures Array of signers who have signed the proposal and their signatures.
* @dev The signatures follow EIP-712. See `PROPOSAL_TYPEHASH` in NounsDAOProposals.sol
* @param targets Target addresses for proposal calls
* @param values Eth values for proposal calls
* @param signatures Function signatures for proposal calls
* @param calldatas Calldatas for proposal calls
* @param description String description of the proposal
* @return uint256 Proposal id of new proposal
*/
function proposeBySigs(
NounsDAOTypes.ProposerSignature[] memory proposerSignatures,
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas,
string memory description
) external returns (uint256);
/**
* @notice Invalidates a signature that may be used for signing a new proposal.
* Once a signature is canceled, the sender can no longer use it again.
* If the sender changes their mind and want to sign the proposal, they can change the expiry timestamp
* in order to produce a new signature.
* The signature will only be invalidated when used by the sender. If used by a different account, it will
* not be invalidated.
* Cancelling a signature for an existing proposal will have no effect. Signers have the ability to cancel
* a proposal they signed if necessary.
* @param sig The signature to cancel
*/
function cancelSig(bytes calldata sig) external;
/**
* @notice Update a proposal transactions and description.
* Only the proposer can update it, and only during the updateable period.
* @param proposalId Proposal's id
* @param targets Updated target addresses for proposal calls
* @param values Updated eth values for proposal calls
* @param signatures Updated function signatures for proposal calls
* @param calldatas Updated calldatas for proposal calls
* @param description Updated description of the proposal
* @param updateMessage Short message to explain the update
*/
function updateProposal(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas,
string memory description,
string memory updateMessage
) external;
/**
* @notice Updates the proposal's description. Only the proposer can update it, and only during the updateable period.
* @param proposalId Proposal's id
* @param description Updated description of the proposal
* @param updateMessage Short message to explain the update
*/
function updateProposalDescription(
uint256 proposalId,
string calldata description,
string calldata updateMessage
) external;
/**
* @notice Updates the proposal's transactions. Only the proposer can update it, and only during the updateable period.
* @param proposalId Proposal's id
* @param targets Updated target addresses for proposal calls
* @param values Updated eth values for proposal calls
* @param signatures Updated function signatures for proposal calls
* @param calldatas Updated calldatas for proposal calls
* @param updateMessage Short message to explain the update
*/
function updateProposalTransactions(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas,
string memory updateMessage
) external;
/**
* @notice Update a proposal's transactions and description that was created with proposeBySigs.
* Only the proposer can update it, during the updateable period.
* Requires the original signers to sign the update.
* @param proposalId Proposal's id
* @param proposerSignatures Array of signers who have signed the proposal and their signatures.
* @dev The signatures follow EIP-712. See `UPDATE_PROPOSAL_TYPEHASH` in NounsDAOProposals.sol
* @param targets Updated target addresses for proposal calls
* @param values Updated eth values for proposal calls
* @param signatures Updated function signatures for proposal calls
* @param calldatas Updated calldatas for proposal calls
* @param description Updated description of the proposal
* @param updateMessage Short message to explain the update
*/
function updateProposalBySigs(
uint256 proposalId,
NounsDAOTypes.ProposerSignature[] memory proposerSignatures,
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas,
string memory description,
string memory updateMessage
) external;
/**
* @notice Queues a proposal of state succeeded
* @param proposalId The id of the proposal to queue
*/
function queue(uint256 proposalId) external;
/**
* @notice Executes a queued proposal if eta has passed
* @param proposalId The id of the proposal to execute
*/
function execute(uint256 proposalId) external;
/**
* @notice Cancels a proposal only if sender is the proposer or a signer, or proposer & signers voting power
* dropped below proposal threshold
* @param proposalId The id of the proposal to cancel
*/
function cancel(uint256 proposalId) external;
/**
* @notice Gets the state of a proposal
* @param proposalId The id of the proposal
* @return Proposal state
*/
function state(uint256 proposalId) external view returns (NounsDAOTypes.ProposalState);
/**
* @notice Gets actions of a proposal
* @param proposalId the id of the proposal
* @return targets
* @return values
* @return signatures
* @return calldatas
*/
function getActions(
uint256 proposalId
)
external
view
returns (
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas
);
/**
* @notice Gets the receipt for a voter on a given proposal
* @param proposalId the id of proposal
* @param voter The address of the voter
* @return The voting receipt
*/
function getReceipt(uint256 proposalId, address voter) external view returns (NounsDAOTypes.Receipt memory);
/**
* @notice Returns the proposal details given a proposal id.
* The `quorumVotes` member holds the *current* quorum, given the current votes.
* @param proposalId the proposal id to get the data for
* @return A `ProposalCondensed` struct with the proposal data, backwards compatible with V1 and V2
*/
function proposals(uint256 proposalId) external view returns (NounsDAOTypes.ProposalCondensedV2 memory);
/**
* @notice Returns the proposal details given a proposal id.
* The `quorumVotes` member holds the *current* quorum, given the current votes.
* @param proposalId the proposal id to get the data for
* @return A `ProposalCondensed` struct with the proposal data, not backwards compatible as it contains additional values
* like `objectionPeriodEndBlock` and `signers`
*/
function proposalsV3(uint256 proposalId) external view returns (NounsDAOTypes.ProposalCondensedV3 memory);
function proposalDataForRewards(
uint256 firstProposalId,
uint256 lastProposalId,
uint16 proposalEligibilityQuorumBps,
bool excludeCanceled,
bool requireVotingEnded,
uint32[] calldata votingClientIds
) external view returns (NounsDAOTypes.ProposalForRewards[] memory);
/**
* @notice Current proposal threshold using Noun Total Supply
* Differs from `GovernerBravo` which uses fixed amount
*/
function proposalThreshold() external view returns (uint256);
/**
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
* ADMIN
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
*/
/**
* @notice Admin function for setting the voting delay. Best to set voting delay to at least a few days, to give
* voters time to make sense of proposals, e.g. 21,600 blocks which should be at least 3 days.
* @param newVotingDelay new voting delay, in blocks
*/
function _setVotingDelay(uint256 newVotingDelay) external;
/**
* @notice Admin function for setting the voting period
* @param newVotingPeriod new voting period, in blocks
*/
function _setVotingPeriod(uint256 newVotingPeriod) external;
/**
* @notice Admin function for setting the proposal threshold basis points
* @dev newProposalThresholdBPS must be in [`MIN_PROPOSAL_THRESHOLD_BPS`,`MAX_PROPOSAL_THRESHOLD_BPS`]
* @param newProposalThresholdBPS new proposal threshold
*/
function _setProposalThresholdBPS(uint256 newProposalThresholdBPS) external;
/**
* @notice Admin function for setting the objection period duration
* @param newObjectionPeriodDurationInBlocks new objection period duration, in blocks
*/
function _setObjectionPeriodDurationInBlocks(uint32 newObjectionPeriodDurationInBlocks) external;
/**
* @notice Admin function for setting the objection period last minute window
* @param newLastMinuteWindowInBlocks new objection period last minute window, in blocks
*/
function _setLastMinuteWindowInBlocks(uint32 newLastMinuteWindowInBlocks) external;
/**
* @notice Admin function for setting the proposal updatable period
* @param newProposalUpdatablePeriodInBlocks the new proposal updatable period, in blocks
*/
function _setProposalUpdatablePeriodInBlocks(uint32 newProposalUpdatablePeriodInBlocks) external;
/**
* @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
* @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
* @param newPendingAdmin New pending admin.
*/
function _setPendingAdmin(address newPendingAdmin) external;
/**
* @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin
* @dev Admin function for pending admin to accept role and update admin
*/
function _acceptAdmin() external;
/**
* @notice Begins transition of vetoer. The newPendingVetoer must call _acceptVetoer to finalize the transfer.
* @param newPendingVetoer New Pending Vetoer
*/
function _setPendingVetoer(address newPendingVetoer) external;
/**
* @notice Called by the pendingVetoer to accept role and update vetoer
*/
function _acceptVetoer() external;
/**
* @notice Burns veto priviledges
* @dev Vetoer function destroying veto power forever
*/
function _burnVetoPower() external;
/**
* @notice Admin function for setting the minimum quorum votes bps
* @param newMinQuorumVotesBPS minimum quorum votes bps
* Must be between `MIN_QUORUM_VOTES_BPS_LOWER_BOUND` and `MIN_QUORUM_VOTES_BPS_UPPER_BOUND`
* Must be lower than or equal to maxQuorumVotesBPS
*/
function _setMinQuorumVotesBPS(uint16 newMinQuorumVotesBPS) external;
/**
* @notice Admin function for setting the maximum quorum votes bps
* @param newMaxQuorumVotesBPS maximum quorum votes bps
* Must be lower than `MAX_QUORUM_VOTES_BPS_UPPER_BOUND`
* Must be higher than or equal to minQuorumVotesBPS
*/
function _setMaxQuorumVotesBPS(uint16 newMaxQuorumVotesBPS) external;
/**
* @notice Admin function for setting the dynamic quorum coefficient
* @param newQuorumCoefficient the new coefficient, as a fixed point integer with 6 decimals
*/
function _setQuorumCoefficient(uint32 newQuorumCoefficient) external;
/**
* @notice Admin function for setting all the dynamic quorum parameters
* @param newMinQuorumVotesBPS minimum quorum votes bps
* Must be between `MIN_QUORUM_VOTES_BPS_LOWER_BOUND` and `MIN_QUORUM_VOTES_BPS_UPPER_BOUND`
* Must be lower than or equal to maxQuorumVotesBPS
* @param newMaxQuorumVotesBPS maximum quorum votes bps
* Must be lower than `MAX_QUORUM_VOTES_BPS_UPPER_BOUND`
* Must be higher than or equal to minQuorumVotesBPS
* @param newQuorumCoefficient the new coefficient, as a fixed point integer with 6 decimals
*/
function _setDynamicQuorumParams(
uint16 newMinQuorumVotesBPS,
uint16 newMaxQuorumVotesBPS,
uint32 newQuorumCoefficient
) external;
/**
* @notice Withdraws all the ETH in the contract. This is callable only by the admin (timelock).
*/
function _withdraw() external returns (uint256, bool);
/**
* @notice Admin function for setting the fork period
* @param newForkPeriod the new fork proposal period, in seconds
*/
function _setForkPeriod(uint256 newForkPeriod) external;
/**
* @notice Admin function for setting the fork threshold
* @param newForkThresholdBPS the new fork proposal threshold, in basis points
*/
function _setForkThresholdBPS(uint256 newForkThresholdBPS) external;
/**
* @notice Admin function for setting the fork DAO deployer contract
*/
function _setForkDAODeployer(address newForkDAODeployer) external;
/**
* @notice Admin function for setting the ERC20 tokens that are used when splitting funds to a fork
*/
function _setErc20TokensToIncludeInFork(address[] calldata erc20tokens) external;
/**
* @notice Admin function for setting the fork escrow contract
*/
function _setForkEscrow(address newForkEscrow) external;
/**
* @notice Admin function for setting the fork related parameters
* @param forkEscrow_ the fork escrow contract
* @param forkDAODeployer_ the fork dao deployer contract
* @param erc20TokensToIncludeInFork_ the ERC20 tokens used when splitting funds to a fork
* @param forkPeriod_ the period during which it's possible to join a fork after exeuction
* @param forkThresholdBPS_ the threshold required of escrowed nouns in order to execute a fork
*/
function _setForkParams(
address forkEscrow_,
address forkDAODeployer_,
address[] calldata erc20TokensToIncludeInFork_,
uint256 forkPeriod_,
uint256 forkThresholdBPS_
) external;
/**
* @notice Admin function for setting the timelocks and admin
* @param newTimelock the new timelock contract
* @param newTimelockV1 the new timelockV1 contract
* @param newAdmin the new admin address
*/
function _setTimelocksAndAdmin(address newTimelock, address newTimelockV1, address newAdmin) external;
/**
* @notice Admin function for zeroing out the state variable `voteSnapshotBlockSwitchProposalId`
* @dev We want to zero-out this state slot so we can remove this temporary variable from contract code and
* be ready to reuse this slot.
*/
function _zeroOutVoteSnapshotBlockSwitchProposalId() external;
/**
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
* DYNAMIC QUORUM
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
*/
/**
* @notice Quorum votes required for a specific proposal to succeed
* Differs from `GovernerBravo` which uses fixed amount
*/
function quorumVotes(uint256 proposalId) external view returns (uint256);
/**
* @notice Calculates the required quorum of for-votes based on the amount of against-votes
* The more against-votes there are for a proposal, the higher the required quorum is.
* The quorum BPS is between `params.minQuorumVotesBPS` and params.maxQuorumVotesBPS.
* The additional quorum is calculated as:
* quorumCoefficient * againstVotesBPS
* @dev Note the coefficient is a fixed point integer with 6 decimals
* @param againstVotes Number of against-votes in the proposal
* @param adjustedTotalSupply_ The adjusted total supply of Nouns at the time of proposal creation
* @param params Configurable parameters for calculating the quorum based on againstVotes. See `DynamicQuorumParams` definition for additional details.
* @return quorumVotes The required quorum
*/
function dynamicQuorumVotes(
uint256 againstVotes,
uint256 adjustedTotalSupply_,
NounsDAOTypes.DynamicQuorumParams memory params
) external pure returns (uint256);
/**
* @notice returns the dynamic quorum parameters values at a certain block number
* @dev The checkpoints array must not be empty, and the block number must be higher than or equal to
* the block of the first checkpoint
* @param blockNumber_ the block number to get the params at
* @return The dynamic quorum parameters that were set at the given block number
*/
function getDynamicQuorumParamsAt(
uint256 blockNumber_
) external view returns (NounsDAOTypes.DynamicQuorumParams memory);
/**
* @notice Current min quorum votes using Nouns adjusted total supply
*/
function minQuorumVotes() external view returns (uint256);
/**
* @notice Current max quorum votes using Nouns adjusted total supply
*/
function maxQuorumVotes() external view returns (uint256);
/**
* @notice Get all quorum params checkpoints
*/
function quorumParamsCheckpoints() external view returns (NounsDAOTypes.DynamicQuorumParamsCheckpoint[] memory);
/**
* @notice Get a quorum params checkpoint by its index
*/
function quorumParamsCheckpoints(
uint256 index
) external view returns (NounsDAOTypes.DynamicQuorumParamsCheckpoint memory);
/**
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
* DAO FORK
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
*/
/**
* @notice Escrow Nouns to contribute to the fork threshold
* @dev Requires approving the tokenIds or the entire noun token to the DAO contract
* @param tokenIds the tokenIds to escrow. They will be sent to the DAO once the fork threshold is reached and the escrow is closed.
* @param proposalIds array of proposal ids which are the reason for wanting to fork. This will only be used to emit event.
* @param reason the reason for want to fork. This will only be used to emit event.
*/
function escrowToFork(uint256[] calldata tokenIds, uint256[] calldata proposalIds, string calldata reason) external;
/**
* @notice Withdraw Nouns from the fork escrow. Only possible if the fork has not been executed.
* Only allowed to withdraw tokens that the sender has escrowed.
* @param tokenIds the tokenIds to withdraw
*/
function withdrawFromForkEscrow(uint256[] calldata tokenIds) external;
/**
* @notice Execute the fork. Only possible if the fork threshold has been met.
* This will deploy a new DAO and send part of the treasury to the new DAO's treasury.
* This will also close the active escrow and all nouns in the escrow belong to the original DAO.
* @return forkTreasury The address of the new DAO's treasury
* @return forkToken The address of the new DAO's token
*/
function executeFork() external returns (address forkTreasury, address forkToken);
/**
* @notice Joins a fork while a fork is active
* @param tokenIds the tokenIds to send to the DAO in exchange for joining the fork
* @param proposalIds array of proposal ids which are the reason for wanting to fork. This will only be used to emit event.
* @param reason the reason for want to fork. This will only be used to emit event.
*/
function joinFork(uint256[] calldata tokenIds, uint256[] calldata proposalIds, string calldata reason) external;
/**
* @notice Withdraws nouns from the fork escrow to the treasury after the fork has been executed
* @dev Only the DAO can call this function
* @param tokenIds the tokenIds to withdraw
*/
function withdrawDAONounsFromEscrowToTreasury(uint256[] calldata tokenIds) external;
/**
* @notice Withdraws nouns from the fork escrow after the fork has been executed to an address other than the treasury
* @dev Only the DAO can call this function
* @param tokenIds the tokenIds to withdraw
* @param to the address to send the nouns to
*/
function withdrawDAONounsFromEscrowIncreasingTotalSupply(uint256[] calldata tokenIds, address to) external;
/**
* @notice Returns the number of nouns in supply minus nouns owned by the DAO, i.e. held in the treasury or in an
* escrow after it has closed.
* This is used when calculating proposal threshold, quorum, fork threshold & treasury split.
*/
function adjustedTotalSupply() external view returns (uint256);
/**
* @notice returns the required number of tokens to escrow to trigger a fork
*/
function forkThreshold() external view returns (uint256);
/**
* @notice Returns the number of tokens currently in escrow, contributing to the fork threshold
*/
function numTokensInForkEscrow() external view returns (uint256);
/**
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
* VOTES
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
*/
/**
* @notice Vetoes a proposal only if sender is the vetoer and the proposal has not been executed.
* @param proposalId The id of the proposal to veto
*/
function veto(uint256 proposalId) external;
/**
* @notice Cast a vote for a proposal
* @param proposalId The id of the proposal to vote on
* @param support The support value for the vote. 0=against, 1=for, 2=abstain
*/
function castVote(uint256 proposalId, uint8 support) external;
function castRefundableVote(uint256 proposalId, uint8 support, uint32 clientId) external;
/**
* @notice Cast a vote for a proposal, asking the DAO to refund gas costs.
* Users with > 0 votes receive refunds. Refunds are partial when using a gas priority fee higher than the DAO's cap.
* Refunds are partial when the DAO's balance is insufficient.
* No refund is sent when the DAO's balance is empty. No refund is sent to users with no votes.
* Voting takes place regardless of refund success.
* @param proposalId The id of the proposal to vote on
* @param support The support value for the vote. 0=against, 1=for, 2=abstain
* @dev Reentrancy is defended against in `castVoteInternal` at the `receipt.hasVoted == false` require statement.
*/
function castRefundableVote(uint256 proposalId, uint8 support) external;
function castRefundableVoteWithReason(
uint256 proposalId,
uint8 support,
string calldata reason,
uint32 clientId
) external;
/**
* @notice Cast a vote for a proposal, asking the DAO to refund gas costs.
* Users with > 0 votes receive refunds. Refunds are partial when using a gas priority fee higher than the DAO's cap.
* Refunds are partial when the DAO's balance is insufficient.
* No refund is sent when the DAO's balance is empty. No refund is sent to users with no votes.
* Voting takes place regardless of refund success.
* @param proposalId The id of the proposal to vote on
* @param support The support value for the vote. 0=against, 1=for, 2=abstain
* @param reason The reason given for the vote by the voter
* @dev Reentrancy is defended against in `castVoteInternal` at the `receipt.hasVoted == false` require statement.
*/
function castRefundableVoteWithReason(uint256 proposalId, uint8 support, string calldata reason) external;
/**
* @notice Cast a vote for a proposal with a reason
* @param proposalId The id of the proposal to vote on
* @param support The support value for the vote. 0=against, 1=for, 2=abstain
* @param reason The reason given for the vote by the voter
*/
function castVoteWithReason(uint256 proposalId, uint8 support, string calldata reason) external;
/**
* @notice Cast a vote for a proposal by signature
* @dev External function that accepts EIP-712 signatures for voting on proposals.
*/
function castVoteBySig(uint256 proposalId, uint8 support, uint8 v, bytes32 r, bytes32 s) external;
/**
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
* STATE VARIABLE GETTERS
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
*/
function admin() external view returns (address);
function implementation() external view returns (address);
function vetoer() external view returns (address);
function pendingVetoer() external view returns (address);
function votingDelay() external view returns (uint256);
function votingPeriod() external view returns (uint256);
function proposalThresholdBPS() external view returns (uint256);
function quorumVotesBPS() external view returns (uint256);
function proposalCount() external view returns (uint256);
function timelock() external view returns (INounsDAOExecutor);
function nouns() external view returns (NounsTokenLike);
function latestProposalIds(address account) external view returns (uint256);
function lastMinuteWindowInBlocks() external view returns (uint256);
function objectionPeriodDurationInBlocks() external view returns (uint256);
function erc20TokensToIncludeInFork() external view returns (address[] memory);
function forkEscrow() external view returns (INounsDAOForkEscrow);
function forkDAODeployer() external view returns (IForkDAODeployer);
function forkEndTimestamp() external view returns (uint256);
function forkPeriod() external view returns (uint256);
function forkThresholdBPS() external view returns (uint256);
function proposalUpdatablePeriodInBlocks() external view returns (uint256);
function timelockV1() external view returns (address);
function voteSnapshotBlockSwitchProposalId() external view returns (uint256);
}// SPDX-License-Identifier: GPL-3.0
/// @title Interface for Noun Auction Houses V2
/*********************************
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░█████████░░█████████░░░ *
* ░░░░░░██░░░████░░██░░░████░░░ *
* ░░██████░░░████████░░░████░░░ *
* ░░██░░██░░░████░░██░░░████░░░ *
* ░░██░░██░░░████░░██░░░████░░░ *
* ░░░░░░█████████░░█████████░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
*********************************/
pragma solidity ^0.8.19;
interface INounsAuctionHouseV2 {
struct AuctionV2 {
// ID for the Noun (ERC721 token ID)
uint96 nounId;
// ID of the client that facilitated the latest bid, used for client rewards
uint32 clientId;
// The current highest bid amount
uint128 amount;
// The time that the auction started
uint40 startTime;
// The time that the auction is scheduled to end
uint40 endTime;
// The address of the current highest bid
address payable bidder;
// Whether or not the auction has been settled
bool settled;
}
/// @dev We use this struct as the return value of the `auction` function, to maintain backwards compatibility.
struct AuctionV2View {
// ID for the Noun (ERC721 token ID)
uint96 nounId;
// The current highest bid amount
uint128 amount;
// The time that the auction started
uint40 startTime;
// The time that the auction is scheduled to end
uint40 endTime;
// The address of the current highest bid
address payable bidder;
// Whether or not the auction has been settled
bool settled;
}
struct SettlementState {
// The block.timestamp when the auction was settled.
uint32 blockTimestamp;
// The winning bid amount, with 10 decimal places (reducing accuracy to save bits).
uint64 amount;
// The address of the auction winner.
address winner;
// ID of the client that facilitated the winning bid, used for client rewards.
uint32 clientId;
// Used only to warm up the storage slot for clientId without setting the clientId value.
bool slotWarmedUp;
}
struct Settlement {
// The block.timestamp when the auction was settled.
uint32 blockTimestamp;
// The winning bid amount, converted from 10 decimal places to 18, for better client UX.
uint256 amount;
// The address of the auction winner.
address winner;
// ID for the Noun (ERC721 token ID).
uint256 nounId;
// ID of the client that facilitated the winning bid, used for client rewards
uint32 clientId;
}
/// @dev Using this struct when setting historic prices, and excluding clientId to save gas.
struct SettlementNoClientId {
// The block.timestamp when the auction was settled.
uint32 blockTimestamp;
// The winning bid amount, converted from 10 decimal places to 18, for better client UX.
uint256 amount;
// The address of the auction winner.
address winner;
// ID for the Noun (ERC721 token ID).
uint256 nounId;
}
event AuctionCreated(uint256 indexed nounId, uint256 startTime, uint256 endTime);
event AuctionBid(uint256 indexed nounId, address sender, uint256 value, bool extended);
event AuctionBidWithClientId(uint256 indexed nounId, uint256 value, uint32 indexed clientId);
event AuctionExtended(uint256 indexed nounId, uint256 endTime);
event AuctionSettled(uint256 indexed nounId, address winner, uint256 amount);
event AuctionSettledWithClientId(uint256 indexed nounId, uint32 indexed clientId);
event AuctionTimeBufferUpdated(uint256 timeBuffer);
event AuctionReservePriceUpdated(uint256 reservePrice);
event AuctionMinBidIncrementPercentageUpdated(uint256 minBidIncrementPercentage);
function settleAuction() external;
function settleCurrentAndCreateNewAuction() external;
function createBid(uint256 nounId) external payable;
function createBid(uint256 nounId, uint32 clientId) external payable;
function pause() external;
function unpause() external;
function setTimeBuffer(uint56 timeBuffer) external;
function setReservePrice(uint192 reservePrice) external;
function setMinBidIncrementPercentage(uint8 minBidIncrementPercentage) external;
function auction() external view returns (AuctionV2View memory);
function getSettlements(
uint256 auctionCount,
bool skipEmptyValues
) external view returns (Settlement[] memory settlements);
function getPrices(uint256 auctionCount) external view returns (uint256[] memory prices);
function getSettlements(
uint256 startId,
uint256 endId,
bool skipEmptyValues
) external view returns (Settlement[] memory settlements);
function getSettlementsFromIdtoTimestamp(
uint256 startId,
uint256 endTimestamp,
bool skipEmptyValues
) external view returns (Settlement[] memory settlements);
function warmUpSettlementState(uint256 startId, uint256 endId) external;
function duration() external view returns (uint256);
function biddingClient(uint256 nounId) external view returns (uint32 clientId);
}// SPDX-License-Identifier: BSD-3-Clause
/// @title Nouns DAO Logic interfaces and events
/*********************************
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░█████████░░█████████░░░ *
* ░░░░░░██░░░████░░██░░░████░░░ *
* ░░██████░░░████████░░░████░░░ *
* ░░██░░██░░░████░░██░░░████░░░ *
* ░░██░░██░░░████░░██░░░████░░░ *
* ░░░░░░█████████░░█████████░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
*********************************/
// LICENSE
// NounsDAOInterfaces.sol is a modified version of Compound Lab's GovernorBravoInterfaces.sol:
// https://github.com/compound-finance/compound-protocol/blob/b9b14038612d846b83f8a009a82c38974ff2dcfe/contracts/Governance/GovernorBravoInterfaces.sol
//
// GovernorBravoInterfaces.sol source code Copyright 2020 Compound Labs, Inc. licensed under the BSD-3-Clause license.
// With modifications by Nounders DAO.
//
// Additional conditions of BSD-3-Clause can be found here: https://opensource.org/licenses/BSD-3-Clause
//
// MODIFICATIONS
// NounsDAOEvents, NounsDAOProxyStorage, NounsDAOStorageV1 add support for changes made by Nouns DAO to GovernorBravo.sol
// See NounsDAOLogicV1.sol for more details.
// NounsDAOStorageV1Adjusted and NounsDAOStorageV2 add support for a dynamic vote quorum.
// See NounsDAOLogicV2.sol for more details.
// NounsDAOStorageV3
// See NounsDAOLogicV3.sol for more details.
pragma solidity ^0.8.19;
interface NounsDAOEventsV3 {
/// @notice An event emitted when a new proposal is created
event ProposalCreated(
uint256 id,
address proposer,
address[] targets,
uint256[] values,
string[] signatures,
bytes[] calldatas,
uint256 startBlock,
uint256 endBlock,
string description
);
/// @notice An event emitted when a new proposal is created, which includes additional information
event ProposalCreatedWithRequirements(
uint256 id,
address proposer,
address[] targets,
uint256[] values,
string[] signatures,
bytes[] calldatas,
uint256 startBlock,
uint256 endBlock,
uint256 proposalThreshold,
uint256 quorumVotes,
string description
);
/// @notice An event emitted when a vote has been cast on a proposal
/// @param voter The address which casted a vote
/// @param proposalId The proposal id which was voted on
/// @param support Support value for the vote. 0=against, 1=for, 2=abstain
/// @param votes Number of votes which were cast by the voter
/// @param reason The reason given for the vote by the voter
event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 votes, string reason);
/// @notice An event emitted when a proposal has been canceled
event ProposalCanceled(uint256 id);
/// @notice An event emitted when a proposal has been queued in the NounsDAOExecutor
event ProposalQueued(uint256 id, uint256 eta);
/// @notice An event emitted when a proposal has been executed in the NounsDAOExecutor
event ProposalExecuted(uint256 id);
/// @notice An event emitted when a proposal has been vetoed by vetoAddress
event ProposalVetoed(uint256 id);
/// @notice An event emitted when the voting delay is set
event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay);
/// @notice An event emitted when the voting period is set
event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod);
/// @notice Emitted when proposal threshold basis points is set
event ProposalThresholdBPSSet(uint256 oldProposalThresholdBPS, uint256 newProposalThresholdBPS);
/// @notice Emitted when quorum votes basis points is set
event QuorumVotesBPSSet(uint256 oldQuorumVotesBPS, uint256 newQuorumVotesBPS);
/// @notice Emitted when pendingAdmin is changed
event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);
/// @notice Emitted when pendingAdmin is accepted, which means admin is updated
event NewAdmin(address oldAdmin, address newAdmin);
/// @notice Emitted when vetoer is changed
event NewVetoer(address oldVetoer, address newVetoer);
/// @notice Emitted when minQuorumVotesBPS is set
event MinQuorumVotesBPSSet(uint16 oldMinQuorumVotesBPS, uint16 newMinQuorumVotesBPS);
/// @notice Emitted when maxQuorumVotesBPS is set
event MaxQuorumVotesBPSSet(uint16 oldMaxQuorumVotesBPS, uint16 newMaxQuorumVotesBPS);
/// @notice Emitted when quorumCoefficient is set
event QuorumCoefficientSet(uint32 oldQuorumCoefficient, uint32 newQuorumCoefficient);
/// @notice Emitted when a voter cast a vote requesting a gas refund.
event RefundableVote(address indexed voter, uint256 refundAmount, bool refundSent);
/// @notice Emitted when admin withdraws the DAO's balance.
event Withdraw(uint256 amount, bool sent);
/// @notice Emitted when pendingVetoer is changed
event NewPendingVetoer(address oldPendingVetoer, address newPendingVetoer);
/// @notice An event emitted when a new proposal is created, which includes additional information
/// @dev V3 adds `signers`, `updatePeriodEndBlock` compared to the V1/V2 event.
/// @dev V4: Removed data that's already emitted in `ProposalCreated`, added clientId
event ProposalCreatedWithRequirements(
uint256 id,
address[] signers,
uint256 updatePeriodEndBlock,
uint256 proposalThreshold,
uint256 quorumVotes,
uint32 indexed clientId
);
/// @notice Emitted when a proposal is created to be executed on timelockV1
event ProposalCreatedOnTimelockV1(uint256 id);
/// @notice Emitted when a proposal is updated
event ProposalUpdated(
uint256 indexed id,
address indexed proposer,
address[] targets,
uint256[] values,
string[] signatures,
bytes[] calldatas,
string description,
string updateMessage
);
/// @notice Emitted when a proposal's transactions are updated
event ProposalTransactionsUpdated(
uint256 indexed id,
address indexed proposer,
address[] targets,
uint256[] values,
string[] signatures,
bytes[] calldatas,
string updateMessage
);
/// @notice Emitted when a proposal's description is updated
event ProposalDescriptionUpdated(
uint256 indexed id,
address indexed proposer,
string description,
string updateMessage
);
/// @notice Emitted when a proposal is set to have an objection period
event ProposalObjectionPeriodSet(uint256 indexed id, uint256 objectionPeriodEndBlock);
/// @notice Emitted when someone cancels a signature
event SignatureCancelled(address indexed signer, bytes sig);
/// @notice An event emitted when the objection period duration is set
event ObjectionPeriodDurationSet(
uint32 oldObjectionPeriodDurationInBlocks,
uint32 newObjectionPeriodDurationInBlocks
);
/// @notice An event emitted when the objection period last minute window is set
event LastMinuteWindowSet(uint32 oldLastMinuteWindowInBlocks, uint32 newLastMinuteWindowInBlocks);
/// @notice An event emitted when the proposal updatable period is set
event ProposalUpdatablePeriodSet(
uint32 oldProposalUpdatablePeriodInBlocks,
uint32 newProposalUpdatablePeriodInBlocks
);
/// @notice Emitted when the erc20 tokens to include in a fork are set
event ERC20TokensToIncludeInForkSet(address[] oldErc20Tokens, address[] newErc20tokens);
/// @notice Emitted when the fork DAO deployer is set
event ForkDAODeployerSet(address oldForkDAODeployer, address newForkDAODeployer);
/// @notice Emitted when the during of the forking period is set
event ForkPeriodSet(uint256 oldForkPeriod, uint256 newForkPeriod);
/// @notice Emitted when the threhsold for forking is set
event ForkThresholdSet(uint256 oldForkThreshold, uint256 newForkThreshold);
/// @notice Emitted when the main timelock, timelockV1 and admin are set
event TimelocksAndAdminSet(address timelock, address timelockV1, address admin);
/// @notice Emitted when someones adds nouns to the fork escrow
event EscrowedToFork(
uint32 indexed forkId,
address indexed owner,
uint256[] tokenIds,
uint256[] proposalIds,
string reason
);
/// @notice Emitted when the owner withdraws their nouns from the fork escrow
event WithdrawFromForkEscrow(uint32 indexed forkId, address indexed owner, uint256[] tokenIds);
/// @notice Emitted when the fork is executed and the forking period begins
event ExecuteFork(
uint32 indexed forkId,
address forkTreasury,
address forkToken,
uint256 forkEndTimestamp,
uint256 tokensInEscrow
);
/// @notice Emitted when someone joins a fork during the forking period
event JoinFork(
uint32 indexed forkId,
address indexed owner,
uint256[] tokenIds,
uint256[] proposalIds,
string reason
);
/// @notice Emitted when the DAO withdraws nouns from the fork escrow after a fork has been executed
event DAOWithdrawNounsFromEscrow(uint256[] tokenIds, address to);
/// @notice Emitted when withdrawing nouns from escrow increases adjusted total supply
event DAONounsSupplyIncreasedFromEscrow(uint256 numTokens, address to);
/// @notice An event emitted when a vote has been cast with a non-zero client Id.
/// @dev Assumes the `VoteCast` event is emitted, and that indexers can use the voter address and propose ID to
/// find the relevant vote and set its client ID.
event VoteCastWithClientId(address indexed voter, uint256 indexed proposalId, uint32 indexed clientId);
}
interface INounsDAOExecutor {
function delay() external view returns (uint256);
function GRACE_PERIOD() external view returns (uint256);
function acceptAdmin() external;
function queuedTransactions(bytes32 hash) external view returns (bool);
function queueTransaction(
address target,
uint256 value,
string calldata signature,
bytes calldata data,
uint256 eta
) external returns (bytes32);
function cancelTransaction(
address target,
uint256 value,
string calldata signature,
bytes calldata data,
uint256 eta
) external;
function executeTransaction(
address target,
uint256 value,
string calldata signature,
bytes calldata data,
uint256 eta
) external payable returns (bytes memory);
}
interface NounsTokenLike {
function getPriorVotes(address account, uint256 blockNumber) external view returns (uint96);
function totalSupply() external view returns (uint256);
function transferFrom(address from, address to, uint256 tokenId) external;
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function minter() external view returns (address);
function mint() external returns (uint256);
function setApprovalForAll(address operator, bool approved) external;
}
interface IForkDAODeployer {
function deployForkDAO(
uint256 forkingPeriodEndTimestamp,
INounsDAOForkEscrow forkEscrowAddress
) external returns (address treasury, address token);
function tokenImpl() external view returns (address);
function auctionImpl() external view returns (address);
function governorImpl() external view returns (address);
function treasuryImpl() external view returns (address);
}
interface INounsDAOExecutorV2 is INounsDAOExecutor {
function sendETH(address recipient, uint256 ethToSend) external;
function sendERC20(address recipient, address erc20Token, uint256 tokensToSend) external;
}
interface INounsDAOForkEscrow {
function markOwner(address owner, uint256[] calldata tokenIds) external;
function returnTokensToOwner(address owner, uint256[] calldata tokenIds) external;
function closeEscrow() external returns (uint32);
function numTokensInEscrow() external view returns (uint256);
function numTokensOwnedByDAO() external view returns (uint256);
function withdrawTokens(uint256[] calldata tokenIds, address to) external;
function forkId() external view returns (uint32);
function nounsToken() external view returns (NounsTokenLike);
function dao() external view returns (address);
function ownerOfEscrowedToken(uint32 forkId_, uint256 tokenId) external view returns (address);
}
interface NounsDAOTypes {
struct Storage {
// ================ PROXY ================ //
/// @notice Administrator for this contract
address admin;
/// @notice Pending administrator for this contract
address pendingAdmin;
/// @notice Active brains of Governor
address implementation;
// ================ V1 ================ //
/// @notice Vetoer who has the ability to veto any proposal
address vetoer;
/// @notice The delay before voting on a proposal may take place, once proposed, in blocks
uint256 votingDelay;
/// @notice The duration of voting on a proposal, in blocks
uint256 votingPeriod;
/// @notice The basis point number of votes required in order for a voter to become a proposer. *DIFFERS from GovernerBravo
uint256 proposalThresholdBPS;
/// @notice The basis point number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed. *DIFFERS from GovernerBravo
uint256 quorumVotesBPS;
/// @notice The total number of proposals
uint256 proposalCount;
/// @notice The address of the Nouns DAO Executor NounsDAOExecutor
INounsDAOExecutorV2 timelock;
/// @notice The address of the Nouns tokens
NounsTokenLike nouns;
/// @notice The official record of all proposals ever proposed
mapping(uint256 => Proposal) _proposals;
/// @notice The latest proposal for each proposer
mapping(address => uint256) latestProposalIds;
// ================ V2 ================ //
DynamicQuorumParamsCheckpoint[] quorumParamsCheckpoints;
/// @notice Pending new vetoer
address pendingVetoer;
// ================ V3 ================ //
/// @notice user => sig => isCancelled: signatures that have been cancelled by the signer and are no longer valid
mapping(address => mapping(bytes32 => bool)) cancelledSigs;
/// @notice The number of blocks before voting ends during which the objection period can be initiated
uint32 lastMinuteWindowInBlocks;
/// @notice Length of the objection period in blocks
uint32 objectionPeriodDurationInBlocks;
/// @notice Length of proposal updatable period in block
uint32 proposalUpdatablePeriodInBlocks;
/// @notice address of the DAO's fork escrow contract
INounsDAOForkEscrow forkEscrow;
/// @notice address of the DAO's fork deployer contract
IForkDAODeployer forkDAODeployer;
/// @notice ERC20 tokens to include when sending funds to a deployed fork
address[] erc20TokensToIncludeInFork;
/// @notice The treasury contract of the last deployed fork
address forkDAOTreasury;
/// @notice The token contract of the last deployed fork
address forkDAOToken;
/// @notice Timestamp at which the last fork period ends
uint256 forkEndTimestamp;
/// @notice Fork period in seconds
uint256 forkPeriod;
/// @notice Threshold defined in basis points (10,000 = 100%) required for forking
uint256 forkThresholdBPS;
/// @notice Address of the original timelock
INounsDAOExecutor timelockV1;
/// @dev Make sure this stays the last variable in this struct, so we can delete it in the next version
/// @dev To be zeroed-out in the upcoming DAO upgrade.
uint256 voteSnapshotBlockSwitchProposalId;
}
struct Proposal {
/// @notice Unique id for looking up a proposal
uint32 id;
/// @notice client id for rewards
uint32 clientId;
/// @notice currently unused
uint192 _gap;
/// @notice Creator of the proposal
address proposer;
/// @notice The number of votes needed to create a proposal at the time of proposal creation. *DIFFERS from GovernerBravo
uint256 proposalThreshold;
/// @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. *DIFFERS from GovernerBravo
uint256 quorumVotes;
/// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds
uint256 eta;
/// @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 block at which voting begins: holders must delegate their votes prior to this block
uint256 startBlock;
/// @notice The block at which voting ends: votes must be cast prior to this block
uint256 endBlock;
/// @notice Current number of votes in favor of this proposal
uint256 forVotes;
/// @notice Current number of votes in opposition to this proposal
uint256 againstVotes;
/// @notice Current number of votes for abstaining for this proposal
uint256 abstainVotes;
/// @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 The total supply at the time of proposal creation
uint256 totalSupply;
/// @notice The block at which this proposal was created
uint32 creationBlock;
/// @notice The timestamp of the block at which this proposal was created
uint32 creationTimestamp;
/// @notice The last block which allows updating a proposal's description and transactions
uint64 updatePeriodEndBlock;
/// @notice Starts at 0 and is set to the block at which the objection period ends when the objection period is initiated
uint64 objectionPeriodEndBlock;
/// @dev unused for now
uint64 placeholder;
/// @notice The signers of a proposal, when using proposeBySigs
address[] signers;
/// @notice When true, a proposal would be executed on timelockV1 instead of the current timelock
bool executeOnTimelockV1;
/// @notice How many votes and vote transactions each clientId contributed to this proposal
mapping(uint32 => ClientVoteData) voteClients;
}
struct ClientVoteData {
/// @notice The number of votes the client facilitated on a proposal
uint32 votes;
/// @notice The number of vote transactions the client facilitated on a proposal
uint32 txs;
}
/// @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
uint96 votes;
}
struct ProposerSignature {
/// @notice Signature of a proposal
bytes sig;
/// @notice The address of the signer
address signer;
/// @notice The timestamp until which the signature is valid
uint256 expirationTimestamp;
}
/// @notice A subset of Proposal data, used for client rewards calculation
struct ProposalForRewards {
/// @notice The proposal's voting period end block
uint256 endBlock;
/// @notice The proposal's objection period end block
uint256 objectionPeriodEndBlock;
/// @notice The proposal's For votes count
uint256 forVotes;
/// @notice The proposal's Against votes count
uint256 againstVotes;
/// @notice The proposal's Abstain votes count
uint256 abstainVotes;
/// @notice The proposal's snapshot of total supply
uint256 totalSupply;
/// @notice The timestamp of the block at which the proposal was created
uint256 creationTimestamp;
/// @notice The ID for the client that facilitated the proposal
uint32 clientId;
ClientVoteData[] voteData;
}
struct ProposalCondensedV3 {
/// @notice Unique id for looking up a proposal
uint256 id;
/// @notice Creator of the proposal
address proposer;
/// @notice The number of votes needed to create a proposal at the time of proposal creation. *DIFFERS from GovernerBravo
uint256 proposalThreshold;
/// @notice The minimum 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. *DIFFERS from GovernerBravo
uint256 quorumVotes;
/// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds
uint256 eta;
/// @notice The block at which voting begins: holders must delegate their votes prior to this block
uint256 startBlock;
/// @notice The block at which voting ends: votes must be cast prior to this block
uint256 endBlock;
/// @notice Current number of votes in favor of this proposal
uint256 forVotes;
/// @notice Current number of votes in opposition to this proposal
uint256 againstVotes;
/// @notice Current number of votes for abstaining for this proposal
uint256 abstainVotes;
/// @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 The total supply at the time of proposal creation
uint256 totalSupply;
/// @notice The block at which this proposal was created
uint256 creationBlock;
/// @notice The signers of a proposal, when using proposeBySigs
address[] signers;
/// @notice The last block which allows updating a proposal's description and transactions
uint256 updatePeriodEndBlock;
/// @notice Starts at 0 and is set to the block at which the objection period ends when the objection period is initiated
uint256 objectionPeriodEndBlock;
/// @notice When true, a proposal would be executed on timelockV1 instead of the current timelock
bool executeOnTimelockV1;
}
struct ProposalCondensedV2 {
/// @notice Unique id for looking up a proposal
uint256 id;
/// @notice Creator of the proposal
address proposer;
/// @notice The number of votes needed to create a proposal at the time of proposal creation. *DIFFERS from GovernerBravo
uint256 proposalThreshold;
/// @notice The minimum 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. *DIFFERS from GovernerBravo
uint256 quorumVotes;
/// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds
uint256 eta;
/// @notice The block at which voting begins: holders must delegate their votes prior to this block
uint256 startBlock;
/// @notice The block at which voting ends: votes must be cast prior to this block
uint256 endBlock;
/// @notice Current number of votes in favor of this proposal
uint256 forVotes;
/// @notice Current number of votes in opposition to this proposal
uint256 againstVotes;
/// @notice Current number of votes for abstaining for this proposal
uint256 abstainVotes;
/// @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 The total supply at the time of proposal creation
uint256 totalSupply;
/// @notice The block at which this proposal was created
uint256 creationBlock;
}
struct DynamicQuorumParams {
/// @notice The minimum basis point number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed.
uint16 minQuorumVotesBPS;
/// @notice The maximum basis point number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed.
uint16 maxQuorumVotesBPS;
/// @notice The dynamic quorum coefficient
/// @dev Assumed to be fixed point integer with 6 decimals, i.e 0.2 is represented as 0.2 * 1e6 = 200000
uint32 quorumCoefficient;
}
struct NounsDAOParams {
uint256 votingPeriod;
uint256 votingDelay;
uint256 proposalThresholdBPS;
uint32 lastMinuteWindowInBlocks;
uint32 objectionPeriodDurationInBlocks;
uint32 proposalUpdatablePeriodInBlocks;
}
/// @notice A checkpoint for storing dynamic quorum params from a given block
struct DynamicQuorumParamsCheckpoint {
/// @notice The block at which the new values were set
uint32 fromBlock;
/// @notice The parameter values of this checkpoint
DynamicQuorumParams params;
}
/// @notice Possible states that a proposal may be in
enum ProposalState {
Pending,
Active,
Canceled,
Defeated,
Succeeded,
Queued,
Expired,
Executed,
Vetoed,
ObjectionPeriod,
Updatable
}
}
contract NounsDAOStorage is NounsDAOTypes {
Storage ds;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.0;
import "../ERC1967/ERC1967UpgradeUpgradeable.sol";
import "./Initializable.sol";
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*
* _Available since v4.1._
*/
abstract contract UUPSUpgradeable is Initializable, ERC1967UpgradeUpgradeable {
function __UUPSUpgradeable_init() internal initializer {
__ERC1967Upgrade_init_unchained();
__UUPSUpgradeable_init_unchained();
}
function __UUPSUpgradeable_init_unchained() internal initializer {
}
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address private immutable __self = address(this);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
require(address(this) != __self, "Function must be called through delegatecall");
require(_getImplementation() == __self, "Function must be called through active proxy");
_;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*/
function upgradeTo(address newImplementation) external virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallSecure(newImplementation, new bytes(0), false);
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*/
function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallSecure(newImplementation, data, true);
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeTo} and {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal override onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
function __Pausable_init() internal initializer {
__Context_init_unchained();
__Pausable_init_unchained();
}
function __Pausable_init_unchained() internal initializer {
_paused = false;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
uint256[49] private __gap;
}// SPDX-License-Identifier: GPL-3.0
/*********************************
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░█████████░░█████████░░░ *
* ░░░░░░██░░░████░░██░░░████░░░ *
* ░░██████░░░████████░░░████░░░ *
* ░░██░░██░░░████░░██░░░████░░░ *
* ░░██░░██░░░████░░██░░░████░░░ *
* ░░░░░░█████████░░█████████░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
*********************************/
pragma solidity ^0.8.19;
/**
* @notice A library for short lived in memory mappings.
* This only works when the keys, in this case clientId, are of limited size so that they we can create
* an array in memory for all the possible values
*/
library ClientRewardsMemoryMapping {
struct Mapping {
/// @dev indexes[clientId] returns the index in `values` array where the value for clientId is.
/// zero means it hasn't been initialized yet.
uint32[] indexes;
/// @dev array of values. the first cell (index zero) is kept empty.
ClientBalance[] values;
/// @dev index of the next cell in `values` array which we can allocate for a new clientId
uint32 nextAvailableIndex;
}
struct ClientBalance {
uint32 clientId;
uint256 balance;
}
/**
* Returns a new in memory mapping.
* @param maxClientId maximum value for a clientId key
*/
function createMapping(uint32 maxClientId) internal pure returns (Mapping memory m) {
m.indexes = new uint32[](maxClientId + 1);
/// @dev index zero is reserved so allocated one extra cell
m.values = new ClientBalance[](maxClientId + 2);
m.nextAvailableIndex = 1; // 0 is reserved to mean unindexed
}
/**
* Sets the value for client `clientId` to `balance`
*/
function set(Mapping memory m, uint32 clientId, uint256 balance) internal pure {
uint32 idx = m.indexes[clientId];
if (idx == 0) {
idx = m.nextAvailableIndex++;
m.indexes[clientId] = idx;
m.values[idx].clientId = clientId;
}
m.values[idx].balance = balance;
}
/**
* Increases the value of client `clientId` by `balanceDiff`
*/
function inc(Mapping memory m, uint32 clientId, uint256 balanceDiff) internal pure {
uint32 idx = m.indexes[clientId];
if (idx == 0) {
idx = m.nextAvailableIndex++;
m.indexes[clientId] = idx;
m.values[idx].clientId = clientId;
}
m.values[idx].balance += balanceDiff;
}
/**
* Returns the current value for client `clientId`
*/
function get(Mapping memory m, uint32 clientId) internal pure returns (uint256 balance) {
uint32 idx = m.indexes[clientId];
if (idx == 0) return 0;
return m.values[idx].balance;
}
/**
* Returns the number of key/values stored
*/
function numValues(Mapping memory m) internal pure returns (uint256) {
return m.nextAvailableIndex - 1;
}
/**
* Returns the idx-th value stored
*/
function getValue(Mapping memory m, uint32 idx) internal pure returns (ClientBalance memory) {
// zero index is unused
return m.values[idx + 1];
}
}// SPDX-License-Identifier: GPL-3.0
/*********************************
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░█████████░░█████████░░░ *
* ░░░░░░██░░░████░░██░░░████░░░ *
* ░░██████░░░████████░░░████░░░ *
* ░░██░░██░░░████░░██░░░████░░░ *
* ░░██░░██░░░████░░██░░░████░░░ *
* ░░░░░░█████████░░█████████░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
*********************************/
pragma solidity ^0.8.19;
import { SafeERC20 } from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
library GasRefund {
using SafeERC20 for IERC20;
/// @notice The maximum priority fee used to cap gas refunds
uint256 public constant MAX_REFUND_PRIORITY_FEE = 2 gwei;
/// @notice The vote refund gas overhead, including 7K for token transfer and 29K for general transaction overhead
uint256 public constant REFUND_BASE_GAS = 36000;
/// @notice The maximum basefee the DAO will refund
uint256 public constant MAX_REFUND_BASE_FEE = 200 gwei;
/// @dev refunds gas using the `ethToken` instead of ETH
function refundGas(IERC20 ethToken, uint256 startGas) internal {
unchecked {
uint256 balance = ethToken.balanceOf(address(this));
if (balance == 0) {
return;
}
uint256 basefee = min(block.basefee, MAX_REFUND_BASE_FEE);
uint256 gasPrice = min(tx.gasprice, basefee + MAX_REFUND_PRIORITY_FEE);
uint256 gasUsed = startGas - gasleft() + REFUND_BASE_GAS;
uint256 refundAmount = min(gasPrice * gasUsed, balance);
ethToken.safeTransfer(tx.origin, refundAmount);
}
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
}// SPDX-License-Identifier: GPL-3.0
/*********************************
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░█████████░░█████████░░░ *
* ░░░░░░██░░░████░░██░░░████░░░ *
* ░░██████░░░████████░░░████░░░ *
* ░░██░░██░░░████░░██░░░████░░░ *
* ░░██░░██░░░████░░██░░░████░░░ *
* ░░░░░░█████████░░█████████░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
*********************************/
pragma solidity ^0.8.19;
import { INounsClientTokenTypes } from './INounsClientTokenTypes.sol';
interface INounsClientTokenDescriptor {
function tokenURI(
uint256 tokenId,
INounsClientTokenTypes.ClientMetadata calldata metadata
) external view returns (string memory);
}// SPDX-License-Identifier: GPL-3.0
/*********************************
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░█████████░░█████████░░░ *
* ░░░░░░██░░░████░░██░░░████░░░ *
* ░░██████░░░████████░░░████░░░ *
* ░░██░░██░░░████░░██░░░████░░░ *
* ░░██░░██░░░████░░██░░░████░░░ *
* ░░░░░░█████████░░█████████░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
*********************************/
pragma solidity ^0.8.19;
interface INounsClientTokenTypes {
struct ClientMetadata {
/// @notice Whether the DAO has approved the client to withdraw their rewards.
bool approved;
/// @notice The amount of reward tokens this client has been rewarded.
uint96 rewarded;
/// @notice The amount of tokens this client has withdrawn.
uint96 withdrawn;
/// @dev A gap for future storage needs.
uint56 __gap;
/// @notice The client's display name.
string name;
/// @notice The client's description, e.g. its URL.
string description;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal initializer {
__Context_init_unchained();
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal initializer {
_transferOwnership(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC721/ERC721.sol)
pragma solidity ^0.8.0;
import "./IERC721Upgradeable.sol";
import "./IERC721ReceiverUpgradeable.sol";
import "./extensions/IERC721MetadataUpgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
import "../../utils/ContextUpgradeable.sol";
import "../../utils/StringsUpgradeable.sol";
import "../../utils/introspection/ERC165Upgradeable.sol";
import "../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable {
using AddressUpgradeable for address;
using StringsUpgradeable for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to owner address
mapping(uint256 => address) private _owners;
// Mapping owner address to token count
mapping(address => uint256) private _balances;
// Mapping from token ID to approved address
mapping(uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
function __ERC721_init(string memory name_, string memory symbol_) internal initializer {
__Context_init_unchained();
__ERC165_init_unchained();
__ERC721_init_unchained(name_, symbol_);
}
function __ERC721_init_unchained(string memory name_, string memory symbol_) internal initializer {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {
return
interfaceId == type(IERC721Upgradeable).interfaceId ||
interfaceId == type(IERC721MetadataUpgradeable).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overriden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721Upgradeable.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* `_data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721Upgradeable.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721Upgradeable.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
// Clear approvals
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721Upgradeable.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
// Clear approvals from the previous owner
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits a {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits a {ApprovalForAll} event.
*/
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try IERC721ReceiverUpgradeable(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721ReceiverUpgradeable.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
uint256[44] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/math/SafeCast.sol)
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 uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
return uint224(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
/**
* @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
*/
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 uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
return uint64(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
*/
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 uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v3.1._
*/
function toInt128(int256 value) internal pure returns (int128) {
require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits");
return int128(value);
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v3.1._
*/
function toInt64(int256 value) internal pure returns (int64) {
require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits");
return int64(value);
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v3.1._
*/
function toInt32(int256 value) internal pure returns (int32) {
require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits");
return int32(value);
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v3.1._
*/
function toInt16(int256 value) internal pure returns (int16) {
require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits");
return int16(value);
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*
* _Available since v3.1._
*/
function toInt8(int256 value) internal pure returns (int8) {
require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits");
return int8(value);
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeaconUpgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
import "../../utils/StorageSlotUpgradeable.sol";
import "../utils/Initializable.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*
* @custom:oz-upgrades-unsafe-allow delegatecall
*/
abstract contract ERC1967UpgradeUpgradeable is Initializable {
function __ERC1967Upgrade_init() internal initializer {
__ERC1967Upgrade_init_unchained();
}
function __ERC1967Upgrade_init_unchained() internal initializer {
}
// This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(
address newImplementation,
bytes memory data,
bool forceCall
) internal {
_upgradeTo(newImplementation);
if (data.length > 0 || forceCall) {
_functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallSecure(
address newImplementation,
bytes memory data,
bool forceCall
) internal {
address oldImplementation = _getImplementation();
// Initial upgrade and setup call
_setImplementation(newImplementation);
if (data.length > 0 || forceCall) {
_functionDelegateCall(newImplementation, data);
}
// Perform rollback test if not already in progress
StorageSlotUpgradeable.BooleanSlot storage rollbackTesting = StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT);
if (!rollbackTesting.value) {
// Trigger rollback using upgradeTo from the new implementation
rollbackTesting.value = true;
_functionDelegateCall(
newImplementation,
abi.encodeWithSignature("upgradeTo(address)", oldImplementation)
);
rollbackTesting.value = false;
// Check rollback was effective
require(oldImplementation == _getImplementation(), "ERC1967Upgrade: upgrade breaks further upgrades");
// Finally reset to the new implementation and log the upgrade
_upgradeTo(newImplementation);
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Emitted when the beacon is upgraded.
*/
event BeaconUpgraded(address indexed beacon);
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(
address newBeacon,
bytes memory data,
bool forceCall
) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
_functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);
}
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function _functionDelegateCall(address target, bytes memory data) private returns (bytes memory) {
require(AddressUpgradeable.isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return AddressUpgradeable.verifyCallResult(success, returndata, "Address: low-level delegate call failed");
}
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (proxy/utils/Initializable.sol)
pragma solidity ^0.8.0;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
* initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() initializer {}
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
require(_initializing || !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Address.sol)
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal initializer {
__Context_init_unchained();
}
function __Context_init_unchained() internal initializer {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165Upgradeable.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721Upgradeable is IERC165Upgradeable {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721ReceiverUpgradeable {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC721Upgradeable.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721MetadataUpgradeable is IERC721Upgradeable {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Address.sol)
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library StringsUpgradeable {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165Upgradeable.sol";
import "../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {
function __ERC165_init() internal initializer {
__ERC165_init_unchained();
}
function __ERC165_init_unchained() internal initializer {
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165Upgradeable).interfaceId;
}
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.0;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeaconUpgradeable {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {BeaconProxy} will check that this address is a contract.
*/
function implementation() external view returns (address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/StorageSlot.sol)
pragma solidity ^0.8.0;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
*/
library StorageSlotUpgradeable {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly {
r.slot := slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165Upgradeable {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}{
"remappings": [
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"@ensdomains/=../../node_modules/@ensdomains/",
"@openzeppelin/=../../node_modules/@openzeppelin/",
"base64-sol/=../../node_modules/base64-sol/",
"eth-gas-reporter/=../../node_modules/eth-gas-reporter/",
"hardhat/=../../node_modules/hardhat/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"nounsDAO_","type":"address"},{"internalType":"address","name":"auctionHouse_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"LastNounIdMustBeHigher","type":"error"},{"inputs":[],"name":"LastNounIdMustBeSettled","type":"error"},{"inputs":[],"name":"OnlyNFTOwner","type":"error"},{"inputs":[],"name":"OnlyOwnerOrAdmin","type":"error"},{"inputs":[],"name":"RewardsDisabled","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","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":[],"name":"AuctionRewardsDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"nextAuctionIdToReward","type":"uint32"}],"name":"AuctionRewardsEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"firstAuctionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastAuctionId","type":"uint256"}],"name":"AuctionRewardsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"clientId","type":"uint32"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ClientApprovalSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"clientId","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"ClientBalanceWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"clientId","type":"uint32"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"description","type":"string"}],"name":"ClientRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"clientId","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClientRewarded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"clientId","type":"uint32"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"description","type":"string"}],"name":"ClientUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[],"name":"ProposalRewardsDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"nextProposalIdToReward","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"nextProposalRewardFirstAuctionId","type":"uint32"}],"name":"ProposalRewardsEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"firstProposalId","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"lastProposalId","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"firstAuctionIdForRevenue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastAuctionIdForRevenue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"auctionRevenue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardPerProposal","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardPerVote","type":"uint256"}],"name":"ProposalRewardsUpdated","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":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"RewardsStorageLocation","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"auctionHouse","outputs":[{"internalType":"contract INounsAuctionHouseV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"auctionRewardsEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"clientId","type":"uint32"}],"name":"clientBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"tokenId","type":"uint32"}],"name":"clientMetadata","outputs":[{"components":[{"internalType":"bool","name":"approved","type":"bool"},{"internalType":"uint96","name":"rewarded","type":"uint96"},{"internalType":"uint96","name":"withdrawn","type":"uint96"},{"internalType":"uint56","name":"__gap","type":"uint56"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"description","type":"string"}],"internalType":"struct INounsClientTokenTypes.ClientMetadata","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"descriptor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"disableAuctionRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableProposalRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableAuctionRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableProposalRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ethToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"firstNounId","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"}],"name":"getAuctionRevenue","outputs":[{"internalType":"uint256","name":"sumRevenue","type":"uint256"},{"internalType":"uint256","name":"lastAuctionId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAuctionRewardParams","outputs":[{"components":[{"internalType":"uint16","name":"auctionRewardBps","type":"uint16"},{"internalType":"uint8","name":"minimumAuctionsBetweenUpdates","type":"uint8"}],"internalType":"struct Rewards.AuctionRewardParams","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProposalRewardParams","outputs":[{"components":[{"internalType":"uint32","name":"minimumRewardPeriod","type":"uint32"},{"internalType":"uint8","name":"numProposalsEnoughForReward","type":"uint8"},{"internalType":"uint16","name":"proposalRewardBps","type":"uint16"},{"internalType":"uint16","name":"votingRewardBps","type":"uint16"},{"internalType":"uint16","name":"proposalEligibilityQuorumBps","type":"uint16"}],"internalType":"struct Rewards.ProposalRewardParams","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"lastProposalId","type":"uint32"}],"name":"getVotingClientIds","outputs":[{"internalType":"uint32[]","name":"","type":"uint32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"admin_","type":"address"},{"internalType":"address","name":"ethToken_","type":"address"},{"internalType":"address","name":"descriptor_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastProposalRewardsUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextAuctionIdToReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextProposalIdToReward","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextProposalRewardFirstAuctionId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextTokenId","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nounsDAO","outputs":[{"internalType":"contract INounsDAOLogic","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalRewardsEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"description","type":"string"}],"name":"registerClient","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","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":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"setAdmin","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":[{"components":[{"internalType":"uint16","name":"auctionRewardBps","type":"uint16"},{"internalType":"uint8","name":"minimumAuctionsBetweenUpdates","type":"uint8"}],"internalType":"struct Rewards.AuctionRewardParams","name":"newParams","type":"tuple"}],"name":"setAuctionRewardParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"clientId","type":"uint32"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setClientApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"descriptor_","type":"address"}],"name":"setDescriptor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newToken","type":"address"}],"name":"setETHToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"minimumRewardPeriod","type":"uint32"},{"internalType":"uint8","name":"numProposalsEnoughForReward","type":"uint8"},{"internalType":"uint16","name":"proposalRewardBps","type":"uint16"},{"internalType":"uint16","name":"votingRewardBps","type":"uint16"},{"internalType":"uint16","name":"proposalEligibilityQuorumBps","type":"uint16"}],"internalType":"struct Rewards.ProposalRewardParams","name":"newParams","type":"tuple"}],"name":"setProposalRewardParams","outputs":[],"stateMutability":"nonpayable","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":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"tokenId","type":"uint32"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"description","type":"string"}],"name":"updateClientMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"lastNounId","type":"uint32"}],"name":"updateRewardsForAuctions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"lastProposalId","type":"uint32"},{"internalType":"uint32[]","name":"votingClientIds","type":"uint32[]"}],"name":"updateRewardsForProposalWritingAndVoting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"clientId","type":"uint32"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"withdrawClientBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60e0604052306080523480156200001557600080fd5b50604051620061ad380380620061ad833981016040819052620000389162000129565b600054610100900460ff168062000052575060005460ff16155b620000ba5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b600054610100900460ff16158015620000dd576000805461ffff19166101011790555b6001600160a01b0380841660a052821660c052801562000103576000805461ff00191690555b50505062000161565b80516001600160a01b03811681146200012457600080fd5b919050565b600080604083850312156200013d57600080fd5b62000148836200010c565b915062000158602084016200010c565b90509250929050565b60805160a05160c051615fcf620001de60003960008181610a7a01528181610ce201528181610ef001528181611a2c015261325a0152600081816105a901528181610c49015281816115630152818161280f01526129810152600081816113d50152818161141501528181611d6a0152611daa0152615fcf6000f3fe6080604052600436106103765760003560e01c8063704b6c02116101d1578063ac4951f611610102578063cc9df021116100a0578063ed9152c81161006f578063ed9152c814610a68578063f2fde38b14610a9c578063f851a44014610abc578063f8c8765e14610ad157600080fd5b8063cc9df021146109fe578063d0e1a84614610a1e578063d715d10114610a33578063e985e9c514610a4857600080fd5b8063bce7f0da116100dc578063bce7f0da14610994578063becbeb22146109a9578063c37bb58b146109c9578063c87b56dd146109de57600080fd5b8063ac4951f61461091c578063b289a2bb1461093c578063b88d4fde1461097457600080fd5b80638d9763231161016f57806395d89b411161014957806395d89b411461089b578063a22cb465146108b0578063a412bfbb146108d0578063a556ba311461090757600080fd5b80638d976323146108035780638da5cb5b1461081857806392c6d4201461083657600080fd5b806375794a3c116101ab57806375794a3c146107a45780637bf1a627146107b95780637d15f041146107ce5780638456cb59146107ee57600080fd5b8063704b6c021461074f57806370a082311461076f578063715018a61461078f57600080fd5b8063337344a2116102ab5780634818ac421161024957806354b1faeb1161022357806354b1faeb146106d55780635c975abb146106ea5780635f27663b146107025780636352211e1461072f57600080fd5b80634818ac42146106825780634f1ef286146106a25780634fc8d76a146106b557600080fd5b80633f4ba83a116102855780633f4ba83a146106185780633fabc2521461062d57806342842e0e146106425780634364d9731461066257600080fd5b8063337344a2146105975780633659cfe6146105cb5780633b5003c0146105eb57600080fd5b8063095ea7b31161031857806320e47641116102f257806320e476411461051857806323b872dd146105385780632a72731114610558578063303e74df1461058257600080fd5b8063095ea7b31461049657806317cb7292146104b65780631ac8875d146104d657600080fd5b80630553d778116103545780630553d778146103f257806306fdde031461040757806307d7461e14610429578063081812fc1461045e57600080fd5b806301b9a3971461037b57806301e336671461039d57806301ffc9a7146103bd575b600080fd5b34801561038757600080fd5b5061039b610396366004614a6b565b610af1565b005b3480156103a957600080fd5b5061039b6103b8366004614a88565b610b6e565b3480156103c957600080fd5b506103dd6103d8366004614adf565b610bba565b60405190151581526020015b60405180910390f35b3480156103fe57600080fd5b5061039b610c0c565b34801561041357600080fd5b5061041c610e2a565b6040516103e99190614b4c565b34801561043557600080fd5b50610449610444366004614b5f565b610ebd565b604080519283526020830191909152016103e9565b34801561046a57600080fd5b5061047e610479366004614b81565b610fa1565b6040516001600160a01b0390911681526020016103e9565b3480156104a257600080fd5b5061039b6104b1366004614b9a565b611038565b3480156104c257600080fd5b5061039b6104d1366004614bc6565b611148565b3480156104e257600080fd5b5061050a7f9a06af3161ac5b0c3de4e6c981ab9d9f60b530386f5eaae00d541393fbecd70081565b6040519081526020016103e9565b34801561052457600080fd5b5061039b610533366004614bff565b611188565b34801561054457600080fd5b5061039b610553366004614a88565b611361565b34801561056457600080fd5b5061056d611392565b60405163ffffffff90911681526020016103e9565b34801561058e57600080fd5b5061047e6113af565b3480156105a357600080fd5b5061047e7f000000000000000000000000000000000000000000000000000000000000000081565b3480156105d757600080fd5b5061039b6105e6366004614a6b565b6113cb565b3480156105f757600080fd5b5061060b610606366004614c4a565b611493565b6040516103e99190614ca9565b34801561062457600080fd5b5061039b6117c0565b34801561063957600080fd5b5061050a611817565b34801561064e57600080fd5b5061039b61065d366004614a88565b611834565b34801561066e57600080fd5b5061056d61067d366004614d04565b61184f565b34801561068e57600080fd5b5061039b61069d366004614c4a565b611943565b61039b6106b0366004614e9f565b611d60565b3480156106c157600080fd5b5061039b6106d0366004614eee565b611e19565b3480156106e157600080fd5b5061050a611e59565b3480156106f657600080fd5b5060975460ff166103dd565b34801561070e57600080fd5b5061072261071d366004614c4a565b611e76565b6040516103e99190614f00565b34801561073b57600080fd5b5061047e61074a366004614b81565b61204f565b34801561075b57600080fd5b5061039b61076a366004614a6b565b6120c7565b34801561077b57600080fd5b5061050a61078a366004614a6b565b61211e565b34801561079b57600080fd5b5061039b6121a6565b3480156107b057600080fd5b5061056d6121dc565b3480156107c557600080fd5b5061047e6121f2565b3480156107da57600080fd5b5061039b6107e9366004614a6b565b61220e565b3480156107fa57600080fd5b5061039b612265565b34801561080f57600080fd5b5061039b6122bc565b34801561082457600080fd5b5060c9546001600160a01b031661047e565b34801561084257600080fd5b5061084b612337565b60408051825163ffffffff16815260208084015160ff16908201528282015161ffff908116928201929092526060808401518316908201526080928301519091169181019190915260a0016103e9565b3480156108a757600080fd5b5061041c6123c7565b3480156108bc57600080fd5b5061039b6108cb366004614f89565b6123d7565b3480156108dc57600080fd5b506108e56123e2565b60408051825161ffff16815260209283015160ff1692810192909252016103e9565b34801561091357600080fd5b506103dd612429565b34801561092857600080fd5b5061039b610937366004614fc2565b612444565b34801561094857600080fd5b5061095c610957366004614c4a565b6124e2565b6040516001600160601b0390911681526020016103e9565b34801561098057600080fd5b5061039b61098f366004614fe0565b61252b565b3480156109a057600080fd5b5061039b612563565b3480156109b557600080fd5b5061039b6109c436600461504b565b6125dc565b3480156109d557600080fd5b506103dd6126a3565b3480156109ea57600080fd5b5061041c6109f9366004614b81565b6126bd565b348015610a0a57600080fd5b5061039b610a193660046150cd565b612763565b348015610a2a57600080fd5b5061039b61321d565b348015610a3f57600080fd5b5061050a613330565b348015610a5457600080fd5b506103dd610a63366004615154565b61334e565b348015610a7457600080fd5b5061047e7f000000000000000000000000000000000000000000000000000000000000000081565b348015610aa857600080fd5b5061039b610ab7366004614a6b565b61337d565b348015610ac857600080fd5b5061047e613415565b348015610add57600080fd5b5061039b610aec366004615182565b613431565b6000610afb613564565b60c9549091506001600160a01b0316331480610b23575060048101546001600160a01b031633145b610b4057604051636f0cab8b60e11b815260040160405180910390fd5b81610b49613564565b60060180546001600160a01b0319166001600160a01b03929092169190911790555050565b60c9546001600160a01b03163314610ba15760405162461bcd60e51b8152600401610b98906151de565b60405180910390fd5b610bb56001600160a01b0384168383613588565b505050565b60006001600160e01b031982166380ac58cd60e01b1480610beb57506001600160e01b03198216635b5e139f60e01b145b80610c0657506301ffc9a760e01b6001600160e01b03198316145b92915050565b60c9546001600160a01b03163314610c365760405162461bcd60e51b8152600401610b98906151de565b6000610c40613564565b90506000610cd97f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663da35c6646040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ca5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc99190615213565b610cd4906001615242565b6135da565b90506000610d717f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637d9f6db56040518163ffffffff1660e01b815260040160c060405180830381865afa158015610d3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d62919061527a565b516001600160601b03166135da565b8354600160481b67ffffffffffffffff60501b19909116600160501b63ffffffff86811691820263ffffffff60701b191692909217600160701b9285169283021776ffffffffff0000000000000000ff0000000000000000001916600160901b4264ffffffffff160260ff60481b1916179290921786556040805192835260208301919091529192507fda1b197b06385756fea2566b6b617ea13d1b3d772596d5e7ad6651385ef7acf7910160405180910390a1505050565b606061012d8054610e3a90615333565b80601f0160208091040260200160405190810160405280929190818152602001828054610e6690615333565b8015610eb35780601f10610e8857610100808354040283529160200191610eb3565b820191906000526020600020905b815481529060010190602001808311610e9657829003601f168201915b5050505050905090565b6040516309b8570960e01b8152600481018390526024810182905260016044820152600090819081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906309b8570990606401600060405180830381865afa158015610f37573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f5f9190810190615395565b9050610f6a81613643565b92508060018251610f7b9190615481565b81518110610f8b57610f8b615494565b6020026020010151606001519150509250929050565b600081815261012f60205260408120546001600160a01b031661101b5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610b98565b50600090815261013160205260409020546001600160a01b031690565b60006110438261204f565b9050806001600160a01b0316836001600160a01b0316036110b05760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610b98565b336001600160a01b03821614806110cc57506110cc813361334e565b61113e5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610b98565b610bb58383613689565b60c9546001600160a01b031633146111725760405162461bcd60e51b8152600401610b98906151de565b8061117b613564565b600201610bb582826154d1565b60975460ff16156111ab5760405162461bcd60e51b8152600401610b9890615510565b60006111b5613564565b63ffffffff85166000818152600583016020526040902091925033906111da9061204f565b6001600160a01b03161461120157604051636a45792360e11b815260040160405180910390fd5b805460ff166112415760405162461bcd60e51b815260206004820152600c60248201526b1b9bdd08185c1c1c9bdd995960a21b6044820152606401610b98565b80546001600160601b03600160681b820481169161126691839161010090041661553a565b6001600160601b0316846001600160601b031611156112ba5760405162461bcd60e51b815260206004820152601060248201526f616d6f756e7420746f6f206c6172676560801b6044820152606401610b98565b6112c48482615561565b82546bffffffffffffffffffffffff60681b1916600160681b6001600160601b03928316021783556040805191861682526001600160a01b038716602083015263ffffffff8816917f1812827f1c6a24a5651bf4de08620620edf7827369871a784625bf0ad118f120910160405180910390a26003830154611359906001600160a01b0316866001600160601b038716613588565b505050505050565b61136b33826136f8565b6113875760405162461bcd60e51b8152600401610b9890615581565b610bb58383836137c8565b600061139c613564565b54600160501b900463ffffffff16919050565b60006113b9613564565b600601546001600160a01b0316919050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036114135760405162461bcd60e51b8152600401610b98906155d2565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661144561396b565b6001600160a01b03161461146b5760405162461bcd60e51b8152600401610b989061561e565b61147481613999565b60408051600080825260208201909252611490918391906139c3565b50565b6060600061149f613564565b905060006114ab6121dc565b63ffffffff1690506000816001600160401b038111156114cd576114cd614d6f565b6040519080825280602002602001820160405280156114f6578160200160208202803683370190505b50905060005b828163ffffffff1610156115485780828263ffffffff168151811061152357611523615494565b63ffffffff909216602092830291909101909101526115418161566a565b90506114fc565b50825460018085015460405163aa0e23c760e01b81526000937f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169363aa0e23c7936115c193600160501b90930463ffffffff16928c92600160481b90920461ffff16919081908a9060040161568d565b600060405180830381865afa1580156115de573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116069190810190615778565b90506000836001600160401b0381111561162257611622614d6f565b60405190808252806020026020018201604052801561164b578160200160208202803683370190505b50905060005b82518110156116e15760005b858110156116d85783828151811061167757611677615494565b60200260200101516101000151818151811061169557611695615494565b6020026020010151600001518382815181106116b3576116b3615494565b602002602001018181516116c791906158bd565b63ffffffff1690525060010161165d565b50600101611651565b50600080856001600160401b038111156116fd576116fd614d6f565b604051908082528060200260200182016040528015611726578160200160208202803683370190505b50905060005b868163ffffffff1610156117b1576000848263ffffffff168151811061175457611754615494565b602002602001015163ffffffff1611156117a157808284611774816158da565b95508151811061178657611786615494565b602002602001019063ffffffff16908163ffffffff16815250505b6117aa8161566a565b905061172c565b50908152979650505050505050565b60006117ca613564565b60c9549091506001600160a01b03163314806117f2575060048101546001600160a01b031633145b61180f57604051636f0cab8b60e11b815260040160405180910390fd5b611490613b07565b6000611821613564565b54600160281b900463ffffffff16919050565b610bb58383836040518060200160405280600081525061252b565b600061185d60975460ff1690565b1561187a5760405162461bcd60e51b8152600401610b9890615510565b6000611884613564565b805490915063ffffffff1661189a8160016158bd565b825463ffffffff191663ffffffff9182161783556118bb9033908316613b9a565b63ffffffff811660009081526005830160205260409020600181016118e1888a8361593b565b50600281016118f186888361593b565b508163ffffffff167f65beab8930287623c694d7e645cdd4b7b83bebaaac913f30933d4c691a271e3c8989898960405161192e9493929190615a23565b60405180910390a2509150505b949350505050565b60975460ff16156119665760405162461bcd60e51b8152600401610b9890615510565b60005a90506000611975613564565b8054909150640100000000900460ff166119a2576040516333d63cbd60e01b815260040160405180910390fd5b80546002820154600091600160281b900463ffffffff16906119cd9062010000900460ff1682615242565b8563ffffffff1610156119f35760405163268bc0ad60e01b815260040160405180910390fd5b6119fe8560016158bd565b835463ffffffff91909116600160281b0268ffffffff00000000001990911617835560006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663b1296a9483611a5d8960016158bd565b6040516001600160e01b031960e085901b168152600481019290925263ffffffff16602482015260016044820152606401600060405180830381865afa158015611aab573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611ad39190810190615395565b905060008160018351611ae69190615481565b81518110611af657611af6615494565b602002602001015190508663ffffffff168160600151148015611b2357506001816000015163ffffffff16115b611b40576040516368752cd160e01b815260040160405180910390fd5b60006001611b4c6121dc565b611b569190615a4a565b90506000611b6382613cdf565b905060005b8451811015611be1576000858281518110611b8557611b85615494565b60200260200101519050806080015163ffffffff16600014158015611bba57508363ffffffff16816080015163ffffffff1611155b15611bd8576080810151602082015160019950611bd8918591613dce565b50600101611b68565b50600287015461ffff166000611bf683613ecd565b905060005b818163ffffffff161015611cf6576000611c158583613eec565b905060006127108561ffff168360200151611c309190615a67565b611c3a9190615a7e565b9050611c4581613f36565b825163ffffffff16600090815260058e01602052604090208054600190611c7b90849061010090046001600160601b0316615561565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550816000015163ffffffff167f8a6390ffb12581558b6798514e694cb23b44ff553c82d4e69024ab1fe2230ae282604051611cdb91815260200190565b60405180910390a2505080611cef9061566a565b9050611bfb565b506040805188815263ffffffff8d1660208201527ff48a534da18c3b27deb2da48e4a2d8b1888ad5cb761889d25b692de9da944d22910160405180910390a18715611d53576003890154611d53906001600160a01b03168b613f9e565b5050505050505050505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611da85760405162461bcd60e51b8152600401610b98906155d2565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611dda61396b565b6001600160a01b031614611e005760405162461bcd60e51b8152600401610b989061561e565b611e0982613999565b611e15828260016139c3565b5050565b60c9546001600160a01b03163314611e435760405162461bcd60e51b8152600401610b98906151de565b80611e4c613564565b600101610bb58282615aa0565b6000611e63613564565b54600160701b900463ffffffff16919050565b6040805160c0810182526000808252602082018190529181018290526060808201929092526080810182905260a0810191909152611eb2613564565b63ffffffff831660009081526005919091016020908152604091829020825160c081018452815460ff81161515825261010081046001600160601b0390811694830194909452600160681b810490931693810193909352600160c81b90910466ffffffffffffff166060830152600181018054608084019190611f3490615333565b80601f0160208091040260200160405190810160405280929190818152602001828054611f6090615333565b8015611fad5780601f10611f8257610100808354040283529160200191611fad565b820191906000526020600020905b815481529060010190602001808311611f9057829003601f168201915b50505050508152602001600282018054611fc690615333565b80601f0160208091040260200160405190810160405280929190818152602001828054611ff290615333565b801561203f5780601f106120145761010080835404028352916020019161203f565b820191906000526020600020905b81548152906001019060200180831161202257829003601f168201915b5050505050815250509050919050565b600081815261012f60205260408120546001600160a01b031680610c065760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610b98565b60c9546001600160a01b031633146120f15760405162461bcd60e51b8152600401610b98906151de565b806120fa613564565b60040180546001600160a01b0319166001600160a01b039290921691909117905550565b60006001600160a01b0382166121895760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610b98565b506001600160a01b03166000908152610130602052604090205490565b60c9546001600160a01b031633146121d05760405162461bcd60e51b8152600401610b98906151de565b6121da6000614077565b565b60006121e6613564565b5463ffffffff16919050565b60006121fc613564565b600301546001600160a01b0316919050565b60c9546001600160a01b031633146122385760405162461bcd60e51b8152600401610b98906151de565b80612241613564565b60030180546001600160a01b0319166001600160a01b039290921691909117905550565b600061226f613564565b60c9549091506001600160a01b0316331480612297575060048101546001600160a01b031633145b6122b457604051636f0cab8b60e11b815260040160405180910390fd5b6114906140c9565b60c9546001600160a01b031633146122e65760405162461bcd60e51b8152600401610b98906151de565b60006122f0613564565b80549115156401000000000264ff00000000199092169190911790556040517f2b6b9a9cec683ce4fb9078fe61298719dcfeb0c26e7217bc748101cd3994367590600090a1565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261236a613564565b6040805160a0810182526001929092015463ffffffff8116835260ff640100000000820416602084015261ffff600160281b8204811692840192909252600160381b810482166060840152600160481b9004166080820152919050565b606061012e8054610e3a90615333565b611e15338383614121565b60408051808201909152600080825260208201526123fe613564565b604080518082019091526002919091015461ffff8116825262010000900460ff166020820152919050565b6000612433613564565b54640100000000900460ff16919050565b60c9546001600160a01b0316331461246e5760405162461bcd60e51b8152600401610b98906151de565b6000612478613564565b63ffffffff8416600081815260058301602052604090819020805486151560ff1990911617905551919250907f0f437477476c892b5eab47c4de7c7b038039c74ddde189b97d3315378149d7cb906124d590851515815260200190565b60405180910390a2505050565b6000806124ed613564565b63ffffffff84166000908152600582016020526040902080549192509061193b906001600160601b03600160681b820481169161010090041661553a565b61253533836136f8565b6125515760405162461bcd60e51b8152600401610b9890615581565b61255d848484846141f0565b50505050565b60c9546001600160a01b0316331461258d5760405162461bcd60e51b8152600401610b98906151de565b6000612597613564565b8054911515600160481b0260ff60481b199092169190911790556040517f59a08195999a8f63cd06ccede81a2f98993507dd88f42e1cc630e3df00a1534590600090a1565b60006125e6613564565b9050336125f863ffffffff881661204f565b6001600160a01b03161461261f57604051636a45792360e11b815260040160405180910390fd5b63ffffffff8616600090815260058201602052604090206001810161264586888361593b565b506002810161265584868361593b565b508663ffffffff167f0bee293e8de088ced65538b9072d95ce36471240b1de1e8193ab5e9391294583878787876040516126929493929190615a23565b60405180910390a250505050505050565b60006126ad613564565b54600160481b900460ff16919050565b606060006126c9613564565b600681015463ffffffff85166000908152600583016020526040908190209051635fa2601560e01b81529293506001600160a01b0390911691635fa260159161271791879190600401615bf3565b600060405180830381865afa158015612734573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261275c9190810190615c72565b9392505050565b60975460ff16156127865760405162461bcd60e51b8152600401610b9890615510565b60005a90506000612795613564565b8054909150600160481b900460ff166127c1576040516333d63cbd60e01b815260040160405180910390fd5b6127c96149b9565b60016127d36121dc565b6127dd9190615a4a565b63ffffffff908116825282546040805163368d719960e21b81529051600160501b909204909216916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163da35c664916004808201926020929091908290030181865afa15801561285b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061287f9190615213565b8763ffffffff16111580156128a057508063ffffffff168763ffffffff1610155b6128e15760405162461bcd60e51b8152602060048201526012602482015271189859081b185cdd141c9bdc1bdcd85b125960721b6044820152606401610b98565b61291d86868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061422392505050565b6129695760405162461bcd60e51b815260206004820152601760248201527f6d75737420626520736f72746564202620756e697175650000000000000000006044820152606401610b98565b60018381015460405163aa0e23c760e01b81526000927f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169263aa0e23c7926129d49287928e92600160481b90910461ffff16919081908f908f90600401615cdf565b600060405180830381865afa1580156129f1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612a199190810190615778565b90506000815111612a6c5760405162461bcd60e51b815260206004820152601e60248201527f6174206c65617374206f6e6520656c696769626c652070726f706f73616c00006044820152606401610b98565b612a778860016158bd565b845463ffffffff91909116600160501b0263ffffffff60501b1990911617845580518190612aa790600190615481565b81518110612ab757612ab7615494565b602090810291909101015160e084018190528454600160701b900463ffffffff1660c0808601829052909101516000918291612af39190610ebd565b9092509050612b038160016158bd565b865463ffffffff91909116600160701b0263ffffffff60701b1990911617865581612b705760405162461bcd60e51b815260206004820152601a60248201527f61756374696f6e526576656e7565206d757374206265203e20300000000000006044820152606401610b98565b600186015461271090612b8e90600160281b900461ffff1684615a67565b612b989190615a7e565b6080860152600186015461271090612bbb90600160381b900461ffff1684615a67565b612bc59190615a7e565b60a086015260005b8351811015612c66576000848281518110612bea57612bea615494565b602002602001015160800151858381518110612c0857612c08615494565b602002602001015160600151868481518110612c2657612c26615494565b602002602001015160400151612c3c9190615242565b612c469190615242565b90508087602001818151612c5a9190615242565b90525050600101612bcd565b506001860154835164010000000090910460ff161115612cfb5760018601548654612ca59163ffffffff1690600160901b900464ffffffffff16615d62565b64ffffffffff168560e0015160c0015111612cfb5760405162461bcd60e51b81526020600482015260166024820152751b9bdd08195b9bdd59da081d1a5b59481c185cdcd95960521b6044820152606401610b98565b60e085015160c00151865464ffffffffff909116600160901b0264ffffffffff60901b1990911617865582516080860151612d369190615a7e565b6040860152602085015160a0860151612d4f9190615a7e565b8560600181815250507fb3719109848cd6df9b4ff39633f0b408e8595e8415ec7bc319800ab3a9dba95d848b8760c0015184868a604001518b60600151604051612dd5979695949392919063ffffffff978816815295909616602086015260408501939093526060840191909152608083015260a082015260c081019190915260e00190565b60405180910390a16000612dec8660000151613cdf565b90506000896001600160401b03811115612e0857612e08614d6f565b604051908082528060200260200182016040528015612e31578160200160208202803683370190505b50905060005b855181101561308d576000868281518110612e5457612e54615494565b602002602001015160e0015190508063ffffffff16600014158015612e895750886000015163ffffffff168163ffffffff1611155b15612ea0576040890151612ea09085908390613dce565b600080888481518110612eb557612eb5615494565b60200260200101516101000151905060005b8e811015612fc2578f8f82818110612ee157612ee1615494565b9050602002016020810190612ef69190614c4a565b93506000828281518110612f0c57612f0c615494565b60200260200101516000015163ffffffff169050868281518110612f3257612f32615494565b602002602001015180612f455750600081115b878381518110612f5757612f57615494565b9115156020928302919091019091015263ffffffff851615801590612f8c57508c6000015163ffffffff168563ffffffff1611155b15612fad57612fad858e6060015183612fa59190615a67565b8a9190613dce565b612fb78185615242565b935050600101612ec7565b50888481518110612fd557612fd5615494565b602002602001015160800151898581518110612ff357612ff3615494565b6020026020010151606001518a868151811061301157613011615494565b6020026020010151604001516130279190615242565b6130319190615242565b821461307f5760405162461bcd60e51b815260206004820152601760248201527f6e6f7420616c6c20766f746573206163636f756e7465640000000000000000006044820152606401610b98565b505050806001019050612e37565b5060005b8151811015613108578181815181106130ac576130ac615494565b60200260200101516131005760405162461bcd60e51b815260206004820152601c60248201527f616c6c20636c69656e744964206d757374206861766520766f746573000000006044820152606401610b98565b600101613091565b50600061311483613ecd565b905060005b818163ffffffff1610156131f55760006131338583613eec565b90506131428160200151613f36565b815163ffffffff16600090815260058d0160205260409020805460019061317890849061010090046001600160601b0316615561565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550806000015163ffffffff167f8a6390ffb12581558b6798514e694cb23b44ff553c82d4e69024ab1fe2230ae282602001516040516131dc91815260200190565b60405180910390a2506131ee8161566a565b9050613119565b50600389015461320e906001600160a01b03168b613f9e565b50505050505050505050505050565b60c9546001600160a01b031633146132475760405162461bcd60e51b8152600401610b98906151de565b6000613251613564565b905060006132b67f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637d9f6db56040518163ffffffff1660e01b815260040160c060405180830381865afa158015610d3e573d6000803e3d6000fd5b825464ff000000001963ffffffff8316600160281b021668ffffffffff0000000019909116176401000000001783556040519091507f8157ff66129c00501479a49058e6c0b2f966c1e797fbb240812faa57ad5b68679061332490839063ffffffff91909116815260200190565b60405180910390a15050565b600061333a613564565b54600160901b900464ffffffffff16919050565b6001600160a01b0391821660009081526101326020908152604080832093909416825291909152205460ff1690565b60c9546001600160a01b031633146133a75760405162461bcd60e51b8152600401610b98906151de565b6001600160a01b03811661340c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b98565b61149081614077565b600061341f613564565b600401546001600160a01b0316919050565b600054610100900460ff168061344a575060005460ff16155b6134665760405162461bcd60e51b8152600401610b9890615d80565b600054610100900460ff16158015613488576000805461ffff19166101011790555b6134906142a3565b6134e7604051806040016040528060128152602001712737bab7399021b634b2b73a102a37b5b2b760711b8152506040518060400160405280600b81526020016a1393d55394d0d31251539560aa1b815250614318565b60006134f1613564565b805463ffffffff19166001178155905061350a86614077565b6004810180546001600160a01b038088166001600160a01b0319928316179092556003830180548784169083161790556006909201805491851691909216179055801561355d576000805461ff00191690555b5050505050565b7f9a06af3161ac5b0c3de4e6c981ab9d9f60b530386f5eaae00d541393fbecd70090565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610bb590849061439f565b600063ffffffff82111561363f5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401610b98565b5090565b6000805b82518110156136835782818151811061366257613662615494565b602002602001015160200151826136799190615242565b9150600101613647565b50919050565b60008181526101316020526040902080546001600160a01b0319166001600160a01b03841690811790915581906136bf8261204f565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600081815261012f60205260408120546001600160a01b03166137725760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610b98565b600061377d8361204f565b9050806001600160a01b0316846001600160a01b031614806137b85750836001600160a01b03166137ad84610fa1565b6001600160a01b0316145b8061193b575061193b818561334e565b826001600160a01b03166137db8261204f565b6001600160a01b0316146138435760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610b98565b6001600160a01b0382166138a55760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610b98565b6138b0600082613689565b6001600160a01b0383166000908152610130602052604081208054600192906138da908490615481565b90915550506001600160a01b038216600090815261013060205260408120805460019290613909908490615242565b9091555050600081815261012f602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b60c9546001600160a01b031633146114905760405162461bcd60e51b8152600401610b98906151de565b60006139cd61396b565b90506139d884614471565b6000835111806139e55750815b156139f6576139f48484614516565b505b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143805460ff1661355d57805460ff191660011781556040516001600160a01b0383166024820152613a7590869060440160408051601f198184030181529190526020810180516001600160e01b0316631b2ce7f360e11b179052614516565b50805460ff19168155613a8661396b565b6001600160a01b0316826001600160a01b031614613afe5760405162461bcd60e51b815260206004820152602f60248201527f45524331393637557067726164653a207570677261646520627265616b73206660448201526e75727468657220757067726164657360881b6064820152608401610b98565b61355d85614601565b60975460ff16613b505760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610b98565b6097805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b038216613bf05760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610b98565b600081815261012f60205260409020546001600160a01b031615613c565760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610b98565b6001600160a01b038216600090815261013060205260408120805460019290613c80908490615242565b9091555050600081815261012f602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60408051606080820183528082526020820152600091810191909152613d068260016158bd565b63ffffffff166001600160401b03811115613d2357613d23614d6f565b604051908082528060200260200182016040528015613d4c578160200160208202803683370190505b508152613d5a8260026158bd565b63ffffffff166001600160401b03811115613d7757613d77614d6f565b604051908082528060200260200182016040528015613dbc57816020015b6040805180820190915260008082526020820152815260200190600190039081613d955790505b50602082015260016040820152919050565b600083600001518363ffffffff1681518110613dec57613dec615494565b602002602001015190508063ffffffff16600003613e8f5760408401805190613e148261566a565b63ffffffff1663ffffffff1681525090508084600001518463ffffffff1681518110613e4257613e42615494565b602002602001019063ffffffff16908163ffffffff16815250508284602001518263ffffffff1681518110613e7957613e79615494565b602090810291909101015163ffffffff90911690525b8184602001518263ffffffff1681518110613eac57613eac615494565b6020026020010151602001818151613ec49190615242565b90525050505050565b600060018260400151613ee09190615a4a565b63ffffffff1692915050565b60408051808201909152600080825260208201526020830151613f108360016158bd565b63ffffffff1681518110613f2657613f26615494565b6020026020010151905092915050565b60006001600160601b0382111561363f5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201526536206269747360d01b6064820152608401610b98565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015613fe5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140099190615213565b90508060000361401857505050565b600061402948642e90edd000614641565b9050600061403d3a63773594008401614641565b90506000618ca05a8603019050600061405882840286614641565b905061406e6001600160a01b0388163283613588565b50505050505050565b60c980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60975460ff16156140ec5760405162461bcd60e51b8152600401610b9890615510565b6097805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613b7d3390565b816001600160a01b0316836001600160a01b0316036141825760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610b98565b6001600160a01b0383811660008181526101326020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6141fb8484846137c8565b61420784848484614657565b61255d5760405162461bcd60e51b8152600401610b9890615dce565b80516000908183818361423857614238615494565b602002602001015190506000600190505b8281101561429857600085828151811061426557614265615494565b602002602001015190508263ffffffff168163ffffffff161161428e5750600095945050505050565b9150600101614249565b506001949350505050565b600054610100900460ff16806142bc575060005460ff16155b6142d85760405162461bcd60e51b8152600401610b9890615d80565b600054610100900460ff161580156142fa576000805461ffff19166101011790555b6097805460ff191690558015611490576000805461ff001916905550565b600054610100900460ff1680614331575060005460ff16155b61434d5760405162461bcd60e51b8152600401610b9890615d80565b600054610100900460ff1615801561436f576000805461ffff19166101011790555b614377614755565b61437f614755565b61438983836147c0565b8015610bb5576000805461ff0019169055505050565b60006143f4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166148499092919063ffffffff16565b805190915015610bb557808060200190518101906144129190615e20565b610bb55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610b98565b803b6144d55760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610b98565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060823b6145755760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610b98565b600080846001600160a01b0316846040516145909190615e3d565b600060405180830381855af49150503d80600081146145cb576040519150601f19603f3d011682016040523d82523d6000602084013e6145d0565b606091505b50915091506145f88282604051806060016040528060278152602001615f7360279139614858565b95945050505050565b61460a81614471565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6000818310614650578161275c565b5090919050565b60006001600160a01b0384163b1561474d57604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061469b903390899088908890600401615e59565b6020604051808303816000875af19250505080156146d6575060408051601f3d908101601f191682019092526146d391810190615e96565b60015b614733573d808015614704576040519150601f19603f3d011682016040523d82523d6000602084013e614709565b606091505b50805160000361472b5760405162461bcd60e51b8152600401610b9890615dce565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061193b565b50600161193b565b600054610100900460ff168061476e575060005460ff16155b61478a5760405162461bcd60e51b8152600401610b9890615d80565b600054610100900460ff161580156147ac576000805461ffff19166101011790555b8015611490576000805461ff001916905550565b600054610100900460ff16806147d9575060005460ff16155b6147f55760405162461bcd60e51b8152600401610b9890615d80565b600054610100900460ff16158015614817576000805461ffff19166101011790555b61012d6148248482615eb3565b5061012e6148328382615eb3565b508015610bb5576000805461ff0019169055505050565b606061193b8484600085614891565b6060831561486757508161275c565b8251156148775782518084602001fd5b8160405162461bcd60e51b8152600401610b989190614b4c565b6060824710156148f25760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610b98565b843b6149405760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610b98565b600080866001600160a01b0316858760405161495c9190615e3d565b60006040518083038185875af1925050503d8060008114614999576040519150601f19603f3d011682016040523d82523d6000602084013e61499e565b606091505b50915091506149ae828286614858565b979650505050505050565b604051806101000160405280600063ffffffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001614a5160405180610120016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600063ffffffff168152602001606081525090565b905290565b6001600160a01b038116811461149057600080fd5b600060208284031215614a7d57600080fd5b813561275c81614a56565b600080600060608486031215614a9d57600080fd5b8335614aa881614a56565b92506020840135614ab881614a56565b929592945050506040919091013590565b6001600160e01b03198116811461149057600080fd5b600060208284031215614af157600080fd5b813561275c81614ac9565b60005b83811015614b17578181015183820152602001614aff565b50506000910152565b60008151808452614b38816020860160208601614afc565b601f01601f19169290920160200192915050565b60208152600061275c6020830184614b20565b60008060408385031215614b7257600080fd5b50508035926020909101359150565b600060208284031215614b9357600080fd5b5035919050565b60008060408385031215614bad57600080fd5b8235614bb881614a56565b946020939093013593505050565b60006040828403121561368357600080fd5b63ffffffff8116811461149057600080fd5b6001600160601b038116811461149057600080fd5b600080600060608486031215614c1457600080fd5b8335614c1f81614bd8565b92506020840135614c2f81614a56565b91506040840135614c3f81614bea565b809150509250925092565b600060208284031215614c5c57600080fd5b813561275c81614bd8565b60008151808452602080850194506020840160005b83811015614c9e57815163ffffffff1687529582019590820190600101614c7c565b509495945050505050565b60208152600061275c6020830184614c67565b60008083601f840112614cce57600080fd5b5081356001600160401b03811115614ce557600080fd5b602083019150836020828501011115614cfd57600080fd5b9250929050565b60008060008060408587031215614d1a57600080fd5b84356001600160401b0380821115614d3157600080fd5b614d3d88838901614cbc565b90965094506020870135915080821115614d5657600080fd5b50614d6387828801614cbc565b95989497509550505050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715614da757614da7614d6f565b60405290565b604080519081016001600160401b0381118282101715614da757614da7614d6f565b60405161012081016001600160401b0381118282101715614da757614da7614d6f565b604051601f8201601f191681016001600160401b0381118282101715614e1a57614e1a614d6f565b604052919050565b60006001600160401b03821115614e3b57614e3b614d6f565b50601f01601f191660200190565b600082601f830112614e5a57600080fd5b8135614e6d614e6882614e22565b614df2565b818152846020838601011115614e8257600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215614eb257600080fd5b8235614ebd81614a56565b915060208301356001600160401b03811115614ed857600080fd5b614ee485828601614e49565b9150509250929050565b600060a0828403121561368357600080fd5b60208152815115156020820152600060208301516001600160601b038082166040850152806040860151166060850152505066ffffffffffffff6060840151166080830152608083015160c060a0840152614f5e60e0840182614b20565b905060a0840151601f198483030160c08501526145f88282614b20565b801515811461149057600080fd5b60008060408385031215614f9c57600080fd5b8235614fa781614a56565b91506020830135614fb781614f7b565b809150509250929050565b60008060408385031215614fd557600080fd5b8235614fa781614bd8565b60008060008060808587031215614ff657600080fd5b843561500181614a56565b9350602085013561501181614a56565b92506040850135915060608501356001600160401b0381111561503357600080fd5b61503f87828801614e49565b91505092959194509250565b60008060008060006060868803121561506357600080fd5b853561506e81614bd8565b945060208601356001600160401b038082111561508a57600080fd5b61509689838a01614cbc565b909650945060408801359150808211156150af57600080fd5b506150bc88828901614cbc565b969995985093965092949392505050565b6000806000604084860312156150e257600080fd5b83356150ed81614bd8565b925060208401356001600160401b038082111561510957600080fd5b818601915086601f83011261511d57600080fd5b81358181111561512c57600080fd5b8760208260051b850101111561514157600080fd5b6020830194508093505050509250925092565b6000806040838503121561516757600080fd5b823561517281614a56565b91506020830135614fb781614a56565b6000806000806080858703121561519857600080fd5b84356151a381614a56565b935060208501356151b381614a56565b925060408501356151c381614a56565b915060608501356151d381614a56565b939692955090935050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60006020828403121561522557600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610c0657610c0661522c565b805164ffffffffff8116811461526a57600080fd5b919050565b805161526a81614f7b565b600060c0828403121561528c57600080fd5b60405160c081018181106001600160401b03821117156152ae576152ae614d6f565b60405282516152bc81614bea565b815260208301516fffffffffffffffffffffffffffffffff811681146152e157600080fd5b60208201526152f260408401615255565b604082015261530360608401615255565b6060820152608083015161531681614a56565b608082015261532760a0840161526f565b60a08201529392505050565b600181811c9082168061534757607f821691505b60208210810361368357634e487b7160e01b600052602260045260246000fd5b60006001600160401b0382111561538057615380614d6f565b5060051b60200190565b805161526a81614bd8565b600060208083850312156153a857600080fd5b82516001600160401b038111156153be57600080fd5b8301601f810185136153cf57600080fd5b80516153dd614e6882615367565b81815260a091820283018401918482019190888411156153fc57600080fd5b938501935b838510156154755780858a0312156154195760008081fd5b615421614d85565b855161542c81614bd8565b8152858701518782015260408087015161544581614a56565b908201526060868101519082015260808087015161546281614bd8565b9082015283529384019391850191615401565b50979650505050505050565b81810381811115610c0657610c0661522c565b634e487b7160e01b600052603260045260246000fd5b6000813561ffff81168114610c0657600080fd5b6000813560ff81168114610c0657600080fd5b61ffff6154dd836154aa565b1681548161ffff19821617835562ff00006154fa602086016154be565b60101b168262ffffff1983161717835550505050565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6001600160601b0382811682821603908082111561555a5761555a61522c565b5092915050565b6001600160601b0381811683821601908082111561555a5761555a61522c565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b600063ffffffff8083168181036156835761568361522c565b6001019392505050565b600063ffffffff808916835280881660208401525061ffff861660408301528415156060830152831515608083015260c060a08301526156d060c0830184614c67565b98975050505050505050565b600082601f8301126156ed57600080fd5b815160206156fd614e6883615367565b82815260069290921b8401810191818101908684111561571c57600080fd5b8286015b8481101561576d57604081890312156157395760008081fd5b615741614dad565b815161574c81614bd8565b81528185015161575b81614bd8565b81860152835291830191604001615720565b509695505050505050565b6000602080838503121561578b57600080fd5b82516001600160401b03808211156157a257600080fd5b818501915085601f8301126157b657600080fd5b81516157c4614e6882615367565b81815260059190911b830184019084810190888311156157e357600080fd5b8585015b838110156158b0578051858111156157ff5760008081fd5b8601610120818c03601f19018113156158185760008081fd5b615820614dcf565b8983015181526040808401518b830152606080850151828401526080915081850151818401525060a0808501518284015260c0915081850151818401525060e08085015182840152610100915061587882860161538a565b9083015291830151918883111561588f5760008081fd5b61589d8e8c858701016156dc565b90820152855250509186019186016157e7565b5098975050505050505050565b63ffffffff81811683821601908082111561555a5761555a61522c565b6000600182016158ec576158ec61522c565b5060010190565b601f821115610bb5576000816000526020600020601f850160051c8101602086101561591c5750805b601f850160051c820191505b8181101561135957828155600101615928565b6001600160401b0383111561595257615952614d6f565b615966836159608354615333565b836158f3565b6000601f84116001811461599a57600085156159825750838201355b600019600387901b1c1916600186901b17835561355d565b600083815260209020601f19861690835b828110156159cb57868501358255602094850194600190920191016159ab565b50868210156159e85760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b604081526000615a376040830186886159fa565b82810360208401526149ae8185876159fa565b63ffffffff82811682821603908082111561555a5761555a61522c565b8082028115828204841417610c0657610c0661522c565b600082615a9b57634e487b7160e01b600052601260045260246000fd5b500490565b8135615aab81614bd8565b63ffffffff8116905081548163ffffffff19821617835564ff00000000615ad4602086016154be565b60201b16808364ffffffffff1984161717845566ffff0000000000615afb604087016154aa565b60281b168366ffffffffffffff1984161793508084831717855561ffff60381b615b27606088016154aa565b60381b1661ffff60381b1985168317821717855550505050611e15615b4e608084016154aa565b82546affff000000000000000000191660489190911b6affff00000000000000000016178255565b60008154615b8381615333565b808552602060018381168015615ba05760018114615bba57615be8565b60ff1985168884015283151560051b880183019550615be8565b866000528260002060005b85811015615be05781548a8201860152908301908401615bc5565b890184019650505b505050505092915050565b828152604060208201526000825460ff8116151560408401526001600160601b03808260081c166060850152615c3960808501828460681c166001600160601b03169052565b5060c81c60a083015260c080830152615c59610100830160018501615b76565b828103603f190160e08401526145f88160028601615b76565b600060208284031215615c8457600080fd5b81516001600160401b03811115615c9a57600080fd5b8201601f81018413615cab57600080fd5b8051615cb9614e6882614e22565b818152856020838501011115615cce57600080fd5b6145f8826020830160208601614afc565b600060c0820163ffffffff808b1684526020818b16602086015261ffff8a1660408601528815156060860152871515608086015260c060a08601528286845260e08601905087935060005b87811015615d51578435615d3d81614bd8565b841682529382019390820190600101615d2a565b509c9b505050505050505050505050565b64ffffffffff81811683821601908082111561555a5761555a61522c565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b600060208284031215615e3257600080fd5b815161275c81614f7b565b60008251615e4f818460208701614afc565b9190910192915050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615e8c90830184614b20565b9695505050505050565b600060208284031215615ea857600080fd5b815161275c81614ac9565b81516001600160401b03811115615ecc57615ecc614d6f565b615ee081615eda8454615333565b846158f3565b602080601f831160018114615f155760008415615efd5750858301515b600019600386901b1c1916600185901b178555611359565b600085815260208120601f198616915b82811015615f4457888601518255948401946001909101908401615f25565b5085821015615f625787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220176aa30f207e9025541dac9c451b5660f7d09f19c40e3df8a2a4ca9332882e4b64736f6c634300081700330000000000000000000000006f3e6272a167e8accb32072d08e0957f9c79223d000000000000000000000000830bd73e4184cef73443c15111a1df14e495c706
Deployed Bytecode
0x6080604052600436106103765760003560e01c8063704b6c02116101d1578063ac4951f611610102578063cc9df021116100a0578063ed9152c81161006f578063ed9152c814610a68578063f2fde38b14610a9c578063f851a44014610abc578063f8c8765e14610ad157600080fd5b8063cc9df021146109fe578063d0e1a84614610a1e578063d715d10114610a33578063e985e9c514610a4857600080fd5b8063bce7f0da116100dc578063bce7f0da14610994578063becbeb22146109a9578063c37bb58b146109c9578063c87b56dd146109de57600080fd5b8063ac4951f61461091c578063b289a2bb1461093c578063b88d4fde1461097457600080fd5b80638d9763231161016f57806395d89b411161014957806395d89b411461089b578063a22cb465146108b0578063a412bfbb146108d0578063a556ba311461090757600080fd5b80638d976323146108035780638da5cb5b1461081857806392c6d4201461083657600080fd5b806375794a3c116101ab57806375794a3c146107a45780637bf1a627146107b95780637d15f041146107ce5780638456cb59146107ee57600080fd5b8063704b6c021461074f57806370a082311461076f578063715018a61461078f57600080fd5b8063337344a2116102ab5780634818ac421161024957806354b1faeb1161022357806354b1faeb146106d55780635c975abb146106ea5780635f27663b146107025780636352211e1461072f57600080fd5b80634818ac42146106825780634f1ef286146106a25780634fc8d76a146106b557600080fd5b80633f4ba83a116102855780633f4ba83a146106185780633fabc2521461062d57806342842e0e146106425780634364d9731461066257600080fd5b8063337344a2146105975780633659cfe6146105cb5780633b5003c0146105eb57600080fd5b8063095ea7b31161031857806320e47641116102f257806320e476411461051857806323b872dd146105385780632a72731114610558578063303e74df1461058257600080fd5b8063095ea7b31461049657806317cb7292146104b65780631ac8875d146104d657600080fd5b80630553d778116103545780630553d778146103f257806306fdde031461040757806307d7461e14610429578063081812fc1461045e57600080fd5b806301b9a3971461037b57806301e336671461039d57806301ffc9a7146103bd575b600080fd5b34801561038757600080fd5b5061039b610396366004614a6b565b610af1565b005b3480156103a957600080fd5b5061039b6103b8366004614a88565b610b6e565b3480156103c957600080fd5b506103dd6103d8366004614adf565b610bba565b60405190151581526020015b60405180910390f35b3480156103fe57600080fd5b5061039b610c0c565b34801561041357600080fd5b5061041c610e2a565b6040516103e99190614b4c565b34801561043557600080fd5b50610449610444366004614b5f565b610ebd565b604080519283526020830191909152016103e9565b34801561046a57600080fd5b5061047e610479366004614b81565b610fa1565b6040516001600160a01b0390911681526020016103e9565b3480156104a257600080fd5b5061039b6104b1366004614b9a565b611038565b3480156104c257600080fd5b5061039b6104d1366004614bc6565b611148565b3480156104e257600080fd5b5061050a7f9a06af3161ac5b0c3de4e6c981ab9d9f60b530386f5eaae00d541393fbecd70081565b6040519081526020016103e9565b34801561052457600080fd5b5061039b610533366004614bff565b611188565b34801561054457600080fd5b5061039b610553366004614a88565b611361565b34801561056457600080fd5b5061056d611392565b60405163ffffffff90911681526020016103e9565b34801561058e57600080fd5b5061047e6113af565b3480156105a357600080fd5b5061047e7f0000000000000000000000006f3e6272a167e8accb32072d08e0957f9c79223d81565b3480156105d757600080fd5b5061039b6105e6366004614a6b565b6113cb565b3480156105f757600080fd5b5061060b610606366004614c4a565b611493565b6040516103e99190614ca9565b34801561062457600080fd5b5061039b6117c0565b34801561063957600080fd5b5061050a611817565b34801561064e57600080fd5b5061039b61065d366004614a88565b611834565b34801561066e57600080fd5b5061056d61067d366004614d04565b61184f565b34801561068e57600080fd5b5061039b61069d366004614c4a565b611943565b61039b6106b0366004614e9f565b611d60565b3480156106c157600080fd5b5061039b6106d0366004614eee565b611e19565b3480156106e157600080fd5b5061050a611e59565b3480156106f657600080fd5b5060975460ff166103dd565b34801561070e57600080fd5b5061072261071d366004614c4a565b611e76565b6040516103e99190614f00565b34801561073b57600080fd5b5061047e61074a366004614b81565b61204f565b34801561075b57600080fd5b5061039b61076a366004614a6b565b6120c7565b34801561077b57600080fd5b5061050a61078a366004614a6b565b61211e565b34801561079b57600080fd5b5061039b6121a6565b3480156107b057600080fd5b5061056d6121dc565b3480156107c557600080fd5b5061047e6121f2565b3480156107da57600080fd5b5061039b6107e9366004614a6b565b61220e565b3480156107fa57600080fd5b5061039b612265565b34801561080f57600080fd5b5061039b6122bc565b34801561082457600080fd5b5060c9546001600160a01b031661047e565b34801561084257600080fd5b5061084b612337565b60408051825163ffffffff16815260208084015160ff16908201528282015161ffff908116928201929092526060808401518316908201526080928301519091169181019190915260a0016103e9565b3480156108a757600080fd5b5061041c6123c7565b3480156108bc57600080fd5b5061039b6108cb366004614f89565b6123d7565b3480156108dc57600080fd5b506108e56123e2565b60408051825161ffff16815260209283015160ff1692810192909252016103e9565b34801561091357600080fd5b506103dd612429565b34801561092857600080fd5b5061039b610937366004614fc2565b612444565b34801561094857600080fd5b5061095c610957366004614c4a565b6124e2565b6040516001600160601b0390911681526020016103e9565b34801561098057600080fd5b5061039b61098f366004614fe0565b61252b565b3480156109a057600080fd5b5061039b612563565b3480156109b557600080fd5b5061039b6109c436600461504b565b6125dc565b3480156109d557600080fd5b506103dd6126a3565b3480156109ea57600080fd5b5061041c6109f9366004614b81565b6126bd565b348015610a0a57600080fd5b5061039b610a193660046150cd565b612763565b348015610a2a57600080fd5b5061039b61321d565b348015610a3f57600080fd5b5061050a613330565b348015610a5457600080fd5b506103dd610a63366004615154565b61334e565b348015610a7457600080fd5b5061047e7f000000000000000000000000830bd73e4184cef73443c15111a1df14e495c70681565b348015610aa857600080fd5b5061039b610ab7366004614a6b565b61337d565b348015610ac857600080fd5b5061047e613415565b348015610add57600080fd5b5061039b610aec366004615182565b613431565b6000610afb613564565b60c9549091506001600160a01b0316331480610b23575060048101546001600160a01b031633145b610b4057604051636f0cab8b60e11b815260040160405180910390fd5b81610b49613564565b60060180546001600160a01b0319166001600160a01b03929092169190911790555050565b60c9546001600160a01b03163314610ba15760405162461bcd60e51b8152600401610b98906151de565b60405180910390fd5b610bb56001600160a01b0384168383613588565b505050565b60006001600160e01b031982166380ac58cd60e01b1480610beb57506001600160e01b03198216635b5e139f60e01b145b80610c0657506301ffc9a760e01b6001600160e01b03198316145b92915050565b60c9546001600160a01b03163314610c365760405162461bcd60e51b8152600401610b98906151de565b6000610c40613564565b90506000610cd97f0000000000000000000000006f3e6272a167e8accb32072d08e0957f9c79223d6001600160a01b031663da35c6646040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ca5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc99190615213565b610cd4906001615242565b6135da565b90506000610d717f000000000000000000000000830bd73e4184cef73443c15111a1df14e495c7066001600160a01b0316637d9f6db56040518163ffffffff1660e01b815260040160c060405180830381865afa158015610d3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d62919061527a565b516001600160601b03166135da565b8354600160481b67ffffffffffffffff60501b19909116600160501b63ffffffff86811691820263ffffffff60701b191692909217600160701b9285169283021776ffffffffff0000000000000000ff0000000000000000001916600160901b4264ffffffffff160260ff60481b1916179290921786556040805192835260208301919091529192507fda1b197b06385756fea2566b6b617ea13d1b3d772596d5e7ad6651385ef7acf7910160405180910390a1505050565b606061012d8054610e3a90615333565b80601f0160208091040260200160405190810160405280929190818152602001828054610e6690615333565b8015610eb35780601f10610e8857610100808354040283529160200191610eb3565b820191906000526020600020905b815481529060010190602001808311610e9657829003601f168201915b5050505050905090565b6040516309b8570960e01b8152600481018390526024810182905260016044820152600090819081906001600160a01b037f000000000000000000000000830bd73e4184cef73443c15111a1df14e495c70616906309b8570990606401600060405180830381865afa158015610f37573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f5f9190810190615395565b9050610f6a81613643565b92508060018251610f7b9190615481565b81518110610f8b57610f8b615494565b6020026020010151606001519150509250929050565b600081815261012f60205260408120546001600160a01b031661101b5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610b98565b50600090815261013160205260409020546001600160a01b031690565b60006110438261204f565b9050806001600160a01b0316836001600160a01b0316036110b05760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610b98565b336001600160a01b03821614806110cc57506110cc813361334e565b61113e5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610b98565b610bb58383613689565b60c9546001600160a01b031633146111725760405162461bcd60e51b8152600401610b98906151de565b8061117b613564565b600201610bb582826154d1565b60975460ff16156111ab5760405162461bcd60e51b8152600401610b9890615510565b60006111b5613564565b63ffffffff85166000818152600583016020526040902091925033906111da9061204f565b6001600160a01b03161461120157604051636a45792360e11b815260040160405180910390fd5b805460ff166112415760405162461bcd60e51b815260206004820152600c60248201526b1b9bdd08185c1c1c9bdd995960a21b6044820152606401610b98565b80546001600160601b03600160681b820481169161126691839161010090041661553a565b6001600160601b0316846001600160601b031611156112ba5760405162461bcd60e51b815260206004820152601060248201526f616d6f756e7420746f6f206c6172676560801b6044820152606401610b98565b6112c48482615561565b82546bffffffffffffffffffffffff60681b1916600160681b6001600160601b03928316021783556040805191861682526001600160a01b038716602083015263ffffffff8816917f1812827f1c6a24a5651bf4de08620620edf7827369871a784625bf0ad118f120910160405180910390a26003830154611359906001600160a01b0316866001600160601b038716613588565b505050505050565b61136b33826136f8565b6113875760405162461bcd60e51b8152600401610b9890615581565b610bb58383836137c8565b600061139c613564565b54600160501b900463ffffffff16919050565b60006113b9613564565b600601546001600160a01b0316919050565b6001600160a01b037f000000000000000000000000aaf173e6b65aa4473c830edb402d26b7a33c5e941630036114135760405162461bcd60e51b8152600401610b98906155d2565b7f000000000000000000000000aaf173e6b65aa4473c830edb402d26b7a33c5e946001600160a01b031661144561396b565b6001600160a01b03161461146b5760405162461bcd60e51b8152600401610b989061561e565b61147481613999565b60408051600080825260208201909252611490918391906139c3565b50565b6060600061149f613564565b905060006114ab6121dc565b63ffffffff1690506000816001600160401b038111156114cd576114cd614d6f565b6040519080825280602002602001820160405280156114f6578160200160208202803683370190505b50905060005b828163ffffffff1610156115485780828263ffffffff168151811061152357611523615494565b63ffffffff909216602092830291909101909101526115418161566a565b90506114fc565b50825460018085015460405163aa0e23c760e01b81526000937f0000000000000000000000006f3e6272a167e8accb32072d08e0957f9c79223d6001600160a01b03169363aa0e23c7936115c193600160501b90930463ffffffff16928c92600160481b90920461ffff16919081908a9060040161568d565b600060405180830381865afa1580156115de573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116069190810190615778565b90506000836001600160401b0381111561162257611622614d6f565b60405190808252806020026020018201604052801561164b578160200160208202803683370190505b50905060005b82518110156116e15760005b858110156116d85783828151811061167757611677615494565b60200260200101516101000151818151811061169557611695615494565b6020026020010151600001518382815181106116b3576116b3615494565b602002602001018181516116c791906158bd565b63ffffffff1690525060010161165d565b50600101611651565b50600080856001600160401b038111156116fd576116fd614d6f565b604051908082528060200260200182016040528015611726578160200160208202803683370190505b50905060005b868163ffffffff1610156117b1576000848263ffffffff168151811061175457611754615494565b602002602001015163ffffffff1611156117a157808284611774816158da565b95508151811061178657611786615494565b602002602001019063ffffffff16908163ffffffff16815250505b6117aa8161566a565b905061172c565b50908152979650505050505050565b60006117ca613564565b60c9549091506001600160a01b03163314806117f2575060048101546001600160a01b031633145b61180f57604051636f0cab8b60e11b815260040160405180910390fd5b611490613b07565b6000611821613564565b54600160281b900463ffffffff16919050565b610bb58383836040518060200160405280600081525061252b565b600061185d60975460ff1690565b1561187a5760405162461bcd60e51b8152600401610b9890615510565b6000611884613564565b805490915063ffffffff1661189a8160016158bd565b825463ffffffff191663ffffffff9182161783556118bb9033908316613b9a565b63ffffffff811660009081526005830160205260409020600181016118e1888a8361593b565b50600281016118f186888361593b565b508163ffffffff167f65beab8930287623c694d7e645cdd4b7b83bebaaac913f30933d4c691a271e3c8989898960405161192e9493929190615a23565b60405180910390a2509150505b949350505050565b60975460ff16156119665760405162461bcd60e51b8152600401610b9890615510565b60005a90506000611975613564565b8054909150640100000000900460ff166119a2576040516333d63cbd60e01b815260040160405180910390fd5b80546002820154600091600160281b900463ffffffff16906119cd9062010000900460ff1682615242565b8563ffffffff1610156119f35760405163268bc0ad60e01b815260040160405180910390fd5b6119fe8560016158bd565b835463ffffffff91909116600160281b0268ffffffff00000000001990911617835560006001600160a01b037f000000000000000000000000830bd73e4184cef73443c15111a1df14e495c7061663b1296a9483611a5d8960016158bd565b6040516001600160e01b031960e085901b168152600481019290925263ffffffff16602482015260016044820152606401600060405180830381865afa158015611aab573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611ad39190810190615395565b905060008160018351611ae69190615481565b81518110611af657611af6615494565b602002602001015190508663ffffffff168160600151148015611b2357506001816000015163ffffffff16115b611b40576040516368752cd160e01b815260040160405180910390fd5b60006001611b4c6121dc565b611b569190615a4a565b90506000611b6382613cdf565b905060005b8451811015611be1576000858281518110611b8557611b85615494565b60200260200101519050806080015163ffffffff16600014158015611bba57508363ffffffff16816080015163ffffffff1611155b15611bd8576080810151602082015160019950611bd8918591613dce565b50600101611b68565b50600287015461ffff166000611bf683613ecd565b905060005b818163ffffffff161015611cf6576000611c158583613eec565b905060006127108561ffff168360200151611c309190615a67565b611c3a9190615a7e565b9050611c4581613f36565b825163ffffffff16600090815260058e01602052604090208054600190611c7b90849061010090046001600160601b0316615561565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550816000015163ffffffff167f8a6390ffb12581558b6798514e694cb23b44ff553c82d4e69024ab1fe2230ae282604051611cdb91815260200190565b60405180910390a2505080611cef9061566a565b9050611bfb565b506040805188815263ffffffff8d1660208201527ff48a534da18c3b27deb2da48e4a2d8b1888ad5cb761889d25b692de9da944d22910160405180910390a18715611d53576003890154611d53906001600160a01b03168b613f9e565b5050505050505050505050565b6001600160a01b037f000000000000000000000000aaf173e6b65aa4473c830edb402d26b7a33c5e94163003611da85760405162461bcd60e51b8152600401610b98906155d2565b7f000000000000000000000000aaf173e6b65aa4473c830edb402d26b7a33c5e946001600160a01b0316611dda61396b565b6001600160a01b031614611e005760405162461bcd60e51b8152600401610b989061561e565b611e0982613999565b611e15828260016139c3565b5050565b60c9546001600160a01b03163314611e435760405162461bcd60e51b8152600401610b98906151de565b80611e4c613564565b600101610bb58282615aa0565b6000611e63613564565b54600160701b900463ffffffff16919050565b6040805160c0810182526000808252602082018190529181018290526060808201929092526080810182905260a0810191909152611eb2613564565b63ffffffff831660009081526005919091016020908152604091829020825160c081018452815460ff81161515825261010081046001600160601b0390811694830194909452600160681b810490931693810193909352600160c81b90910466ffffffffffffff166060830152600181018054608084019190611f3490615333565b80601f0160208091040260200160405190810160405280929190818152602001828054611f6090615333565b8015611fad5780601f10611f8257610100808354040283529160200191611fad565b820191906000526020600020905b815481529060010190602001808311611f9057829003601f168201915b50505050508152602001600282018054611fc690615333565b80601f0160208091040260200160405190810160405280929190818152602001828054611ff290615333565b801561203f5780601f106120145761010080835404028352916020019161203f565b820191906000526020600020905b81548152906001019060200180831161202257829003601f168201915b5050505050815250509050919050565b600081815261012f60205260408120546001600160a01b031680610c065760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610b98565b60c9546001600160a01b031633146120f15760405162461bcd60e51b8152600401610b98906151de565b806120fa613564565b60040180546001600160a01b0319166001600160a01b039290921691909117905550565b60006001600160a01b0382166121895760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610b98565b506001600160a01b03166000908152610130602052604090205490565b60c9546001600160a01b031633146121d05760405162461bcd60e51b8152600401610b98906151de565b6121da6000614077565b565b60006121e6613564565b5463ffffffff16919050565b60006121fc613564565b600301546001600160a01b0316919050565b60c9546001600160a01b031633146122385760405162461bcd60e51b8152600401610b98906151de565b80612241613564565b60030180546001600160a01b0319166001600160a01b039290921691909117905550565b600061226f613564565b60c9549091506001600160a01b0316331480612297575060048101546001600160a01b031633145b6122b457604051636f0cab8b60e11b815260040160405180910390fd5b6114906140c9565b60c9546001600160a01b031633146122e65760405162461bcd60e51b8152600401610b98906151de565b60006122f0613564565b80549115156401000000000264ff00000000199092169190911790556040517f2b6b9a9cec683ce4fb9078fe61298719dcfeb0c26e7217bc748101cd3994367590600090a1565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261236a613564565b6040805160a0810182526001929092015463ffffffff8116835260ff640100000000820416602084015261ffff600160281b8204811692840192909252600160381b810482166060840152600160481b9004166080820152919050565b606061012e8054610e3a90615333565b611e15338383614121565b60408051808201909152600080825260208201526123fe613564565b604080518082019091526002919091015461ffff8116825262010000900460ff166020820152919050565b6000612433613564565b54640100000000900460ff16919050565b60c9546001600160a01b0316331461246e5760405162461bcd60e51b8152600401610b98906151de565b6000612478613564565b63ffffffff8416600081815260058301602052604090819020805486151560ff1990911617905551919250907f0f437477476c892b5eab47c4de7c7b038039c74ddde189b97d3315378149d7cb906124d590851515815260200190565b60405180910390a2505050565b6000806124ed613564565b63ffffffff84166000908152600582016020526040902080549192509061193b906001600160601b03600160681b820481169161010090041661553a565b61253533836136f8565b6125515760405162461bcd60e51b8152600401610b9890615581565b61255d848484846141f0565b50505050565b60c9546001600160a01b0316331461258d5760405162461bcd60e51b8152600401610b98906151de565b6000612597613564565b8054911515600160481b0260ff60481b199092169190911790556040517f59a08195999a8f63cd06ccede81a2f98993507dd88f42e1cc630e3df00a1534590600090a1565b60006125e6613564565b9050336125f863ffffffff881661204f565b6001600160a01b03161461261f57604051636a45792360e11b815260040160405180910390fd5b63ffffffff8616600090815260058201602052604090206001810161264586888361593b565b506002810161265584868361593b565b508663ffffffff167f0bee293e8de088ced65538b9072d95ce36471240b1de1e8193ab5e9391294583878787876040516126929493929190615a23565b60405180910390a250505050505050565b60006126ad613564565b54600160481b900460ff16919050565b606060006126c9613564565b600681015463ffffffff85166000908152600583016020526040908190209051635fa2601560e01b81529293506001600160a01b0390911691635fa260159161271791879190600401615bf3565b600060405180830381865afa158015612734573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261275c9190810190615c72565b9392505050565b60975460ff16156127865760405162461bcd60e51b8152600401610b9890615510565b60005a90506000612795613564565b8054909150600160481b900460ff166127c1576040516333d63cbd60e01b815260040160405180910390fd5b6127c96149b9565b60016127d36121dc565b6127dd9190615a4a565b63ffffffff908116825282546040805163368d719960e21b81529051600160501b909204909216916001600160a01b037f0000000000000000000000006f3e6272a167e8accb32072d08e0957f9c79223d169163da35c664916004808201926020929091908290030181865afa15801561285b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061287f9190615213565b8763ffffffff16111580156128a057508063ffffffff168763ffffffff1610155b6128e15760405162461bcd60e51b8152602060048201526012602482015271189859081b185cdd141c9bdc1bdcd85b125960721b6044820152606401610b98565b61291d86868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061422392505050565b6129695760405162461bcd60e51b815260206004820152601760248201527f6d75737420626520736f72746564202620756e697175650000000000000000006044820152606401610b98565b60018381015460405163aa0e23c760e01b81526000927f0000000000000000000000006f3e6272a167e8accb32072d08e0957f9c79223d6001600160a01b03169263aa0e23c7926129d49287928e92600160481b90910461ffff16919081908f908f90600401615cdf565b600060405180830381865afa1580156129f1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612a199190810190615778565b90506000815111612a6c5760405162461bcd60e51b815260206004820152601e60248201527f6174206c65617374206f6e6520656c696769626c652070726f706f73616c00006044820152606401610b98565b612a778860016158bd565b845463ffffffff91909116600160501b0263ffffffff60501b1990911617845580518190612aa790600190615481565b81518110612ab757612ab7615494565b602090810291909101015160e084018190528454600160701b900463ffffffff1660c0808601829052909101516000918291612af39190610ebd565b9092509050612b038160016158bd565b865463ffffffff91909116600160701b0263ffffffff60701b1990911617865581612b705760405162461bcd60e51b815260206004820152601a60248201527f61756374696f6e526576656e7565206d757374206265203e20300000000000006044820152606401610b98565b600186015461271090612b8e90600160281b900461ffff1684615a67565b612b989190615a7e565b6080860152600186015461271090612bbb90600160381b900461ffff1684615a67565b612bc59190615a7e565b60a086015260005b8351811015612c66576000848281518110612bea57612bea615494565b602002602001015160800151858381518110612c0857612c08615494565b602002602001015160600151868481518110612c2657612c26615494565b602002602001015160400151612c3c9190615242565b612c469190615242565b90508087602001818151612c5a9190615242565b90525050600101612bcd565b506001860154835164010000000090910460ff161115612cfb5760018601548654612ca59163ffffffff1690600160901b900464ffffffffff16615d62565b64ffffffffff168560e0015160c0015111612cfb5760405162461bcd60e51b81526020600482015260166024820152751b9bdd08195b9bdd59da081d1a5b59481c185cdcd95960521b6044820152606401610b98565b60e085015160c00151865464ffffffffff909116600160901b0264ffffffffff60901b1990911617865582516080860151612d369190615a7e565b6040860152602085015160a0860151612d4f9190615a7e565b8560600181815250507fb3719109848cd6df9b4ff39633f0b408e8595e8415ec7bc319800ab3a9dba95d848b8760c0015184868a604001518b60600151604051612dd5979695949392919063ffffffff978816815295909616602086015260408501939093526060840191909152608083015260a082015260c081019190915260e00190565b60405180910390a16000612dec8660000151613cdf565b90506000896001600160401b03811115612e0857612e08614d6f565b604051908082528060200260200182016040528015612e31578160200160208202803683370190505b50905060005b855181101561308d576000868281518110612e5457612e54615494565b602002602001015160e0015190508063ffffffff16600014158015612e895750886000015163ffffffff168163ffffffff1611155b15612ea0576040890151612ea09085908390613dce565b600080888481518110612eb557612eb5615494565b60200260200101516101000151905060005b8e811015612fc2578f8f82818110612ee157612ee1615494565b9050602002016020810190612ef69190614c4a565b93506000828281518110612f0c57612f0c615494565b60200260200101516000015163ffffffff169050868281518110612f3257612f32615494565b602002602001015180612f455750600081115b878381518110612f5757612f57615494565b9115156020928302919091019091015263ffffffff851615801590612f8c57508c6000015163ffffffff168563ffffffff1611155b15612fad57612fad858e6060015183612fa59190615a67565b8a9190613dce565b612fb78185615242565b935050600101612ec7565b50888481518110612fd557612fd5615494565b602002602001015160800151898581518110612ff357612ff3615494565b6020026020010151606001518a868151811061301157613011615494565b6020026020010151604001516130279190615242565b6130319190615242565b821461307f5760405162461bcd60e51b815260206004820152601760248201527f6e6f7420616c6c20766f746573206163636f756e7465640000000000000000006044820152606401610b98565b505050806001019050612e37565b5060005b8151811015613108578181815181106130ac576130ac615494565b60200260200101516131005760405162461bcd60e51b815260206004820152601c60248201527f616c6c20636c69656e744964206d757374206861766520766f746573000000006044820152606401610b98565b600101613091565b50600061311483613ecd565b905060005b818163ffffffff1610156131f55760006131338583613eec565b90506131428160200151613f36565b815163ffffffff16600090815260058d0160205260409020805460019061317890849061010090046001600160601b0316615561565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550806000015163ffffffff167f8a6390ffb12581558b6798514e694cb23b44ff553c82d4e69024ab1fe2230ae282602001516040516131dc91815260200190565b60405180910390a2506131ee8161566a565b9050613119565b50600389015461320e906001600160a01b03168b613f9e565b50505050505050505050505050565b60c9546001600160a01b031633146132475760405162461bcd60e51b8152600401610b98906151de565b6000613251613564565b905060006132b67f000000000000000000000000830bd73e4184cef73443c15111a1df14e495c7066001600160a01b0316637d9f6db56040518163ffffffff1660e01b815260040160c060405180830381865afa158015610d3e573d6000803e3d6000fd5b825464ff000000001963ffffffff8316600160281b021668ffffffffff0000000019909116176401000000001783556040519091507f8157ff66129c00501479a49058e6c0b2f966c1e797fbb240812faa57ad5b68679061332490839063ffffffff91909116815260200190565b60405180910390a15050565b600061333a613564565b54600160901b900464ffffffffff16919050565b6001600160a01b0391821660009081526101326020908152604080832093909416825291909152205460ff1690565b60c9546001600160a01b031633146133a75760405162461bcd60e51b8152600401610b98906151de565b6001600160a01b03811661340c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b98565b61149081614077565b600061341f613564565b600401546001600160a01b0316919050565b600054610100900460ff168061344a575060005460ff16155b6134665760405162461bcd60e51b8152600401610b9890615d80565b600054610100900460ff16158015613488576000805461ffff19166101011790555b6134906142a3565b6134e7604051806040016040528060128152602001712737bab7399021b634b2b73a102a37b5b2b760711b8152506040518060400160405280600b81526020016a1393d55394d0d31251539560aa1b815250614318565b60006134f1613564565b805463ffffffff19166001178155905061350a86614077565b6004810180546001600160a01b038088166001600160a01b0319928316179092556003830180548784169083161790556006909201805491851691909216179055801561355d576000805461ff00191690555b5050505050565b7f9a06af3161ac5b0c3de4e6c981ab9d9f60b530386f5eaae00d541393fbecd70090565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610bb590849061439f565b600063ffffffff82111561363f5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401610b98565b5090565b6000805b82518110156136835782818151811061366257613662615494565b602002602001015160200151826136799190615242565b9150600101613647565b50919050565b60008181526101316020526040902080546001600160a01b0319166001600160a01b03841690811790915581906136bf8261204f565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600081815261012f60205260408120546001600160a01b03166137725760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610b98565b600061377d8361204f565b9050806001600160a01b0316846001600160a01b031614806137b85750836001600160a01b03166137ad84610fa1565b6001600160a01b0316145b8061193b575061193b818561334e565b826001600160a01b03166137db8261204f565b6001600160a01b0316146138435760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610b98565b6001600160a01b0382166138a55760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610b98565b6138b0600082613689565b6001600160a01b0383166000908152610130602052604081208054600192906138da908490615481565b90915550506001600160a01b038216600090815261013060205260408120805460019290613909908490615242565b9091555050600081815261012f602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b60c9546001600160a01b031633146114905760405162461bcd60e51b8152600401610b98906151de565b60006139cd61396b565b90506139d884614471565b6000835111806139e55750815b156139f6576139f48484614516565b505b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143805460ff1661355d57805460ff191660011781556040516001600160a01b0383166024820152613a7590869060440160408051601f198184030181529190526020810180516001600160e01b0316631b2ce7f360e11b179052614516565b50805460ff19168155613a8661396b565b6001600160a01b0316826001600160a01b031614613afe5760405162461bcd60e51b815260206004820152602f60248201527f45524331393637557067726164653a207570677261646520627265616b73206660448201526e75727468657220757067726164657360881b6064820152608401610b98565b61355d85614601565b60975460ff16613b505760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610b98565b6097805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b038216613bf05760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610b98565b600081815261012f60205260409020546001600160a01b031615613c565760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610b98565b6001600160a01b038216600090815261013060205260408120805460019290613c80908490615242565b9091555050600081815261012f602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60408051606080820183528082526020820152600091810191909152613d068260016158bd565b63ffffffff166001600160401b03811115613d2357613d23614d6f565b604051908082528060200260200182016040528015613d4c578160200160208202803683370190505b508152613d5a8260026158bd565b63ffffffff166001600160401b03811115613d7757613d77614d6f565b604051908082528060200260200182016040528015613dbc57816020015b6040805180820190915260008082526020820152815260200190600190039081613d955790505b50602082015260016040820152919050565b600083600001518363ffffffff1681518110613dec57613dec615494565b602002602001015190508063ffffffff16600003613e8f5760408401805190613e148261566a565b63ffffffff1663ffffffff1681525090508084600001518463ffffffff1681518110613e4257613e42615494565b602002602001019063ffffffff16908163ffffffff16815250508284602001518263ffffffff1681518110613e7957613e79615494565b602090810291909101015163ffffffff90911690525b8184602001518263ffffffff1681518110613eac57613eac615494565b6020026020010151602001818151613ec49190615242565b90525050505050565b600060018260400151613ee09190615a4a565b63ffffffff1692915050565b60408051808201909152600080825260208201526020830151613f108360016158bd565b63ffffffff1681518110613f2657613f26615494565b6020026020010151905092915050565b60006001600160601b0382111561363f5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201526536206269747360d01b6064820152608401610b98565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015613fe5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140099190615213565b90508060000361401857505050565b600061402948642e90edd000614641565b9050600061403d3a63773594008401614641565b90506000618ca05a8603019050600061405882840286614641565b905061406e6001600160a01b0388163283613588565b50505050505050565b60c980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60975460ff16156140ec5760405162461bcd60e51b8152600401610b9890615510565b6097805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613b7d3390565b816001600160a01b0316836001600160a01b0316036141825760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610b98565b6001600160a01b0383811660008181526101326020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6141fb8484846137c8565b61420784848484614657565b61255d5760405162461bcd60e51b8152600401610b9890615dce565b80516000908183818361423857614238615494565b602002602001015190506000600190505b8281101561429857600085828151811061426557614265615494565b602002602001015190508263ffffffff168163ffffffff161161428e5750600095945050505050565b9150600101614249565b506001949350505050565b600054610100900460ff16806142bc575060005460ff16155b6142d85760405162461bcd60e51b8152600401610b9890615d80565b600054610100900460ff161580156142fa576000805461ffff19166101011790555b6097805460ff191690558015611490576000805461ff001916905550565b600054610100900460ff1680614331575060005460ff16155b61434d5760405162461bcd60e51b8152600401610b9890615d80565b600054610100900460ff1615801561436f576000805461ffff19166101011790555b614377614755565b61437f614755565b61438983836147c0565b8015610bb5576000805461ff0019169055505050565b60006143f4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166148499092919063ffffffff16565b805190915015610bb557808060200190518101906144129190615e20565b610bb55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610b98565b803b6144d55760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610b98565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060823b6145755760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610b98565b600080846001600160a01b0316846040516145909190615e3d565b600060405180830381855af49150503d80600081146145cb576040519150601f19603f3d011682016040523d82523d6000602084013e6145d0565b606091505b50915091506145f88282604051806060016040528060278152602001615f7360279139614858565b95945050505050565b61460a81614471565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6000818310614650578161275c565b5090919050565b60006001600160a01b0384163b1561474d57604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061469b903390899088908890600401615e59565b6020604051808303816000875af19250505080156146d6575060408051601f3d908101601f191682019092526146d391810190615e96565b60015b614733573d808015614704576040519150601f19603f3d011682016040523d82523d6000602084013e614709565b606091505b50805160000361472b5760405162461bcd60e51b8152600401610b9890615dce565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061193b565b50600161193b565b600054610100900460ff168061476e575060005460ff16155b61478a5760405162461bcd60e51b8152600401610b9890615d80565b600054610100900460ff161580156147ac576000805461ffff19166101011790555b8015611490576000805461ff001916905550565b600054610100900460ff16806147d9575060005460ff16155b6147f55760405162461bcd60e51b8152600401610b9890615d80565b600054610100900460ff16158015614817576000805461ffff19166101011790555b61012d6148248482615eb3565b5061012e6148328382615eb3565b508015610bb5576000805461ff0019169055505050565b606061193b8484600085614891565b6060831561486757508161275c565b8251156148775782518084602001fd5b8160405162461bcd60e51b8152600401610b989190614b4c565b6060824710156148f25760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610b98565b843b6149405760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610b98565b600080866001600160a01b0316858760405161495c9190615e3d565b60006040518083038185875af1925050503d8060008114614999576040519150601f19603f3d011682016040523d82523d6000602084013e61499e565b606091505b50915091506149ae828286614858565b979650505050505050565b604051806101000160405280600063ffffffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001614a5160405180610120016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600063ffffffff168152602001606081525090565b905290565b6001600160a01b038116811461149057600080fd5b600060208284031215614a7d57600080fd5b813561275c81614a56565b600080600060608486031215614a9d57600080fd5b8335614aa881614a56565b92506020840135614ab881614a56565b929592945050506040919091013590565b6001600160e01b03198116811461149057600080fd5b600060208284031215614af157600080fd5b813561275c81614ac9565b60005b83811015614b17578181015183820152602001614aff565b50506000910152565b60008151808452614b38816020860160208601614afc565b601f01601f19169290920160200192915050565b60208152600061275c6020830184614b20565b60008060408385031215614b7257600080fd5b50508035926020909101359150565b600060208284031215614b9357600080fd5b5035919050565b60008060408385031215614bad57600080fd5b8235614bb881614a56565b946020939093013593505050565b60006040828403121561368357600080fd5b63ffffffff8116811461149057600080fd5b6001600160601b038116811461149057600080fd5b600080600060608486031215614c1457600080fd5b8335614c1f81614bd8565b92506020840135614c2f81614a56565b91506040840135614c3f81614bea565b809150509250925092565b600060208284031215614c5c57600080fd5b813561275c81614bd8565b60008151808452602080850194506020840160005b83811015614c9e57815163ffffffff1687529582019590820190600101614c7c565b509495945050505050565b60208152600061275c6020830184614c67565b60008083601f840112614cce57600080fd5b5081356001600160401b03811115614ce557600080fd5b602083019150836020828501011115614cfd57600080fd5b9250929050565b60008060008060408587031215614d1a57600080fd5b84356001600160401b0380821115614d3157600080fd5b614d3d88838901614cbc565b90965094506020870135915080821115614d5657600080fd5b50614d6387828801614cbc565b95989497509550505050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715614da757614da7614d6f565b60405290565b604080519081016001600160401b0381118282101715614da757614da7614d6f565b60405161012081016001600160401b0381118282101715614da757614da7614d6f565b604051601f8201601f191681016001600160401b0381118282101715614e1a57614e1a614d6f565b604052919050565b60006001600160401b03821115614e3b57614e3b614d6f565b50601f01601f191660200190565b600082601f830112614e5a57600080fd5b8135614e6d614e6882614e22565b614df2565b818152846020838601011115614e8257600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215614eb257600080fd5b8235614ebd81614a56565b915060208301356001600160401b03811115614ed857600080fd5b614ee485828601614e49565b9150509250929050565b600060a0828403121561368357600080fd5b60208152815115156020820152600060208301516001600160601b038082166040850152806040860151166060850152505066ffffffffffffff6060840151166080830152608083015160c060a0840152614f5e60e0840182614b20565b905060a0840151601f198483030160c08501526145f88282614b20565b801515811461149057600080fd5b60008060408385031215614f9c57600080fd5b8235614fa781614a56565b91506020830135614fb781614f7b565b809150509250929050565b60008060408385031215614fd557600080fd5b8235614fa781614bd8565b60008060008060808587031215614ff657600080fd5b843561500181614a56565b9350602085013561501181614a56565b92506040850135915060608501356001600160401b0381111561503357600080fd5b61503f87828801614e49565b91505092959194509250565b60008060008060006060868803121561506357600080fd5b853561506e81614bd8565b945060208601356001600160401b038082111561508a57600080fd5b61509689838a01614cbc565b909650945060408801359150808211156150af57600080fd5b506150bc88828901614cbc565b969995985093965092949392505050565b6000806000604084860312156150e257600080fd5b83356150ed81614bd8565b925060208401356001600160401b038082111561510957600080fd5b818601915086601f83011261511d57600080fd5b81358181111561512c57600080fd5b8760208260051b850101111561514157600080fd5b6020830194508093505050509250925092565b6000806040838503121561516757600080fd5b823561517281614a56565b91506020830135614fb781614a56565b6000806000806080858703121561519857600080fd5b84356151a381614a56565b935060208501356151b381614a56565b925060408501356151c381614a56565b915060608501356151d381614a56565b939692955090935050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60006020828403121561522557600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610c0657610c0661522c565b805164ffffffffff8116811461526a57600080fd5b919050565b805161526a81614f7b565b600060c0828403121561528c57600080fd5b60405160c081018181106001600160401b03821117156152ae576152ae614d6f565b60405282516152bc81614bea565b815260208301516fffffffffffffffffffffffffffffffff811681146152e157600080fd5b60208201526152f260408401615255565b604082015261530360608401615255565b6060820152608083015161531681614a56565b608082015261532760a0840161526f565b60a08201529392505050565b600181811c9082168061534757607f821691505b60208210810361368357634e487b7160e01b600052602260045260246000fd5b60006001600160401b0382111561538057615380614d6f565b5060051b60200190565b805161526a81614bd8565b600060208083850312156153a857600080fd5b82516001600160401b038111156153be57600080fd5b8301601f810185136153cf57600080fd5b80516153dd614e6882615367565b81815260a091820283018401918482019190888411156153fc57600080fd5b938501935b838510156154755780858a0312156154195760008081fd5b615421614d85565b855161542c81614bd8565b8152858701518782015260408087015161544581614a56565b908201526060868101519082015260808087015161546281614bd8565b9082015283529384019391850191615401565b50979650505050505050565b81810381811115610c0657610c0661522c565b634e487b7160e01b600052603260045260246000fd5b6000813561ffff81168114610c0657600080fd5b6000813560ff81168114610c0657600080fd5b61ffff6154dd836154aa565b1681548161ffff19821617835562ff00006154fa602086016154be565b60101b168262ffffff1983161717835550505050565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6001600160601b0382811682821603908082111561555a5761555a61522c565b5092915050565b6001600160601b0381811683821601908082111561555a5761555a61522c565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b600063ffffffff8083168181036156835761568361522c565b6001019392505050565b600063ffffffff808916835280881660208401525061ffff861660408301528415156060830152831515608083015260c060a08301526156d060c0830184614c67565b98975050505050505050565b600082601f8301126156ed57600080fd5b815160206156fd614e6883615367565b82815260069290921b8401810191818101908684111561571c57600080fd5b8286015b8481101561576d57604081890312156157395760008081fd5b615741614dad565b815161574c81614bd8565b81528185015161575b81614bd8565b81860152835291830191604001615720565b509695505050505050565b6000602080838503121561578b57600080fd5b82516001600160401b03808211156157a257600080fd5b818501915085601f8301126157b657600080fd5b81516157c4614e6882615367565b81815260059190911b830184019084810190888311156157e357600080fd5b8585015b838110156158b0578051858111156157ff5760008081fd5b8601610120818c03601f19018113156158185760008081fd5b615820614dcf565b8983015181526040808401518b830152606080850151828401526080915081850151818401525060a0808501518284015260c0915081850151818401525060e08085015182840152610100915061587882860161538a565b9083015291830151918883111561588f5760008081fd5b61589d8e8c858701016156dc565b90820152855250509186019186016157e7565b5098975050505050505050565b63ffffffff81811683821601908082111561555a5761555a61522c565b6000600182016158ec576158ec61522c565b5060010190565b601f821115610bb5576000816000526020600020601f850160051c8101602086101561591c5750805b601f850160051c820191505b8181101561135957828155600101615928565b6001600160401b0383111561595257615952614d6f565b615966836159608354615333565b836158f3565b6000601f84116001811461599a57600085156159825750838201355b600019600387901b1c1916600186901b17835561355d565b600083815260209020601f19861690835b828110156159cb57868501358255602094850194600190920191016159ab565b50868210156159e85760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b604081526000615a376040830186886159fa565b82810360208401526149ae8185876159fa565b63ffffffff82811682821603908082111561555a5761555a61522c565b8082028115828204841417610c0657610c0661522c565b600082615a9b57634e487b7160e01b600052601260045260246000fd5b500490565b8135615aab81614bd8565b63ffffffff8116905081548163ffffffff19821617835564ff00000000615ad4602086016154be565b60201b16808364ffffffffff1984161717845566ffff0000000000615afb604087016154aa565b60281b168366ffffffffffffff1984161793508084831717855561ffff60381b615b27606088016154aa565b60381b1661ffff60381b1985168317821717855550505050611e15615b4e608084016154aa565b82546affff000000000000000000191660489190911b6affff00000000000000000016178255565b60008154615b8381615333565b808552602060018381168015615ba05760018114615bba57615be8565b60ff1985168884015283151560051b880183019550615be8565b866000528260002060005b85811015615be05781548a8201860152908301908401615bc5565b890184019650505b505050505092915050565b828152604060208201526000825460ff8116151560408401526001600160601b03808260081c166060850152615c3960808501828460681c166001600160601b03169052565b5060c81c60a083015260c080830152615c59610100830160018501615b76565b828103603f190160e08401526145f88160028601615b76565b600060208284031215615c8457600080fd5b81516001600160401b03811115615c9a57600080fd5b8201601f81018413615cab57600080fd5b8051615cb9614e6882614e22565b818152856020838501011115615cce57600080fd5b6145f8826020830160208601614afc565b600060c0820163ffffffff808b1684526020818b16602086015261ffff8a1660408601528815156060860152871515608086015260c060a08601528286845260e08601905087935060005b87811015615d51578435615d3d81614bd8565b841682529382019390820190600101615d2a565b509c9b505050505050505050505050565b64ffffffffff81811683821601908082111561555a5761555a61522c565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b600060208284031215615e3257600080fd5b815161275c81614f7b565b60008251615e4f818460208701614afc565b9190910192915050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615e8c90830184614b20565b9695505050505050565b600060208284031215615ea857600080fd5b815161275c81614ac9565b81516001600160401b03811115615ecc57615ecc614d6f565b615ee081615eda8454615333565b846158f3565b602080601f831160018114615f155760008415615efd5750858301515b600019600386901b1c1916600185901b178555611359565b600085815260208120601f198616915b82811015615f4457888601518255948401946001909101908401615f25565b5085821015615f625787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220176aa30f207e9025541dac9c451b5660f7d09f19c40e3df8a2a4ca9332882e4b64736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006f3e6272a167e8accb32072d08e0957f9c79223d000000000000000000000000830bd73e4184cef73443c15111a1df14e495c706
-----Decoded View---------------
Arg [0] : nounsDAO_ (address): 0x6f3E6272A167e8AcCb32072d08E0957F9c79223d
Arg [1] : auctionHouse_ (address): 0x830BD73E4184ceF73443C15111a1DF14e495C706
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000006f3e6272a167e8accb32072d08e0957f9c79223d
Arg [1] : 000000000000000000000000830bd73e4184cef73443c15111a1df14e495c706
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.