Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
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:
Party
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
import "../tokens/IERC721.sol";
import "./PartyGovernanceNFT.sol";
import "./PartyGovernance.sol";
/// @notice The governance contract that also custodies the precious NFTs. This
/// is also the Governance NFT 721 contract.
contract Party is PartyGovernanceNFT {
// Arguments used to initialize the party.
struct PartyOptions {
PartyGovernance.GovernanceOpts governance;
string name;
string symbol;
uint256 customizationPresetId;
}
// Arguments used to initialize the `PartyGovernanceNFT`.
struct PartyInitData {
PartyOptions options;
IERC721[] preciousTokens;
uint256[] preciousTokenIds;
address mintAuthority;
}
// Set the `Globals` contract.
constructor(IGlobals globals) PartyGovernanceNFT(globals) {}
/// @notice Initializer to be delegatecalled by `Proxy` constructor. Will
/// revert if called outside the constructor.
/// @param initData Options used to initialize the party governance.
function initialize(PartyInitData memory initData)
external
onlyConstructor
{
PartyGovernanceNFT._initialize(
initData.options.name,
initData.options.symbol,
initData.options.customizationPresetId,
initData.options.governance,
initData.preciousTokens,
initData.preciousTokenIds,
initData.mintAuthority
);
}
receive() external payable {}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
import "../tokens/IERC20.sol";
import "./ITokenDistributorParty.sol";
/// @notice Creates token distributions for parties.
interface ITokenDistributor {
enum TokenType {
Native,
Erc20
}
// Info on a distribution, created by createDistribution().
struct DistributionInfo {
// Type of distribution/token.
TokenType tokenType;
// ID of the distribution. Assigned by createDistribution().
uint256 distributionId;
// The party whose members can claim the distribution.
ITokenDistributorParty party;
// Who can claim `fee`.
address payable feeRecipient;
// The token being distributed.
address token;
// Total amount of `token` that can be claimed by party members.
uint128 memberSupply;
// Amount of `token` to be redeemed by `feeRecipient`.
uint128 fee;
}
event DistributionCreated(
ITokenDistributorParty indexed party,
DistributionInfo info
);
event DistributionFeeClaimed(
ITokenDistributorParty indexed party,
address indexed feeRecipient,
TokenType tokenType,
address token,
uint256 amount
);
event DistributionClaimedByPartyToken(
ITokenDistributorParty indexed party,
uint256 indexed partyTokenId,
address indexed owner,
TokenType tokenType,
address token,
uint256 amountClaimed
);
/// @notice Create a new distribution for an outstanding native token balance
/// governed by a party.
/// @dev Native tokens should be transferred directly into this contract
/// immediately prior (same tx) to calling `createDistribution()` or
/// attached to the call itself.
/// @param party The party whose members can claim the distribution.
/// @param feeRecipient Who can claim `fee`.
/// @param feeBps Percentage (in bps) of the distribution `feeRecipient` receives.
/// @return info Information on the created distribution.
function createNativeDistribution(
ITokenDistributorParty party,
address payable feeRecipient,
uint16 feeBps
)
external
payable
returns (DistributionInfo memory info);
/// @notice Create a new distribution for an outstanding ERC20 token balance
/// governed by a party.
/// @dev ERC20 tokens should be transferred directly into this contract
/// immediately prior (same tx) to calling `createDistribution()` or
/// attached to the call itself.
/// @param token The ERC20 token to distribute.
/// @param party The party whose members can claim the distribution.
/// @param feeRecipient Who can claim `fee`.
/// @param feeBps Percentage (in bps) of the distribution `feeRecipient` receives.
/// @return info Information on the created distribution.
function createErc20Distribution(
IERC20 token,
ITokenDistributorParty party,
address payable feeRecipient,
uint16 feeBps
)
external
returns (DistributionInfo memory info);
/// @notice Claim a portion of a distribution owed to a `partyTokenId` belonging
/// to the party that created the distribution. The caller
/// must own this token.
/// @param info Information on the distribution being claimed.
/// @param partyTokenId The ID of the party token to claim for.
/// @return amountClaimed The amount of the distribution claimed.
function claim(DistributionInfo calldata info, uint256 partyTokenId)
external
returns (uint128 amountClaimed);
/// @notice Claim the fee for a distribution. Only a distribution's `feeRecipient`
/// can call this.
/// @param info Information on the distribution being claimed.
/// @param recipient The address to send the fee to.
function claimFee(DistributionInfo calldata info, address payable recipient)
external;
/// @notice Batch version of `claim()`.
/// @param infos Information on the distributions being claimed.
/// @param partyTokenIds The ID of the party tokens to claim for.
/// @return amountsClaimed The amount of the distributions claimed.
function batchClaim(DistributionInfo[] calldata infos, uint256[] calldata partyTokenIds)
external
returns (uint128[] memory amountsClaimed);
/// @notice Batch version of `claimFee()`.
/// @param infos Information on the distributions to claim fees for.
/// @param recipients The addresses to send the fees to.
function batchClaimFee(DistributionInfo[] calldata infos, address payable[] calldata recipients)
external;
/// @notice Compute the amount of a distribution's token are owed to a party
/// member, identified by the `partyTokenId`.
/// @param party The party to use for computing the claim amount.
/// @param memberSupply Total amount of tokens that can be claimed in the distribution.
/// @param partyTokenId The ID of the party token to claim for.
/// @return claimAmount The amount of the distribution owed to the party member.
function getClaimAmount(
ITokenDistributorParty party,
uint256 memberSupply,
uint256 partyTokenId
)
external
view
returns (uint128);
/// @notice Check whether the fee has been claimed for a distribution.
/// @param party The party to use for checking whether the fee has been claimed.
/// @param distributionId The ID of the distribution to check.
/// @return feeClaimed Whether the fee has been claimed.
function wasFeeClaimed(ITokenDistributorParty party, uint256 distributionId)
external
view
returns (bool);
/// @notice Check whether a `partyTokenId` has claimed their share of a distribution.
/// @param party The party to use for checking whether the `partyTokenId` has claimed.
/// @param partyTokenId The ID of the party token to check.
/// @param distributionId The ID of the distribution to check.
/// @return hasClaimed Whether the `partyTokenId` has claimed.
function hasPartyTokenIdClaimed(
ITokenDistributorParty party,
uint256 partyTokenId,
uint256 distributionId
)
external
view returns (bool);
/// @notice Get how much unclaimed member tokens are left in a distribution.
/// @param party The party to use for checking the unclaimed member tokens.
/// @param distributionId The ID of the distribution to check.
/// @return remainingMemberSupply The amount of distribution supply remaining.
function getRemainingMemberSupply(
ITokenDistributorParty party,
uint256 distributionId
)
external
view
returns (uint128);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
// Interface the caller of `ITokenDistributor.createDistribution()` must implement.
interface ITokenDistributorParty {
/// @notice Return the owner of a token.
/// @param tokenId The token ID to query.
/// @return owner The owner of `tokenId`.
function ownerOf(uint256 tokenId) external view returns (address);
/// @notice Return the distribution share of a token. Denominated fractions
/// of 1e18. I.e., 1e18 = 100%.
/// @param tokenId The token ID to query.
/// @return share The distribution percentage of `tokenId`.
function getDistributionShareOf(uint256 tokenId) external view returns (uint256);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
import "../utils/Implementation.sol";
// Single registry of global values controlled by multisig.
// See `LibGlobals` for all valid keys.
interface IGlobals {
function getBytes32(uint256 key) external view returns (bytes32);
function getUint256(uint256 key) external view returns (uint256);
function getBool(uint256 key) external view returns (bool);
function getAddress(uint256 key) external view returns (address);
function getImplementation(uint256 key) external view returns (Implementation);
function getIncludesBytes32(uint256 key, bytes32 value) external view returns (bool);
function getIncludesUint256(uint256 key, uint256 value) external view returns (bool);
function getIncludesAddress(uint256 key, address value) external view returns (bool);
function setBytes32(uint256 key, bytes32 value) external;
function setUint256(uint256 key, uint256 value) external;
function setBool(uint256 key, bool value) external;
function setAddress(uint256 key, address value) external;
function setIncludesBytes32(uint256 key, bytes32 value, bool isIncluded) external;
function setIncludesUint256(uint256 key, uint256 value, bool isIncluded) external;
function setIncludesAddress(uint256 key, address value, bool isIncluded) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
// Valid keys in `IGlobals`. Append-only.
library LibGlobals {
uint256 internal constant GLOBAL_PARTY_IMPL = 1;
uint256 internal constant GLOBAL_PROPOSAL_ENGINE_IMPL = 2;
uint256 internal constant GLOBAL_PARTY_FACTORY = 3;
uint256 internal constant GLOBAL_GOVERNANCE_NFT_RENDER_IMPL = 4;
uint256 internal constant GLOBAL_CF_NFT_RENDER_IMPL = 5;
uint256 internal constant GLOBAL_OS_ZORA_AUCTION_TIMEOUT = 6;
uint256 internal constant GLOBAL_OS_ZORA_AUCTION_DURATION = 7;
uint256 internal constant GLOBAL_AUCTION_CF_IMPL = 8;
uint256 internal constant GLOBAL_BUY_CF_IMPL = 9;
uint256 internal constant GLOBAL_COLLECTION_BUY_CF_IMPL = 10;
uint256 internal constant GLOBAL_DAO_WALLET = 11;
uint256 internal constant GLOBAL_TOKEN_DISTRIBUTOR = 12;
uint256 internal constant GLOBAL_OPENSEA_CONDUIT_KEY = 13;
uint256 internal constant GLOBAL_OPENSEA_ZONE = 14;
uint256 internal constant GLOBAL_PROPOSAL_MAX_CANCEL_DURATION = 15;
uint256 internal constant GLOBAL_ZORA_MIN_AUCTION_DURATION = 16;
uint256 internal constant GLOBAL_ZORA_MAX_AUCTION_DURATION = 17;
uint256 internal constant GLOBAL_ZORA_MAX_AUCTION_TIMEOUT = 18;
uint256 internal constant GLOBAL_OS_MIN_ORDER_DURATION = 19;
uint256 internal constant GLOBAL_OS_MAX_ORDER_DURATION = 20;
uint256 internal constant GLOBAL_DISABLE_PARTY_ACTIONS = 21;
uint256 internal constant GLOBAL_RENDERER_STORAGE = 22;
uint256 internal constant GLOBAL_PROPOSAL_MIN_CANCEL_DURATION = 23;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
import "../globals/IGlobals.sol";
import "../tokens/IERC721.sol";
import "./Party.sol";
// Creates generic Party instances.
interface IPartyFactory {
event PartyCreated(
Party indexed party,
Party.PartyOptions opts,
IERC721[] preciousTokens,
uint256[] preciousTokenIds,
address creator
);
/// @notice Deploy a new party instance. Afterwards, governance NFTs can be minted
/// for party members using the `mint()` function from the newly
/// created party.
/// @param authority The address that can call `mint()`.
/// @param opts Options used to initialize the party. These are fixed
/// and cannot be changed later.
/// @param preciousTokens The tokens that are considered precious by the
/// party.These are protected assets and are subject
/// to extra restrictions in proposals vs other
/// assets.
/// @param preciousTokenIds The IDs associated with each token in `preciousTokens`.
/// @return party The newly created `Party` instance.
function createParty(
address authority,
Party.PartyOptions calldata opts,
IERC721[] memory preciousTokens,
uint256[] memory preciousTokenIds
)
external
returns (Party party);
/// @notice The `Globals` contract storing global configuration values. This contract
/// is immutable and it’s address will never change.
function GLOBALS() external view returns (IGlobals);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
import "../distribution/ITokenDistributorParty.sol";
import "../distribution/ITokenDistributor.sol";
import "../utils/ReadOnlyDelegateCall.sol";
import "../tokens/IERC721.sol";
import "../tokens/IERC20.sol";
import "../tokens/IERC1155.sol";
import "../tokens/ERC721Receiver.sol";
import "../tokens/ERC1155Receiver.sol";
import "../utils/LibERC20Compat.sol";
import "../utils/LibRawResult.sol";
import "../utils/LibSafeCast.sol";
import "../globals/IGlobals.sol";
import "../globals/LibGlobals.sol";
import "../proposals/IProposalExecutionEngine.sol";
import "../proposals/LibProposal.sol";
import "../proposals/ProposalStorage.sol";
import "./IPartyFactory.sol";
/// @notice Base contract for a Party encapsulating all governance functionality.
abstract contract PartyGovernance is
ITokenDistributorParty,
ERC721Receiver,
ERC1155Receiver,
ProposalStorage,
Implementation,
ReadOnlyDelegateCall
{
using LibERC20Compat for IERC20;
using LibRawResult for bytes;
using LibSafeCast for uint256;
using LibSafeCast for int192;
using LibSafeCast for uint96;
// States a proposal can be in.
enum ProposalStatus {
// The proposal does not exist.
Invalid,
// The proposal has been proposed (via `propose()`), has not been vetoed
// by a party host, and is within the voting window. Members can vote on
// the proposal and party hosts can veto the proposal.
Voting,
// The proposal has either exceeded its voting window without reaching
// `passThresholdBps` of votes or was vetoed by a party host.
Defeated,
// The proposal reached at least `passThresholdBps` of votes but is still
// waiting for `executionDelay` to pass before it can be executed. Members
// can continue to vote on the proposal and party hosts can veto at this time.
Passed,
// Same as `Passed` but now `executionDelay` has been satisfied. Any member
// may execute the proposal via `execute()`, unless `maxExecutableTime`
// has arrived.
Ready,
// The proposal has been executed at least once but has further steps to
// complete so it needs to be executed again. No other proposals may be
// executed while a proposal is in the `InProgress` state. No voting or
// vetoing of the proposal is allowed, however it may be forcibly cancelled
// via `cancel()` if the `cancelDelay` has passed since being first executed.
InProgress,
// The proposal was executed and completed all its steps. No voting or
// vetoing can occur and it cannot be cancelled nor executed again.
Complete,
// The proposal was executed at least once but did not complete before
// `cancelDelay` seconds passed since the first execute and was forcibly cancelled.
Cancelled
}
struct GovernanceOpts {
// Address of initial party hosts.
address[] hosts;
// How long people can vote on a proposal.
uint40 voteDuration;
// How long to wait after a proposal passes before it can be
// executed.
uint40 executionDelay;
// Minimum ratio of accept votes to consider a proposal passed,
// in bps, where 10,000 == 100%.
uint16 passThresholdBps;
// Total voting power of governance NFTs.
uint96 totalVotingPower;
// Fee bps for distributions.
uint16 feeBps;
// Fee recipeint for distributions.
address payable feeRecipient;
}
// Subset of `GovernanceOpts` that are commonly read together for
// efficiency.
struct GovernanceValues {
uint40 voteDuration;
uint40 executionDelay;
uint16 passThresholdBps;
uint96 totalVotingPower;
}
// A snapshot of voting power for a member.
struct VotingPowerSnapshot {
// The timestamp when the snapshot was taken.
uint40 timestamp;
// Voting power that was delegated to this user by others.
uint96 delegatedVotingPower;
// The intrinsic (not delegated from someone else) voting power of this user.
uint96 intrinsicVotingPower;
// Whether the user was delegated to another at this snapshot.
bool isDelegated;
}
// Proposal details chosen by proposer.
struct Proposal {
// Time beyond which the proposal can no longer be executed.
// If the proposal has already been executed, and is still InProgress,
// this value is ignored.
uint40 maxExecutableTime;
// The minimum seconds this proposal can remain in the InProgress status
// before it can be cancelled.
uint40 cancelDelay;
// Encoded proposal data. The first 4 bytes are the proposal type, followed
// by encoded proposal args specific to the proposal type. See
// ProposalExecutionEngine for details.
bytes proposalData;
}
// Accounting and state tracking values for a proposal.
// Fits in a word.
struct ProposalStateValues {
// When the proposal was proposed.
uint40 proposedTime;
// When the proposal passed the vote.
uint40 passedTime;
// When the proposal was first executed.
uint40 executedTime;
// When the proposal completed.
uint40 completedTime;
// Number of accept votes.
uint96 votes; // -1 == vetoed
}
// Storage states for a proposal.
struct ProposalState {
// Accounting and state tracking values.
ProposalStateValues values;
// Hash of the proposal.
bytes32 hash;
// Whether a member has voted for (accepted) this proposal already.
mapping (address => bool) hasVoted;
}
event Proposed(
uint256 proposalId,
address proposer,
Proposal proposal
);
event ProposalAccepted(
uint256 proposalId,
address voter,
uint256 weight
);
event EmergencyExecute(address target, bytes data, uint256 amountEth);
event ProposalPassed(uint256 indexed proposalId);
event ProposalVetoed(uint256 indexed proposalId, address host);
event ProposalExecuted(uint256 indexed proposalId, address executor, bytes nextProgressData);
event ProposalCancelled(uint256 indexed proposalId);
event DistributionCreated(ITokenDistributor.TokenType tokenType, address token, uint256 tokenId);
event VotingPowerDelegated(address indexed owner, address indexed delegate);
event HostStatusTransferred(address oldHost, address newHost);
event EmergencyExecuteDisabled();
error MismatchedPreciousListLengths();
error BadProposalStatusError(ProposalStatus status);
error BadProposalHashError(bytes32 proposalHash, bytes32 actualHash);
error ExecutionTimeExceededError(uint40 maxExecutableTime, uint40 timestamp);
error OnlyPartyHostError();
error OnlyActiveMemberError();
error InvalidDelegateError();
error BadPreciousListError();
error OnlyPartyDaoError(address notDao, address partyDao);
error OnlyPartyDaoOrHostError(address notDao, address partyDao);
error OnlyWhenEmergencyActionsAllowedError();
error OnlyWhenEnabledError();
error AlreadyVotedError(address voter);
error InvalidNewHostError();
error ProposalCannotBeCancelledYetError(uint40 currentTime, uint40 cancelTime);
error InvalidBpsError(uint16 bps);
uint256 constant private UINT40_HIGH_BIT = 1 << 39;
uint96 constant private VETO_VALUE = type(uint96).max;
// The `Globals` contract storing global configuration values. This contract
// is immutable and it’s address will never change.
IGlobals private immutable _GLOBALS;
/// @notice Whether the DAO has emergency powers for this party.
bool public emergencyExecuteDisabled;
/// @notice Distribution fee bps.
uint16 public feeBps;
/// @notice Distribution fee recipient.
address payable public feeRecipient;
/// @notice The hash of the list of precious NFTs guarded by the party.
bytes32 public preciousListHash;
/// @notice The last proposal ID that was used. 0 means no proposals have been made.
uint256 public lastProposalId;
/// @notice Whether an address is a party host.
mapping(address => bool) public isHost;
/// @notice The last person a voter delegated its voting power to.
mapping(address => address) public delegationsByVoter;
// Constant governance parameters, fixed from the inception of this party.
GovernanceValues internal _governanceValues;
// ProposalState by proposal ID.
mapping(uint256 => ProposalState) private _proposalStateByProposalId;
// Snapshots of voting power per user, each sorted by increasing time.
mapping(address => VotingPowerSnapshot[]) private _votingPowerSnapshotsByVoter;
modifier onlyHost() {
if (!isHost[msg.sender]) {
revert OnlyPartyHostError();
}
_;
}
// Caller must have voting power at the current time.
modifier onlyActiveMember() {
{
VotingPowerSnapshot memory snap =
_getLastVotingPowerSnapshotForVoter(msg.sender);
// Must have either delegated voting power or intrinsic voting power.
if (snap.intrinsicVotingPower == 0 && snap.delegatedVotingPower == 0) {
revert OnlyActiveMemberError();
}
}
_;
}
// Caller must have voting power at the current time or be the `Party` instance.
modifier onlyActiveMemberOrSelf() {
// Ignore if the party is calling functions on itself, like with
// `FractionalizeProposal` calling `distribute()`.
if (msg.sender != address(this)) {
VotingPowerSnapshot memory snap =
_getLastVotingPowerSnapshotForVoter(msg.sender);
// Must have either delegated voting power or intrinsic voting power.
if (snap.intrinsicVotingPower == 0 && snap.delegatedVotingPower == 0) {
revert OnlyActiveMemberError();
}
}
_;
}
// Only the party DAO multisig can call.
modifier onlyPartyDao() {
{
address partyDao = _GLOBALS.getAddress(LibGlobals.GLOBAL_DAO_WALLET);
if (msg.sender != partyDao) {
revert OnlyPartyDaoError(msg.sender, partyDao);
}
}
_;
}
// Only the party DAO multisig or a party host can call.
modifier onlyPartyDaoOrHost() {
address partyDao = _GLOBALS.getAddress(LibGlobals.GLOBAL_DAO_WALLET);
if (msg.sender != partyDao && !isHost[msg.sender]) {
revert OnlyPartyDaoOrHostError(msg.sender, partyDao);
}
_;
}
// Only if `emergencyExecuteDisabled` is not true.
modifier onlyWhenEmergencyExecuteAllowed() {
if (emergencyExecuteDisabled) {
revert OnlyWhenEmergencyActionsAllowedError();
}
_;
}
modifier onlyWhenNotGloballyDisabled() {
if (_GLOBALS.getBool(LibGlobals.GLOBAL_DISABLE_PARTY_ACTIONS)) {
revert OnlyWhenEnabledError();
}
_;
}
// Set the `Globals` contract.
constructor(IGlobals globals) {
_GLOBALS = globals;
}
// Initialize storage for proxy contracts and initialize the proposal execution engine.
function _initialize(
GovernanceOpts memory opts,
IERC721[] memory preciousTokens,
uint256[] memory preciousTokenIds
)
internal
virtual
{
// Check BPS are valid.
if (opts.feeBps > 1e4) {
revert InvalidBpsError(opts.feeBps);
}
if (opts.passThresholdBps > 1e4) {
revert InvalidBpsError(opts.passThresholdBps);
}
// Initialize the proposal execution engine.
_initProposalImpl(
IProposalExecutionEngine(
_GLOBALS.getAddress(LibGlobals.GLOBAL_PROPOSAL_ENGINE_IMPL)
),
""
);
// Set the governance parameters.
_governanceValues = GovernanceValues({
voteDuration: opts.voteDuration,
executionDelay: opts.executionDelay,
passThresholdBps: opts.passThresholdBps,
totalVotingPower: opts.totalVotingPower
});
// Set fees.
feeBps = opts.feeBps;
feeRecipient = opts.feeRecipient;
// Set the precious list.
_setPreciousList(preciousTokens, preciousTokenIds);
// Set the party hosts.
for (uint256 i=0; i < opts.hosts.length; ++i) {
isHost[opts.hosts[i]] = true;
}
}
/// @dev Forward all unknown read-only calls to the proposal execution engine.
/// Initial use case is to facilitate eip-1271 signatures.
fallback() external {
_readOnlyDelegateCall(
address(_getProposalExecutionEngine()),
msg.data
);
}
/// @inheritdoc EIP165
/// @dev Combined logic for `ERC721Receiver` and `ERC1155Receiver`.
function supportsInterface(bytes4 interfaceId)
public
override(ERC721Receiver, ERC1155Receiver)
virtual
pure
returns (bool)
{
return ERC721Receiver.supportsInterface(interfaceId) ||
ERC1155Receiver.supportsInterface(interfaceId);
}
/// @notice Get the current `ProposalExecutionEngine` instance.
function getProposalExecutionEngine()
external
view
returns (IProposalExecutionEngine)
{
return _getProposalExecutionEngine();
}
/// @notice Get the total voting power of `voter` at a `timestamp`.
/// @param voter The address of the voter.
/// @param timestamp The timestamp to get the voting power at.
/// @return votingPower The total voting power of `voter` at `timestamp`.
function getVotingPowerAt(address voter, uint40 timestamp)
external
view
returns (uint96 votingPower)
{
return getVotingPowerAt(voter, timestamp, type(uint256).max);
}
/// @notice Get the total voting power of `voter` at a snapshot `snapIndex`, with checks to
/// make sure it is the latest voting snapshot =< `timestamp`.
/// @param voter The address of the voter.
/// @param timestamp The timestamp to get the voting power at.
/// @param snapIndex The index of the snapshot to get the voting power at.
/// @return votingPower The total voting power of `voter` at `timestamp`.
function getVotingPowerAt(address voter, uint40 timestamp, uint256 snapIndex)
public
view
returns (uint96 votingPower)
{
VotingPowerSnapshot memory snap = _getVotingPowerSnapshotAt(voter, timestamp, snapIndex);
return (snap.isDelegated ? 0 : snap.intrinsicVotingPower) + snap.delegatedVotingPower;
}
/// @notice Get the state of a proposal.
/// @param proposalId The ID of the proposal.
/// @return status The status of the proposal.
/// @return values The state of the proposal.
function getProposalStateInfo(uint256 proposalId)
external
view
returns (ProposalStatus status, ProposalStateValues memory values)
{
values = _proposalStateByProposalId[proposalId].values;
status = _getProposalStatus(values);
}
/// @notice Retrieve fixed governance parameters.
/// @return gv The governance parameters of this party.
function getGovernanceValues() external view returns (GovernanceValues memory gv) {
return _governanceValues;
}
/// @notice Get the hash of a proposal.
/// @dev Proposal details are not stored on-chain so the hash is used to enforce
/// consistency between calls.
/// @param proposal The proposal to hash.
/// @return proposalHash The hash of the proposal.
function getProposalHash(Proposal memory proposal)
public
pure
returns (bytes32 proposalHash)
{
// Hash the proposal in-place. Equivalent to:
// keccak256(abi.encode(
// proposal.maxExecutableTime,
// proposal.cancelDelay,
// keccak256(proposal.proposalData)
// ))
bytes32 dataHash = keccak256(proposal.proposalData);
assembly {
// Overwrite the data field with the hash of its contents and then
// hash the struct.
let dataPos := add(proposal, 0x40)
let t := mload(dataPos)
mstore(dataPos, dataHash)
proposalHash := keccak256(proposal, 0x60)
// Restore the data field.
mstore(dataPos, t)
}
}
/// @notice Get the index of the most recent voting power snapshot <= `timestamp`.
/// @param voter The address of the voter.
/// @param timestamp The timestamp to get the snapshot index at.
/// @return index The index of the snapshot.
function findVotingPowerSnapshotIndex(address voter, uint40 timestamp)
public
view
returns (uint256 index)
{
VotingPowerSnapshot[] storage snaps = _votingPowerSnapshotsByVoter[voter];
// Derived from Open Zeppelin binary search
// ref: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Checkpoints.sol#L39
uint256 high = snaps.length;
uint256 low = 0;
while (low < high) {
uint256 mid = (low + high) / 2;
if (snaps[mid].timestamp > timestamp) {
// Entry is too recent.
high = mid;
} else {
// Entry is older. This is our best guess for now.
low = mid + 1;
}
}
// Return `type(uint256).max` if no valid voting snapshots found.
return high == 0 ? type(uint256).max : high - 1;
}
/// @notice Pledge your intrinsic voting power to a new delegate, removing it from
/// the old one (if any).
/// @param delegate The address to delegating voting power to.
function delegateVotingPower(address delegate) external onlyDelegateCall {
_adjustVotingPower(msg.sender, 0, delegate);
emit VotingPowerDelegated(msg.sender, delegate);
}
/// @notice Transfer party host status to another.
/// @param newPartyHost The address of the new host.
function abdicate(address newPartyHost) external onlyHost onlyDelegateCall {
// 0 is a special case burn address.
if (newPartyHost != address(0)) {
// Cannot transfer host status to an existing host.
if(isHost[newPartyHost]) {
revert InvalidNewHostError();
}
isHost[newPartyHost] = true;
}
isHost[msg.sender] = false;
emit HostStatusTransferred(msg.sender, newPartyHost);
}
/// @notice Create a token distribution by moving the party's entire balance
/// to the `TokenDistributor` contract and immediately creating a
/// distribution governed by this party.
/// @dev The `feeBps` and `feeRecipient` this party was created with will be
/// propagated to the distribution. Party members are entitled to a
/// share of the distribution's tokens proportionate to their relative
/// voting power in this party (less the fee).
/// @dev Allow this to be called by the party itself for `FractionalizeProposal`.
/// @param tokenType The type of token to distribute.
/// @param token The address of the token to distribute.
/// @param tokenId The ID of the token to distribute. Currently unused but
/// may be used in the future to support other distribution types.
/// @return distInfo The information about the created distribution.
function distribute(
ITokenDistributor.TokenType tokenType,
address token,
uint256 tokenId
)
external
onlyActiveMemberOrSelf
onlyWhenNotGloballyDisabled
onlyDelegateCall
returns (ITokenDistributor.DistributionInfo memory distInfo)
{
// Get the address of the token distributor.
ITokenDistributor distributor = ITokenDistributor(
_GLOBALS.getAddress(LibGlobals.GLOBAL_TOKEN_DISTRIBUTOR)
);
emit DistributionCreated(tokenType, token, tokenId);
// Create a native token distribution.
address payable feeRecipient_ = feeRecipient;
uint16 feeBps_ = feeBps;
if (tokenType == ITokenDistributor.TokenType.Native) {
return distributor.createNativeDistribution
{ value: address(this).balance }(this, feeRecipient_, feeBps_);
}
// Otherwise must be an ERC20 token distribution.
assert(tokenType == ITokenDistributor.TokenType.Erc20);
IERC20(token).compatTransfer(
address(distributor),
IERC20(token).balanceOf(address(this))
);
return distributor.createErc20Distribution(
IERC20(token),
this,
feeRecipient_,
feeBps_
);
}
/// @notice Make a proposal for members to vote on and cast a vote to accept it
/// as well.
/// @dev Only an active member (has voting power) can call this.
/// Afterwards, members can vote to support it with `accept()` or a party
/// host can unilaterally reject the proposal with `veto()`.
/// @param proposal The details of the proposal.
/// @param latestSnapIndex The index of the caller's most recent voting power
/// snapshot before the proposal was created. Should
/// be retrieved off-chain and passed in.
function propose(Proposal memory proposal, uint256 latestSnapIndex)
external
onlyActiveMember
onlyDelegateCall
returns (uint256 proposalId)
{
proposalId = ++lastProposalId;
// Store the time the proposal was created and the proposal hash.
(
_proposalStateByProposalId[proposalId].values,
_proposalStateByProposalId[proposalId].hash
) = (
ProposalStateValues({
proposedTime: uint40(block.timestamp),
passedTime: 0,
executedTime: 0,
completedTime: 0,
votes: 0
}),
getProposalHash(proposal)
);
emit Proposed(proposalId, msg.sender, proposal);
accept(proposalId, latestSnapIndex);
}
/// @notice Vote to support a proposed proposal.
/// @dev The voting power cast will be the effective voting power of the caller
/// just before `propose()` was called (see `getVotingPowerAt()`).
/// If the proposal reaches `passThresholdBps` acceptance ratio then the
/// proposal will be in the `Passed` state and will be executable after
/// the `executionDelay` has passed, putting it in the `Ready` state.
/// @param proposalId The ID of the proposal to accept.
/// @param snapIndex The index of the caller's last voting power snapshot
/// before the proposal was created. Should be retrieved
/// off-chain and passed in.
/// @return totalVotes The total votes cast on the proposal.
function accept(uint256 proposalId, uint256 snapIndex)
public
onlyDelegateCall
returns (uint256 totalVotes)
{
// Get the information about the proposal.
ProposalState storage info = _proposalStateByProposalId[proposalId];
ProposalStateValues memory values = info.values;
// Can only vote in certain proposal statuses.
{
ProposalStatus status = _getProposalStatus(values);
// Allow voting even if the proposal is passed/ready so it can
// potentially reach 100% consensus, which unlocks special
// behaviors for certain proposal types.
if (
status != ProposalStatus.Voting &&
status != ProposalStatus.Passed &&
status != ProposalStatus.Ready
) {
revert BadProposalStatusError(status);
}
}
// Cannot vote twice.
if (info.hasVoted[msg.sender]) {
revert AlreadyVotedError(msg.sender);
}
// Mark the caller as having voted.
info.hasVoted[msg.sender] = true;
// Increase the total votes that have been cast on this proposal.
uint96 votingPower = getVotingPowerAt(msg.sender, values.proposedTime - 1, snapIndex);
values.votes += votingPower;
info.values = values;
emit ProposalAccepted(proposalId, msg.sender, votingPower);
// Update the proposal status if it has reached the pass threshold.
if (values.passedTime == 0 && _areVotesPassing(
values.votes,
_governanceValues.totalVotingPower,
_governanceValues.passThresholdBps))
{
info.values.passedTime = uint40(block.timestamp);
emit ProposalPassed(proposalId);
}
return values.votes;
}
/// @notice As a party host, veto a proposal, unilaterally rejecting it.
/// @dev The proposal will never be executable and cannot be voted on anymore.
/// A proposal that has been already executed at least once (in the `InProgress` status)
/// cannot be vetoed.
/// @param proposalId The ID of the proposal to veto.
function veto(uint256 proposalId) external onlyHost onlyDelegateCall {
// Setting `votes` to -1 indicates a veto.
ProposalState storage info = _proposalStateByProposalId[proposalId];
ProposalStateValues memory values = info.values;
{
ProposalStatus status = _getProposalStatus(values);
// Proposal must be in one of the following states.
if (
status != ProposalStatus.Voting &&
status != ProposalStatus.Passed &&
status != ProposalStatus.Ready
) {
revert BadProposalStatusError(status);
}
}
// -1 indicates veto.
info.values.votes = VETO_VALUE;
emit ProposalVetoed(proposalId, msg.sender);
}
/// @notice Executes a proposal that has passed governance.
/// @dev The proposal must be in the `Ready` or `InProgress` status.
/// A `ProposalExecuted` event will be emitted with a non-empty `nextProgressData`
/// if the proposal has extra steps (must be executed again) to carry out,
/// in which case `nextProgressData` should be passed into the next `execute()` call.
/// The `ProposalExecutionEngine` enforces that only one `InProgress` proposal
/// is active at a time, so that proposal must be completed or cancelled via `cancel()`
/// in order to execute a different proposal.
/// `extraData` is optional, off-chain data a proposal might need to execute a step.
/// @param proposalId The ID of the proposal to execute.
/// @param proposal The details of the proposal.
/// @param preciousTokens The tokens that the party considers precious.
/// @param preciousTokenIds The token IDs associated with each precious token.
/// @param progressData The data returned from the last `execute()` call, if any.
/// @param extraData Off-chain data a proposal might need to execute a step.
function execute(
uint256 proposalId,
Proposal memory proposal,
IERC721[] memory preciousTokens,
uint256[] memory preciousTokenIds,
bytes calldata progressData,
bytes calldata extraData
)
external
payable
onlyActiveMember
onlyWhenNotGloballyDisabled
onlyDelegateCall
{
// Get information about the proposal.
ProposalState storage proposalState = _proposalStateByProposalId[proposalId];
// Proposal details must remain the same from `propose()`.
_validateProposalHash(proposal, proposalState.hash);
ProposalStateValues memory values = proposalState.values;
ProposalStatus status = _getProposalStatus(values);
// The proposal must be executable or have already been executed but still
// has more steps to go.
if (status != ProposalStatus.Ready && status != ProposalStatus.InProgress) {
revert BadProposalStatusError(status);
}
if (status == ProposalStatus.Ready) {
// If the proposal has not been executed yet, make sure it hasn't
// expired. Note that proposals that have been executed
// (but still have more steps) ignore `maxExecutableTime`.
if (proposal.maxExecutableTime < block.timestamp) {
revert ExecutionTimeExceededError(
proposal.maxExecutableTime,
uint40(block.timestamp)
);
}
proposalState.values.executedTime = uint40(block.timestamp);
}
// Check that the precious list is valid.
if (!_isPreciousListCorrect(preciousTokens, preciousTokenIds)) {
revert BadPreciousListError();
}
// Preemptively set the proposal to completed to avoid it being executed
// again in a deeper call.
proposalState.values.completedTime = uint40(block.timestamp);
// Execute the proposal.
bool completed = _executeProposal(
proposalId,
proposal,
preciousTokens,
preciousTokenIds,
_getProposalFlags(values),
progressData,
extraData
);
if (!completed) {
// Proposal did not complete.
proposalState.values.completedTime = 0;
}
}
/// @notice Cancel a (probably stuck) InProgress proposal.
/// @dev `proposal.cancelDelay` seconds must have passed since it was first
/// executed for this to be valid. The currently active proposal will
/// simply be yeeted out of existence so another proposal can execute.
/// This is intended to be a last resort and can leave the party in a
/// broken state. Whenever possible, active proposals should be
/// allowed to complete their lifecycle.
/// @param proposalId The ID of the proposal to cancel.
/// @param proposal The details of the proposal to cancel.
function cancel(uint256 proposalId, Proposal calldata proposal)
external
onlyActiveMember
onlyDelegateCall
{
// Get information about the proposal.
ProposalState storage proposalState = _proposalStateByProposalId[proposalId];
// Proposal details must remain the same from `propose()`.
_validateProposalHash(proposal, proposalState.hash);
ProposalStateValues memory values = proposalState.values;
{
// Must be `InProgress`.
ProposalStatus status = _getProposalStatus(values);
if (status != ProposalStatus.InProgress) {
revert BadProposalStatusError(status);
}
}
{
// Limit the `cancelDelay` to the global max and min cancel delay
// to mitigate parties accidentally getting stuck forever by setting an
// unrealistic `cancelDelay` or being reckless with too low a
// cancel delay.
uint256 cancelDelay = proposal.cancelDelay;
uint256 globalMaxCancelDelay =
_GLOBALS.getUint256(LibGlobals.GLOBAL_PROPOSAL_MAX_CANCEL_DURATION);
uint256 globalMinCancelDelay =
_GLOBALS.getUint256(LibGlobals.GLOBAL_PROPOSAL_MIN_CANCEL_DURATION);
if (globalMaxCancelDelay != 0) { // Only if we have one set.
if (cancelDelay > globalMaxCancelDelay) {
cancelDelay = globalMaxCancelDelay;
}
}
if (globalMinCancelDelay != 0) { // Only if we have one set.
if (cancelDelay < globalMinCancelDelay) {
cancelDelay = globalMinCancelDelay;
}
}
uint256 cancelTime = values.executedTime + cancelDelay;
// Must not be too early.
if (block.timestamp < cancelTime) {
revert ProposalCannotBeCancelledYetError(
uint40(block.timestamp),
uint40(cancelTime)
);
}
}
// Mark the proposal as cancelled by setting the completed time to the current
// time with the high bit set.
proposalState.values.completedTime = uint40(block.timestamp | UINT40_HIGH_BIT);
{
// Delegatecall into the proposal engine impl to perform the cancel.
(bool success, bytes memory resultData) =
(address(_getProposalExecutionEngine())).delegatecall(abi.encodeCall(
IProposalExecutionEngine.cancelProposal,
(proposalId)
));
if (!success) {
resultData.rawRevert();
}
}
emit ProposalCancelled(proposalId);
}
/// @notice As the DAO, execute an arbitrary function call from this contract.
/// @dev Emergency actions must not be revoked for this to work.
/// @param targetAddress The contract to call.
/// @param targetCallData The data to pass to the contract.
/// @param amountEth The amount of ETH to send to the contract.
function emergencyExecute(
address targetAddress,
bytes calldata targetCallData,
uint256 amountEth
)
external
payable
onlyPartyDao
onlyWhenEmergencyExecuteAllowed
onlyDelegateCall
{
(bool success, bytes memory res) = targetAddress.call{value: amountEth}(targetCallData);
if (!success) {
res.rawRevert();
}
emit EmergencyExecute(targetAddress, targetCallData, amountEth);
}
/// @notice Revoke the DAO's ability to call emergencyExecute().
/// @dev Either the DAO or the party host can call this.
function disableEmergencyExecute() external onlyPartyDaoOrHost onlyDelegateCall {
emergencyExecuteDisabled = true;
emit EmergencyExecuteDisabled();
}
function _executeProposal(
uint256 proposalId,
Proposal memory proposal,
IERC721[] memory preciousTokens,
uint256[] memory preciousTokenIds,
uint256 flags,
bytes memory progressData,
bytes memory extraData
)
private
returns (bool completed)
{
// Setup the arguments for the proposal execution engine.
IProposalExecutionEngine.ExecuteProposalParams memory executeParams =
IProposalExecutionEngine.ExecuteProposalParams({
proposalId: proposalId,
proposalData: proposal.proposalData,
progressData: progressData,
extraData: extraData,
preciousTokens: preciousTokens,
preciousTokenIds: preciousTokenIds,
flags: flags
});
// Get the progress data returned after the proposal is executed.
bytes memory nextProgressData;
{
// Execute the proposal.
(bool success, bytes memory resultData) =
address(_getProposalExecutionEngine()).delegatecall(abi.encodeCall(
IProposalExecutionEngine.executeProposal,
(executeParams)
));
if (!success) {
resultData.rawRevert();
}
nextProgressData = abi.decode(resultData, (bytes));
}
emit ProposalExecuted(proposalId, msg.sender, nextProgressData);
// If the returned progress data is empty, then the proposal completed
// and it should not be executed again.
return nextProgressData.length == 0;
}
// Get the most recent voting power snapshot <= timestamp using `hintindex` as a "hint".
function _getVotingPowerSnapshotAt(address voter, uint40 timestamp, uint256 hintIndex)
internal
view
returns (VotingPowerSnapshot memory snap)
{
VotingPowerSnapshot[] storage snaps = _votingPowerSnapshotsByVoter[voter];
uint256 snapsLength = snaps.length;
if (snapsLength != 0) {
if (
// Hint is within bounds.
hintIndex < snapsLength &&
// Snapshot is not too recent.
snaps[hintIndex].timestamp <= timestamp &&
// Snapshot is not too old.
(hintIndex == snapsLength - 1 || snaps[hintIndex+1].timestamp > timestamp)
) {
return snaps[hintIndex];
}
// Hint was wrong, fallback to binary search to find snapshot.
hintIndex = findVotingPowerSnapshotIndex(voter, timestamp);
// Check that snapshot was found.
if (hintIndex != type(uint256).max) {
return snaps[hintIndex];
}
}
// No snapshot found.
return snap;
}
// Transfers some voting power of `from` to `to`. The total voting power of
// their respective delegates will be updated as well.
function _transferVotingPower(address from, address to, uint256 power)
internal
{
int192 powerI192 = power.safeCastUint256ToInt192();
_adjustVotingPower(from, -powerI192, address(0));
_adjustVotingPower(to, powerI192, address(0));
}
// Increase `voter`'s intrinsic voting power and update their delegate if delegate is nonzero.
function _adjustVotingPower(address voter, int192 votingPower, address delegate)
internal
{
VotingPowerSnapshot memory oldSnap =
_getLastVotingPowerSnapshotForVoter(voter);
address oldDelegate = delegationsByVoter[voter];
// If `oldDelegate` is zero and `voter` never delegated, then have
// `voter` delegate to themself.
oldDelegate = oldDelegate == address(0) ? voter : oldDelegate;
// If the new `delegate` is zero, use the current (old) delegate.
delegate = delegate == address(0) ? oldDelegate : delegate;
VotingPowerSnapshot memory newSnap = VotingPowerSnapshot({
timestamp: uint40(block.timestamp),
delegatedVotingPower: oldSnap.delegatedVotingPower,
intrinsicVotingPower: (
oldSnap.intrinsicVotingPower.safeCastUint96ToInt192() + votingPower
).safeCastInt192ToUint96(),
isDelegated: delegate != voter
});
_insertVotingPowerSnapshot(voter, newSnap);
delegationsByVoter[voter] = delegate;
// Handle rebalancing delegates.
_rebalanceDelegates(voter, oldDelegate, delegate, oldSnap, newSnap);
}
function _getTotalVotingPower() internal view returns (uint256) {
return _governanceValues.totalVotingPower;
}
// Update the delegated voting power of the old and new delegates delegated to
// by `voter` based on the snapshot change.
function _rebalanceDelegates(
address voter,
address oldDelegate,
address newDelegate,
VotingPowerSnapshot memory oldSnap,
VotingPowerSnapshot memory newSnap
)
private
{
if (newDelegate == address(0) || oldDelegate == address(0)) {
revert InvalidDelegateError();
}
if (oldDelegate != voter && oldDelegate != newDelegate) {
// Remove past voting power from old delegate.
VotingPowerSnapshot memory oldDelegateSnap =
_getLastVotingPowerSnapshotForVoter(oldDelegate);
VotingPowerSnapshot memory updatedOldDelegateSnap =
VotingPowerSnapshot({
timestamp: uint40(block.timestamp),
delegatedVotingPower:
oldDelegateSnap.delegatedVotingPower -
oldSnap.intrinsicVotingPower,
intrinsicVotingPower: oldDelegateSnap.intrinsicVotingPower,
isDelegated: oldDelegateSnap.isDelegated
});
_insertVotingPowerSnapshot(oldDelegate, updatedOldDelegateSnap);
}
if (newDelegate != voter) { // Not delegating to self.
// Add new voting power to new delegate.
VotingPowerSnapshot memory newDelegateSnap =
_getLastVotingPowerSnapshotForVoter(newDelegate);
uint96 newDelegateDelegatedVotingPower =
newDelegateSnap.delegatedVotingPower + newSnap.intrinsicVotingPower;
if (newDelegate == oldDelegate) {
// If the old and new delegate are the same, subtract the old
// intrinsic voting power of the voter, or else we will double
// count a portion of it.
newDelegateDelegatedVotingPower -= oldSnap.intrinsicVotingPower;
}
VotingPowerSnapshot memory updatedNewDelegateSnap =
VotingPowerSnapshot({
timestamp: uint40(block.timestamp),
delegatedVotingPower: newDelegateDelegatedVotingPower,
intrinsicVotingPower: newDelegateSnap.intrinsicVotingPower,
isDelegated: newDelegateSnap.isDelegated
});
_insertVotingPowerSnapshot(newDelegate, updatedNewDelegateSnap);
}
}
// Append a new voting power snapshot, overwriting the last one if possible.
function _insertVotingPowerSnapshot(address voter, VotingPowerSnapshot memory snap)
private
{
VotingPowerSnapshot[] storage voterSnaps = _votingPowerSnapshotsByVoter[voter];
uint256 n = voterSnaps.length;
// If same timestamp as last entry, overwrite the last snapshot, otherwise append.
if (n != 0) {
VotingPowerSnapshot memory lastSnap = voterSnaps[n - 1];
if (lastSnap.timestamp == snap.timestamp) {
voterSnaps[n - 1] = snap;
return;
}
}
voterSnaps.push(snap);
}
function _getLastVotingPowerSnapshotForVoter(address voter)
private
view
returns (VotingPowerSnapshot memory snap)
{
VotingPowerSnapshot[] storage voterSnaps = _votingPowerSnapshotsByVoter[voter];
uint256 n = voterSnaps.length;
if (n != 0) {
snap = voterSnaps[n - 1];
}
}
function _getProposalFlags(ProposalStateValues memory pv)
private
view
returns (uint256)
{
if (_isUnanimousVotes(pv.votes, _governanceValues.totalVotingPower)) {
return LibProposal.PROPOSAL_FLAG_UNANIMOUS;
}
return 0;
}
function _getProposalStatus(ProposalStateValues memory pv)
private
view
returns (ProposalStatus status)
{
// Never proposed.
if (pv.proposedTime == 0) {
return ProposalStatus.Invalid;
}
// Executed at least once.
if (pv.executedTime != 0) {
if (pv.completedTime == 0) {
return ProposalStatus.InProgress;
}
// completedTime high bit will be set if cancelled.
if (pv.completedTime & UINT40_HIGH_BIT == UINT40_HIGH_BIT) {
return ProposalStatus.Cancelled;
}
return ProposalStatus.Complete;
}
// Vetoed.
if (pv.votes == type(uint96).max) {
return ProposalStatus.Defeated;
}
uint40 t = uint40(block.timestamp);
GovernanceValues memory gv = _governanceValues;
if (pv.passedTime != 0) {
// Ready.
if (pv.passedTime + gv.executionDelay <= t) {
return ProposalStatus.Ready;
}
// If unanimous, we skip the execution delay.
if (_isUnanimousVotes(pv.votes, gv.totalVotingPower)) {
return ProposalStatus.Ready;
}
// Passed.
return ProposalStatus.Passed;
}
// Voting window expired.
if (pv.proposedTime + gv.voteDuration <= t) {
return ProposalStatus.Defeated;
}
return ProposalStatus.Voting;
}
function _isUnanimousVotes(uint96 totalVotes, uint96 totalVotingPower)
private
pure
returns (bool)
{
uint256 acceptanceRatio = (totalVotes * 1e4) / totalVotingPower;
// If >= 99.99% acceptance, consider it unanimous.
// The minting formula for voting power is a bit lossy, so we check
// for slightly less than 100%.
return acceptanceRatio >= 0.9999e4;
}
function _areVotesPassing(
uint96 voteCount,
uint96 totalVotingPower,
uint16 passThresholdBps
)
private
pure
returns (bool)
{
return uint256(voteCount) * 1e4
/ uint256(totalVotingPower) >= uint256(passThresholdBps);
}
function _setPreciousList(
IERC721[] memory preciousTokens,
uint256[] memory preciousTokenIds
)
private
{
if (preciousTokens.length != preciousTokenIds.length) {
revert MismatchedPreciousListLengths();
}
preciousListHash = _hashPreciousList(preciousTokens, preciousTokenIds);
}
function _isPreciousListCorrect(
IERC721[] memory preciousTokens,
uint256[] memory preciousTokenIds
)
private
view
returns (bool)
{
return preciousListHash == _hashPreciousList(preciousTokens, preciousTokenIds);
}
function _hashPreciousList(
IERC721[] memory preciousTokens,
uint256[] memory preciousTokenIds
)
internal
pure
returns (bytes32 h)
{
assembly {
mstore(0x00, keccak256(
add(preciousTokens, 0x20),
mul(mload(preciousTokens), 0x20)
))
mstore(0x20, keccak256(
add(preciousTokenIds, 0x20),
mul(mload(preciousTokenIds), 0x20)
))
h := keccak256(0x00, 0x40)
}
}
// Assert that the hash of a proposal matches expectedHash.
function _validateProposalHash(Proposal memory proposal, bytes32 expectedHash)
private
pure
{
bytes32 actualHash = getProposalHash(proposal);
if (expectedHash != actualHash) {
revert BadProposalHashError(actualHash, expectedHash);
}
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
import "../utils/ReadOnlyDelegateCall.sol";
import "../utils/LibSafeCast.sol";
import "openzeppelin/contracts/interfaces/IERC2981.sol";
import "../globals/IGlobals.sol";
import "../tokens/IERC721.sol";
import "../vendor/solmate/ERC721.sol";
import "./PartyGovernance.sol";
import "../renderers/RendererStorage.sol";
/// @notice ERC721 functionality built on top of `PartyGovernance`.
contract PartyGovernanceNFT is
PartyGovernance,
ERC721,
IERC2981
{
using LibSafeCast for uint256;
using LibSafeCast for uint96;
error OnlyMintAuthorityError(address actual, address expected);
// The `Globals` contract storing global configuration values. This contract
// is immutable and it’s address will never change.
IGlobals private immutable _GLOBALS;
/// @notice Who can call `mint()`. Usually this will be the crowdfund contract that
/// created the party.
address public mintAuthority;
/// @notice The number of tokens that have been minted.
uint96 public tokenCount;
/// @notice The total minted voting power.
/// Capped to `_governanceValues.totalVotingPower`
uint96 public mintedVotingPower;
/// @notice The voting power of `tokenId`.
mapping (uint256 => uint256) public votingPowerByTokenId;
modifier onlyMinter() {
address minter = mintAuthority;
if (msg.sender != minter) {
revert OnlyMintAuthorityError(msg.sender, minter);
}
_;
}
// Set the `Globals` contract. The name of symbol of ERC721 does not matter;
// it will be set in `_initialize()`.
constructor(IGlobals globals) PartyGovernance(globals) ERC721('', '') {
_GLOBALS = globals;
}
// Initialize storage for proxy contracts.
function _initialize(
string memory name_,
string memory symbol_,
uint256 customizationPresetId,
PartyGovernance.GovernanceOpts memory governanceOpts,
IERC721[] memory preciousTokens,
uint256[] memory preciousTokenIds,
address mintAuthority_
)
internal
{
PartyGovernance._initialize(governanceOpts, preciousTokens, preciousTokenIds);
name = name_;
symbol = symbol_;
mintAuthority = mintAuthority_;
if (customizationPresetId != 0) {
RendererStorage(_GLOBALS.getAddress(LibGlobals.GLOBAL_RENDERER_STORAGE))
.useCustomizationPreset(customizationPresetId);
}
}
/// @inheritdoc ERC721
function ownerOf(uint256 tokenId)
public
view
override(ERC721, ITokenDistributorParty)
returns (address owner)
{
return ERC721.ownerOf(tokenId);
}
/// @inheritdoc EIP165
function supportsInterface(bytes4 interfaceId)
public
pure
override(PartyGovernance, ERC721, IERC165)
returns (bool)
{
return PartyGovernance.supportsInterface(interfaceId) ||
ERC721.supportsInterface(interfaceId) ||
interfaceId == type(IERC2981).interfaceId;
}
/// @inheritdoc ERC721
function tokenURI(uint256) public override view returns (string memory) {
_delegateToRenderer();
return ""; // Just to make the compiler happy.
}
/// @notice Returns a URI for the storefront-level metadata for your contract.
function contractURI() external view returns (string memory) {
_delegateToRenderer();
return ""; // Just to make the compiler happy.
}
/// @notice Called with the sale price to determine how much royalty
// is owed and to whom.
function royaltyInfo(uint256, uint256)
external
view
returns (address, uint256)
{
_delegateToRenderer();
return (address(0), 0); // Just to make the compiler happy.
}
/// @inheritdoc ITokenDistributorParty
function getDistributionShareOf(uint256 tokenId) external view returns (uint256) {
return votingPowerByTokenId[tokenId] * 1e18 / _getTotalVotingPower();
}
/// @notice Mint a governance NFT for `owner` with `votingPower` and
/// immediately delegate voting power to `delegate.`
/// @param owner The owner of the NFT.
/// @param votingPower The voting power of the NFT.
/// @param delegate The address to delegate voting power to.
function mint(
address owner,
uint256 votingPower,
address delegate
)
external
onlyMinter
onlyDelegateCall
returns (uint256 tokenId)
{
(uint96 tokenCount_, uint96 mintedVotingPower_) = (tokenCount, mintedVotingPower);
uint96 totalVotingPower = _governanceValues.totalVotingPower;
// Cap voting power to remaining unminted voting power supply.
uint96 votingPower_ = votingPower.safeCastUint256ToUint96();
if (totalVotingPower - mintedVotingPower_ < votingPower_) {
votingPower_ = totalVotingPower - mintedVotingPower_;
}
mintedVotingPower_ += votingPower_;
// Update state.
tokenId = tokenCount = tokenCount_ + 1;
mintedVotingPower = mintedVotingPower_;
votingPowerByTokenId[tokenId] = votingPower_;
// Use delegate from party over the one set during crowdfund.
address delegate_ = delegationsByVoter[owner];
if (delegate_ != address(0)) {
delegate = delegate_;
}
_adjustVotingPower(owner, votingPower_.safeCastUint96ToInt192(), delegate);
_safeMint(owner, tokenId);
}
/// @inheritdoc ERC721
function transferFrom(address owner, address to, uint256 tokenId)
public
override
onlyDelegateCall
{
// Transfer voting along with token.
_transferVotingPower(owner, to, votingPowerByTokenId[tokenId]);
super.transferFrom(owner, to, tokenId);
}
/// @inheritdoc ERC721
function safeTransferFrom(address owner, address to, uint256 tokenId)
public
override
onlyDelegateCall
{
// super.safeTransferFrom() will call transferFrom() first which will
// transfer voting power.
super.safeTransferFrom(owner, to, tokenId);
}
/// @inheritdoc ERC721
function safeTransferFrom(address owner, address to, uint256 tokenId, bytes calldata data)
public
override
onlyDelegateCall
{
// super.safeTransferFrom() will call transferFrom() first which will
// transfer voting power.
super.safeTransferFrom(owner, to, tokenId, data);
}
/// @notice Relinquish the ability to call `mint()` by an authority.
function abdicate() external onlyMinter onlyDelegateCall {
delete mintAuthority;
}
function _delegateToRenderer() private view {
_readOnlyDelegateCall(
// Instance of IERC721Renderer.
_GLOBALS.getAddress(LibGlobals.GLOBAL_GOVERNANCE_NFT_RENDER_IMPL),
msg.data
);
assert(false); // Will not be reached.
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
import "../tokens/IERC721.sol";
// Upgradeable proposals logic contract interface.
interface IProposalExecutionEngine {
struct ExecuteProposalParams {
uint256 proposalId;
bytes proposalData;
bytes progressData;
bytes extraData;
uint256 flags;
IERC721[] preciousTokens;
uint256[] preciousTokenIds;
}
function initialize(address oldImpl, bytes memory initData) external;
/// @notice Execute a proposal.
/// @dev Must be delegatecalled into by PartyGovernance.
/// If the proposal is incomplete, continues its next step (if possible).
/// If another proposal is incomplete, this will fail. Only one
/// incomplete proposal is allowed at a time.
/// @param params The data needed to execute the proposal.
/// @return nextProgressData Bytes to be passed into the next `execute()` call,
/// if the proposal execution is incomplete. Otherwise, empty bytes
/// to indicate the proposal is complete.
function executeProposal(ExecuteProposalParams memory params)
external returns (bytes memory nextProgressData);
/// @notice Forcibly cancel an incomplete proposal.
/// @param proposalId The ID of the proposal to cancel.
/// @dev This is intended to be a last resort as it can leave a party in a
/// broken step. Whenever possible, proposals should be allowed to
/// complete their entire lifecycle.
function cancelProposal(uint256 proposalId) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
import "../tokens/IERC721.sol";
library LibProposal {
uint256 internal constant PROPOSAL_FLAG_UNANIMOUS = 0x1;
function isTokenPrecious(IERC721 token, IERC721[] memory preciousTokens)
internal
pure
returns (bool)
{
for (uint256 i; i < preciousTokens.length; ++i) {
if (token == preciousTokens[i]) {
return true;
}
}
return false;
}
function isTokenIdPrecious(
IERC721 token,
uint256 tokenId,
IERC721[] memory preciousTokens,
uint256[] memory preciousTokenIds
)
internal
pure
returns (bool)
{
for (uint256 i; i < preciousTokens.length; ++i) {
if (token == preciousTokens[i] && tokenId == preciousTokenIds[i]) {
return true;
}
}
return false;
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
import "./IProposalExecutionEngine.sol";
import "../utils/LibRawResult.sol";
// The storage bucket shared by `PartyGovernance` and the `ProposalExecutionEngine`.
// Read this for more context on the pattern motivating this:
// https://github.com/dragonfly-xyz/useful-solidity-patterns/tree/main/patterns/explicit-storage-buckets
abstract contract ProposalStorage {
using LibRawResult for bytes;
struct SharedProposalStorage {
IProposalExecutionEngine engineImpl;
}
uint256 internal constant PROPOSAL_FLAG_UNANIMOUS = 0x1;
uint256 private constant SHARED_STORAGE_SLOT = uint256(keccak256("ProposalStorage.SharedProposalStorage"));
function _getProposalExecutionEngine()
internal
view
returns (IProposalExecutionEngine impl)
{
return _getSharedProposalStorage().engineImpl;
}
function _setProposalExecutionEngine(IProposalExecutionEngine impl) internal {
_getSharedProposalStorage().engineImpl = impl;
}
function _initProposalImpl(IProposalExecutionEngine impl, bytes memory initData)
internal
{
SharedProposalStorage storage stor = _getSharedProposalStorage();
IProposalExecutionEngine oldImpl = stor.engineImpl;
stor.engineImpl = impl;
(bool s, bytes memory r) = address(impl).delegatecall(
abi.encodeCall(
IProposalExecutionEngine.initialize,
(address(oldImpl), initData)
)
);
if (!s) {
r.rawRevert();
}
}
function _getSharedProposalStorage()
private
pure
returns (SharedProposalStorage storage stor)
{
uint256 s = SHARED_STORAGE_SLOT;
assembly { stor.slot := s }
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
import "solmate/utils/SSTORE2.sol";
import "../utils/Multicall.sol";
contract RendererStorage is Multicall {
error AlreadySetError();
error NotOwnerError(address caller, address owner);
event OwnershipTransferred(address previousOwner, address newOwner);
uint256 constant CROWDFUND_CARD_DATA = 0;
uint256 constant PARTY_CARD_DATA = 1;
/// @notice Address allowed to store new data.
address public owner;
/// @notice Customization presets by ID, used for rendering cards. Begins at
/// 1, 0 is reserved to indicate in `getPresetFor()` that a
/// party instance use the preset set by the crowdfund instance that
/// created it.
mapping(uint256 => bytes) public customizationPresets;
/// @notice Customization preset used by a crowdfund or party instance.
mapping(address => uint256) public getPresetFor;
/// @notice Addresses where URI data chunks are stored.
mapping(uint256 => address) public files;
modifier onlyOwner() {
address owner_ = owner;
if (msg.sender != owner_) {
revert NotOwnerError(msg.sender, owner_);
}
_;
}
constructor(address _owner) {
// Set the address allowed to write new data.
owner = _owner;
// Write URI data used by V1 of the renderers:
files[CROWDFUND_CARD_DATA] = SSTORE2.write(bytes(
'<path class="o" d="M118.4 419.5h5.82v1.73h-4.02v1.87h3.74v1.73h-3.74v1.94h4.11v1.73h-5.91v-9Zm9.93 1.76h-2.6v-1.76h7.06v1.76h-2.61v7.24h-1.85v-7.24Zm6.06-1.76h1.84v3.55h3.93v-3.55H142v9h-1.84v-3.67h-3.93v3.67h-1.84v-9Z"/><path class="o" d="M145 413a4 4 0 0 1 4 4v14a4 4 0 0 1-4 4H35a4 4 0 0 1-4-4v-14a4 4 0 0 1 4-4h110m0-1H35a5 5 0 0 0-5 5v14a5 5 0 0 0 5 5h110a5 5 0 0 0 5-5v-14a5 5 0 0 0-5-5Z"/><path d="M239.24 399.83h3.04c1.7 0 2.82 1 2.82 2.55 0 2.1-1.27 3.32-3.57 3.32h-1.97l-.71 3.3h-1.56l1.96-9.17Zm2.34 4.38c1.23 0 1.88-.58 1.88-1.68 0-.73-.49-1.2-1.48-1.2h-1.51l-.6 2.88h1.7Zm3.57 1.86c0-2.27 1.44-3.83 3.57-3.83 1.82 0 3.06 1.25 3.06 3.09 0 2.28-1.43 3.83-3.57 3.83-1.82 0-3.06-1.25-3.06-3.09Zm3.13 1.74c1.19 0 1.93-1.02 1.93-2.52 0-1.06-.62-1.69-1.56-1.69-1.19 0-1.93 1.02-1.93 2.52 0 1.06.62 1.69 1.56 1.69Zm4.74-5.41h1.49l.28 4.73 2.25-4.73h1.64l.23 4.77 2.25-4.77h1.56l-3.3 6.61h-1.62l-.25-5.04-2.42 5.04h-1.63l-.48-6.61Zm9.54 3.66c0-2.27 1.45-3.81 3.6-3.81 2 0 3.05 1.58 2.33 3.92h-4.46c0 1.1.81 1.68 2.05 1.68.8 0 1.45-.2 2.1-.59l-.31 1.46a4.2 4.2 0 0 1-2.04.44c-2.06 0-3.26-1.19-3.26-3.11Zm4.7-1.07c.12-.86-.31-1.46-1.22-1.46s-1.57.61-1.82 1.46h3.05Zm3.46-2.59h1.55l-.28 1.28c.81-1.7 2.56-1.36 2.77-1.29l-.35 1.46c-.18-.06-2.3-.63-2.82 1.68l-.74 3.48h-1.55l1.42-6.61Zm3.91 3.66c0-2.27 1.45-3.81 3.6-3.81 2 0 3.05 1.58 2.33 3.92h-4.46c0 1.1.81 1.68 2.05 1.68.8 0 1.45-.2 2.1-.59l-.31 1.46a4.2 4.2 0 0 1-2.04.44c-2.06 0-3.26-1.19-3.26-3.11Zm4.7-1.07c.12-.86-.31-1.46-1.22-1.46s-1.57.61-1.82 1.46h3.05Zm2.25 1.36c0-2.44 1.36-4.1 3.26-4.1 1 0 1.76.53 2.05 1.31l.79-3.72h1.55l-1.96 9.17h-1.55l.2-.92a2.15 2.15 0 0 1-1.92 1.08c-1.49 0-2.43-1.18-2.43-2.82Zm3 1.51c.88 0 1.51-.58 1.73-1.56l.17-.81c.24-1.1-.31-1.93-1.36-1.93-1.19 0-1.94 1.08-1.94 2.59 0 1.06.55 1.71 1.4 1.71Zm9.6-.01-.25 1.16h-1.55l1.96-9.17h1.55l-.73 3.47a2.35 2.35 0 0 1 1.99-1.05c1.49 0 2.35 1.16 2.35 2.76 0 2.52-1.36 4.16-3.21 4.16-.98 0-1.81-.53-2.1-1.32Zm1.83.01c1.16 0 1.87-1.06 1.87-2.61 0-1.04-.5-1.69-1.39-1.69s-1.52.56-1.73 1.55l-.17.79c-.24 1.14.34 1.97 1.42 1.97Zm5.68 1.16-1.04-6.62h1.52l.66 4.75 2.66-4.75h1.69l-5.31 9.13h-1.73l1.55-2.51Zm23.48-6.8a42.14 42.14 0 0 0-.75 6.01 43.12 43.12 0 0 0 5.58 2.35 42.54 42.54 0 0 0 5.58-2.35 45.32 45.32 0 0 0-.75-6.01c-.91-.79-2.6-2.21-4.83-3.66a42.5 42.5 0 0 0-4.83 3.66Zm13.07-7.95s.82-.29 1.76-.45a14.9 14.9 0 0 0-9.53-3.81c.66.71 1.28 1.67 1.84 2.75 1.84.22 4.07.7 5.92 1.51Zm-2.71 18.36c-2.06-.4-4.05-.97-5.53-1.51a38.65 38.65 0 0 1-5.53 1.51c.12 1.5.35 3.04.76 4.58 0 0 1.54 1.82 4.78 2.8 3.23-.98 4.78-2.8 4.78-2.8.4-1.53.64-3.08.76-4.58Zm-13.77-18.37a22.3 22.3 0 0 1 5.93-1.51 12.4 12.4 0 0 1 1.84-2.75 14.97 14.97 0 0 0-9.53 3.81c.95.16 1.76.45 1.76.45Zm-4.72 8.77a25.74 25.74 0 0 0 3.58 2.94 37.48 37.48 0 0 1 4.08-4.04c.27-1.56.77-3.57 1.46-5.55a25.24 25.24 0 0 0-4.34-1.63s-2.35.42-4.81 2.74c-.77 3.29.04 5.54.04 5.54Zm25.92 0s.81-2.25.04-5.54c-2.46-2.31-4.81-2.74-4.81-2.74-1.53.42-2.99.99-4.34 1.63a37.79 37.79 0 0 1 1.46 5.55 37.44 37.44 0 0 1 4.08 4.04 25.86 25.86 0 0 0 3.58-2.94Zm-26.38.2s-.66-.56-1.27-1.3c-.7 3.34-.27 6.93 1.46 10.16.28-.93.8-1.94 1.46-2.97a22.32 22.32 0 0 1-1.66-5.88Zm8.24 14.27a22.07 22.07 0 0 1-4.27-4.38c-1.22.06-2.36 0-3.3-.22a14.91 14.91 0 0 0 8.07 6.34c-.34-.9-.5-1.75-.5-1.75Zm18.6-14.27s.66-.56 1.27-1.3c.7 3.34.27 6.93-1.46 10.16-.28-.93-.8-1.94-1.46-2.97a22.32 22.32 0 0 0 1.66-5.88Zm-8.24 14.27a22.07 22.07 0 0 0 4.27-4.38c1.22.06 2.36 0 3.3-.22a14.91 14.91 0 0 1-8.07 6.34c.34-.9.5-1.75.5-1.75ZM330 391.84l-4.12 2.45 1.26 3.91h5.72l1.26-3.91-4.12-2.45Zm-11.4 19.74 4.18 2.35 2.75-3.05-2.86-4.95-4.02.86-.06 4.79Zm22.79 0-.06-4.79-4.02-.86-2.86 4.95 2.75 3.05 4.18-2.35Z" style="fill:#00c1fa"/><use height="300" transform="matrix(1 0 0 .09 29.85 444)" width="300.15" xlink:href="#a"/><use height="21.15" transform="translate(30 446.92)" width="300" xlink:href="#b"/><g><path d="m191.54 428.67-28.09-24.34A29.98 29.98 0 0 0 143.8 397H30a15 15 0 0 0-15 15v98a15 15 0 0 0 15 15h300a15 15 0 0 0 15-15v-59a15 15 0 0 0-15-15H211.19a30 30 0 0 1-19.65-7.33Z" style="fill:url(#i)"/></g></svg>'
));
files[PARTY_CARD_DATA] = SSTORE2.write(bytes(
' d="M30 444.28h4.3c3.05 0 5.17 2.13 5.17 5.36s-2.11 5.35-5.17 5.35H30v-10.72Zm3.95 8.61c2.07 0 3.24-1.2 3.24-3.25s-1.16-3.26-3.24-3.26h-1.77v6.51h1.77Zm7.78-8.61h2.19V455h-2.19v-10.72Zm4.79 10.02v-2.31c1 .74 2.13 1.13 3.25 1.13s1.68-.45 1.68-1.23c0-.69-.39-.95-1.23-1.19l-1.19-.34c-1.78-.48-2.65-1.46-2.65-3.1 0-1.95 1.5-3.18 3.87-3.18 1.05 0 2.09.21 2.91.66V447a5.53 5.53 0 0 0-2.96-.84c-.93 0-1.57.35-1.57 1.06.01.6.39.91 1.16 1.12l1.32.39c1.82.5 2.61 1.42 2.61 3.07 0 2.1-1.53 3.39-3.82 3.39a6.08 6.08 0 0 1-3.38-.9Zm11.93-7.92h-3.1v-2.1h8.41v2.1h-3.11V455h-2.2v-8.62Zm7.56-2.1h4.5c2 0 3.33 1.26 3.33 3.25 0 1.86-1.18 3.1-3.01 3.19l3.53 4.27H71.7l-3.54-4.43v4.43h-2.14v-10.72Zm4.1 4.85c.98 0 1.54-.55 1.54-1.44s-.56-1.43-1.54-1.43h-1.96v2.87h1.96Zm6.04-4.85h2.19V455h-2.19v-10.72Zm5.07 0h4.5c1.99 0 3.21 1.15 3.21 2.79 0 1.06-.5 1.93-1.36 2.32a2.46 2.46 0 0 1 1.78 2.49c0 1.9-1.33 3.11-3.52 3.11h-4.61v-10.72Zm4.17 4.4c.87 0 1.37-.45 1.37-1.26s-.5-1.26-1.37-1.26h-2.06v2.52h2.06Zm.34 4.44c.88 0 1.46-.46 1.46-1.29s-.57-1.3-1.46-1.3h-2.39v2.59h2.39Zm5.63-2.51v-6.33h2.18v6.29c0 1.6.88 2.52 2.3 2.52s2.28-.92 2.28-2.52v-6.29h2.18v6.33c0 2.86-1.72 4.58-4.47 4.58s-4.48-1.72-4.48-4.58Zm14.21-4.23h-3.1v-2.1h8.41v2.1h-3.11V455h-2.2v-8.62Zm7.56-2.1h2.18V455h-2.18v-10.72Zm4.45 5.36c0-3.25 2.21-5.56 5.32-5.56s5.28 2.31 5.28 5.56-2.2 5.55-5.28 5.55-5.32-2.31-5.32-5.55Zm5.32 3.45c1.85 0 3-1.34 3-3.45s-1.15-3.46-3-3.46-3.04 1.34-3.04 3.46 1.16 3.45 3.04 3.45Zm7.54-8.81h2.94l4.03 8.17v-8.17h2.07V455h-2.93l-4.03-8.17V455h-2.09v-10.72Zm11.65 10.02v-2.31c.99.74 2.13 1.13 3.25 1.13s1.68-.45 1.68-1.23c0-.69-.39-.95-1.23-1.19l-1.19-.34c-1.78-.48-2.65-1.46-2.65-3.1 0-1.95 1.5-3.18 3.87-3.18 1.05 0 2.09.21 2.91.66V447a5.53 5.53 0 0 0-2.96-.84c-.92 0-1.57.35-1.57 1.06.01.6.39.91 1.16 1.12l1.32.39c1.82.5 2.61 1.42 2.61 3.07 0 2.1-1.53 3.39-3.82 3.39a6.08 6.08 0 0 1-3.38-.9Zm45.9-10.02h2.38l2.63 8.18 2.72-8.18h2.33L194.39 455h-2.76l-3.64-10.72Zm11.19 5.36c0-3.25 2.21-5.56 5.32-5.56s5.28 2.31 5.28 5.56-2.2 5.55-5.28 5.55-5.32-2.31-5.32-5.55Zm5.32 3.45c1.85 0 3-1.34 3-3.45s-1.15-3.46-3-3.46-3.04 1.34-3.04 3.46 1.16 3.45 3.04 3.45Zm9.41-6.71h-3.1v-2.1h8.41v2.1h-3.11V455h-2.2v-8.62Zm7.56-2.1h6.93v2.06h-4.79v2.23h4.45v2.06h-4.45v2.31h4.89V455h-7.03v-10.72Zm14.17 0h4.27c2.25 0 3.66 1.33 3.66 3.52s-1.4 3.53-3.66 3.53h-2.11V455h-2.16v-10.72Zm4.08 4.99c1.06 0 1.61-.53 1.61-1.47s-.55-1.46-1.61-1.46h-1.92v2.93h1.92Zm5.49.38c0-3.25 2.21-5.56 5.32-5.56s5.28 2.31 5.28 5.56-2.2 5.55-5.28 5.55-5.32-2.31-5.32-5.55Zm5.32 3.45c1.85 0 3-1.34 3-3.45s-1.15-3.46-3-3.46-3.04 1.34-3.04 3.46 1.16 3.45 3.04 3.45Zm6.54-8.81h2.34l1.69 7.84 1.86-7.84h2.41l1.82 7.84 1.75-7.84h2.27l-2.66 10.72H266l-1.88-8.15-1.85 8.15h-2.55l-2.66-10.72Zm16.11 0h6.93v2.06h-4.79v2.23h4.45v2.06h-4.45v2.31h4.89v2.06h-7.03v-10.72Zm9.69 0h4.5c2 0 3.33 1.26 3.33 3.25 0 1.86-1.18 3.1-3.01 3.19l3.53 4.27h-2.66l-3.54-4.43V455h-2.14v-10.72Zm4.1 4.85c.98 0 1.54-.55 1.54-1.44s-.56-1.43-1.54-1.43h-1.96v2.87h1.96ZM30 259.28h4.27c2.25 0 3.66 1.33 3.66 3.52s-1.4 3.53-3.66 3.53h-2.12V270h-2.16v-10.72Zm4.08 4.99c1.06 0 1.61-.53 1.61-1.47s-.55-1.46-1.61-1.46h-1.92v2.93h1.92Zm6.1-4.99h4.5c2 0 3.33 1.26 3.33 3.25 0 1.86-1.18 3.1-3.01 3.19l3.53 4.27h-2.66l-3.54-4.43v4.43h-2.14v-10.72Zm4.1 4.85c.98 0 1.54-.55 1.54-1.44s-.56-1.43-1.54-1.43h-1.96v2.87h1.96Zm5.43.52c0-3.25 2.21-5.56 5.32-5.56s5.28 2.31 5.28 5.56-2.2 5.55-5.28 5.55-5.32-2.31-5.32-5.55Zm5.32 3.45c1.85 0 3-1.34 3-3.45s-1.15-3.46-3-3.46-3.04 1.34-3.04 3.46 1.16 3.45 3.04 3.45Zm7.54-8.81h4.27c2.25 0 3.66 1.33 3.66 3.52s-1.4 3.53-3.66 3.53h-2.11v3.67h-2.16v-10.72Zm4.08 4.99c1.06 0 1.61-.53 1.61-1.47s-.55-1.46-1.61-1.46h-1.92v2.93h1.92Zm5.49.38c0-3.25 2.21-5.56 5.32-5.56s5.28 2.31 5.28 5.56-2.2 5.55-5.28 5.55-5.32-2.31-5.32-5.55Zm5.32 3.45c1.85 0 3-1.34 3-3.45s-1.15-3.46-3-3.46-3.04 1.34-3.04 3.46 1.16 3.45 3.04 3.45Zm7.26 1.21v-2.31c.99.74 2.13 1.13 3.25 1.13s1.68-.45 1.68-1.23c0-.69-.39-.95-1.23-1.19l-1.19-.34c-1.78-.48-2.65-1.46-2.65-3.1 0-1.95 1.5-3.18 3.87-3.18 1.05 0 2.09.21 2.91.66v2.26a5.53 5.53 0 0 0-2.96-.84c-.92 0-1.57.35-1.57 1.06.01.6.39.91 1.16 1.12l1.32.39c1.82.5 2.61 1.42 2.61 3.07 0 2.1-1.53 3.39-3.82 3.39a6.08 6.08 0 0 1-3.38-.9Zm12.22-10.02h2.83l3.67 10.72h-2.28l-.83-2.55h-4.02l-.83 2.55h-2.2l3.66-10.72Zm2.76 6.25-1.39-4.24-1.37 4.24h2.76Zm5.72-6.25h2.19v8.61h4.73v2.1h-6.92v-10.72Zm9.06 10.02v-2.31c.99.74 2.13 1.13 3.25 1.13s1.68-.45 1.68-1.23c0-.69-.39-.95-1.23-1.19l-1.19-.34c-1.78-.48-2.65-1.46-2.65-3.1 0-1.95 1.5-3.18 3.87-3.18 1.05 0 2.09.21 2.91.66v2.26a5.53 5.53 0 0 0-2.96-.84c-.92 0-1.57.35-1.57 1.06.01.6.39.91 1.16 1.12l1.32.39c1.82.5 2.61 1.42 2.61 3.07 0 2.1-1.53 3.39-3.82 3.39a6.08 6.08 0 0 1-3.38-.9ZM30 199.28h2.94l4.03 8.17v-8.17h2.07V210h-2.93l-4.03-8.17V210h-2.09v-10.72Zm14.7 0h2.83L51.2 210h-2.28l-.83-2.55h-4.02l-.83 2.55h-2.2l3.66-10.72Zm2.76 6.25-1.39-4.24-1.37 4.24h2.76Zm5.72-6.25h3.28l2.49 8.21 2.45-8.21h3.33V210h-2.04v-8.62L59.96 210h-2.07l-2.7-8.47V210h-2v-10.72Zm14.43 0h6.93v2.06h-4.79v2.23h4.45v2.06h-4.45v2.31h4.89V210h-7.03v-10.72Z" /><path d="M239.24 24.83h3.04c1.7 0 2.82 1 2.82 2.55 0 2.1-1.27 3.32-3.57 3.32h-1.97l-.71 3.3h-1.56l1.96-9.17Zm2.34 4.38c1.23 0 1.88-.58 1.88-1.68 0-.73-.49-1.2-1.48-1.2h-1.51l-.6 2.88h1.7Zm3.57 1.86c0-2.27 1.44-3.83 3.57-3.83 1.82 0 3.06 1.25 3.06 3.09 0 2.28-1.43 3.83-3.57 3.83-1.82 0-3.06-1.25-3.06-3.09Zm3.13 1.74c1.19 0 1.93-1.02 1.93-2.52 0-1.06-.62-1.69-1.56-1.69-1.19 0-1.93 1.02-1.93 2.52 0 1.06.62 1.69 1.56 1.69Zm4.74-5.41h1.49l.28 4.73 2.25-4.73h1.64l.23 4.77 2.25-4.77h1.56l-3.3 6.61h-1.62l-.25-5.04-2.42 5.04h-1.63l-.48-6.61Zm9.54 3.66c0-2.27 1.45-3.81 3.6-3.81 2 0 3.05 1.58 2.33 3.92h-4.46c0 1.1.81 1.68 2.05 1.68.8 0 1.45-.2 2.1-.59l-.31 1.46a4.2 4.2 0 0 1-2.04.44c-2.06 0-3.26-1.19-3.26-3.11Zm4.7-1.07c.12-.86-.31-1.46-1.22-1.46s-1.57.61-1.82 1.46h3.05Zm3.46-2.59h1.55l-.28 1.28c.81-1.7 2.56-1.36 2.77-1.29l-.35 1.46c-.18-.06-2.3-.63-2.82 1.68l-.74 3.48h-1.55l1.42-6.61Zm3.91 3.66c0-2.27 1.45-3.81 3.6-3.81 2 0 3.05 1.58 2.33 3.92h-4.46c0 1.1.81 1.68 2.05 1.68.8 0 1.45-.2 2.1-.59l-.31 1.46a4.2 4.2 0 0 1-2.04.44c-2.06 0-3.26-1.19-3.26-3.11Zm4.7-1.07c.12-.86-.31-1.46-1.22-1.46s-1.57.61-1.82 1.46h3.05Zm2.25 1.36c0-2.44 1.36-4.1 3.26-4.1 1 0 1.76.53 2.05 1.31l.79-3.72h1.55l-1.96 9.17h-1.55l.2-.92a2.15 2.15 0 0 1-1.92 1.08c-1.49 0-2.43-1.18-2.43-2.82Zm3 1.51c.88 0 1.51-.58 1.73-1.56l.17-.81c.24-1.1-.31-1.93-1.36-1.93-1.19 0-1.94 1.08-1.94 2.59 0 1.06.55 1.71 1.4 1.71Zm9.6-.01-.25 1.16h-1.55l1.96-9.17h1.55l-.73 3.47a2.35 2.35 0 0 1 1.99-1.05c1.49 0 2.35 1.16 2.35 2.76 0 2.52-1.36 4.16-3.21 4.16-.98 0-1.81-.53-2.1-1.32Zm1.83.01c1.16 0 1.87-1.06 1.87-2.61 0-1.04-.5-1.69-1.39-1.69s-1.52.56-1.73 1.55l-.17.79c-.24 1.14.34 1.97 1.42 1.97Zm5.68 1.16-1.04-6.62h1.52l.66 4.75 2.66-4.75h1.69l-5.31 9.13h-1.73l1.55-2.51Zm23.47-6.8c.91-.79 2.6-2.21 4.83-3.66a42.5 42.5 0 0 1 4.83 3.66c.23 1.18.62 3.36.75 6.01a43.12 43.12 0 0 1-5.58 2.35 42.54 42.54 0 0 1-5.58-2.35c.14-2.65.53-4.83.75-6.01Zm13.07-7.95s.82-.29 1.76-.45a14.9 14.9 0 0 0-9.53-3.81c.66.71 1.28 1.67 1.84 2.75 1.84.22 4.07.7 5.92 1.51Zm-2.71 18.36c-2.06-.4-4.05-.97-5.53-1.51a38.65 38.65 0 0 1-5.53 1.51c.12 1.5.35 3.04.76 4.58 0 0 1.54 1.82 4.78 2.8 3.23-.98 4.78-2.8 4.78-2.8.4-1.53.64-3.08.76-4.58Zm-13.77-18.37a22.3 22.3 0 0 1 5.93-1.51 12.4 12.4 0 0 1 1.84-2.75 14.97 14.97 0 0 0-9.53 3.81c.95.16 1.76.45 1.76.45Zm-4.72 8.77a25.74 25.74 0 0 0 3.58 2.94 37.48 37.48 0 0 1 4.08-4.04c.27-1.56.77-3.57 1.46-5.55a25.24 25.24 0 0 0-4.34-1.63s-2.35.42-4.81 2.74c-.77 3.29.04 5.54.04 5.54Zm25.92 0s.81-2.25.04-5.54c-2.46-2.31-4.81-2.74-4.81-2.74-1.53.42-2.99.99-4.34 1.63a37.79 37.79 0 0 1 1.46 5.55 37.44 37.44 0 0 1 4.08 4.04 25.86 25.86 0 0 0 3.58-2.94Zm-26.38.2s-.66-.56-1.27-1.3c-.7 3.34-.27 6.93 1.46 10.16.28-.93.8-1.94 1.46-2.97a22.32 22.32 0 0 1-1.66-5.88Zm8.24 14.27a22.07 22.07 0 0 1-4.27-4.38c-1.22.06-2.36 0-3.3-.22a14.91 14.91 0 0 0 8.07 6.34c-.34-.9-.5-1.75-.5-1.75Zm18.6-14.27s.66-.56 1.27-1.3c.7 3.34.27 6.93-1.46 10.16-.28-.93-.8-1.94-1.46-2.97a22.32 22.32 0 0 0 1.66-5.88Zm-8.24 14.27a22.07 22.07 0 0 0 4.27-4.38c1.22.06 2.36 0 3.3-.22a14.91 14.91 0 0 1-8.07 6.34c.34-.9.5-1.75.5-1.75Zm-5.18-25.66-4.12 2.45 1.26 3.91h5.72l1.26-3.91-4.12-2.45Zm-11.4 19.74 4.18 2.35 2.75-3.05-2.86-4.95-4.02.86-.06 4.79Zm22.79 0-.06-4.79-4.02-.86-2.86 4.95 2.75 3.05 4.18-2.35Z" style="fill:#00c1fa"/><path d="M106.67 109.1a304.9 304.9 0 0 0-3.72-10.89c5.04-5.53 35.28-40.74 24.54-68.91 10.57 10.67 8.19 28.85 3.59 41.95-4.79 13.14-13.43 26.48-24.4 37.84Zm30.89 20.82c-5.87 6.12-20.46 17.92-21.67 18.77a99.37 99.37 0 0 0 7.94 6.02 133.26 133.26 0 0 0 20.09-18.48 353.47 353.47 0 0 0-6.36-6.31Zm-29.65-16.74a380.9 380.9 0 0 1 3.13 11.56c-4.8-1.37-8.66-2.53-12.36-3.82a123.4 123.4 0 0 1-21.16 13.21l15.84 5.47c14.83-8.23 28.13-20.82 37.81-34.68 0 0 8.56-12.55 12.42-23.68 2.62-7.48 4.46-16.57 3.49-24.89-2.21-12.27-6.95-15.84-9.32-17.66 6.16 5.72 3.25 27.8-2.79 39.89-6.08 12.16-15.73 24.27-27.05 34.59Zm59.05-37.86c-.03 7.72-3.05 15.69-6.44 22.69 1.7 2.2 3.18 4.36 4.42 6.49 7.97-16.51 3.74-26.67 2.02-29.18ZM61.18 128.51l12.5 4.3a101.45 101.45 0 0 0 21.42-13.19 163.26 163.26 0 0 1-10.61-4.51 101.28 101.28 0 0 1-23.3 13.4Zm87.78-42.73c.86.77 5.44 5.18 6.75 6.59 6.39-16.61.78-28.86-1.27-30.56.72 8.05-2.02 16.51-5.48 23.98Zm-14.29 40.62-2.47-15.18a142.42 142.42 0 0 1-35.74 29.45c6.81 2.36 12.69 4.4 15.45 5.38a115.98 115.98 0 0 0 22.75-19.66Zm-42.62 34.73c4.48 2.93 12.94 4.24 18.8 1.23 6.03-3.84-.6-8.34-8.01-9.88-9.8-2.03-16.82 1.22-13.4 6.21.41.6 1.19 1.5 2.62 2.44m-1.84.4c-3.56-2.37-6.77-7.2-.23-10.08 10.41-3.43 28.39 3.2 24.99 9.22-.58 1.04-1.46 1.6-2.38 2.19h-.03v.02h-.03v.02h-.03c-7.04 3.65-17.06 2.13-22.3-1.36m5.48-3.86a4.94 4.94 0 0 0 5.06.49l1.35-.74-4.68-2.38-1.47.79c-.38.22-1.53.88-.26 1.84m-1.7.59c-2.35-1.57-.78-2.61-.02-3.11 1.09-.57 2.19-1.15 3.28-1.77 6.95 3.67 7.22 3.81 13.19 6.17l-1.38.81c-1.93-.78-4.52-1.82-6.42-2.68.86 1.4 1.99 3.27 2.9 4.64l-1.68.87c-.75-1.28-1.76-2.99-2.47-4.29-3.19 2.06-6.99-.36-7.42-.64" style="fill:url(#f2)"/><path d="M159.13 52.37C143.51 24.04 119.45 15 103.6 15c-11.92 0-25.97 5.78-36.84 13.17 9.54 4.38 21.86 15.96 22.02 16.11-7.94-3.05-17.83-6.72-33.23-7.87a135.1 135.1 0 0 0-19.77 20.38c.77 7.66 2.88 15.68 2.88 15.68-6.28-4.75-11.02-4.61-18 9.45-5.4 12.66-6.93 24.25-4.65 33.18 0 0 4.72 26.8 36.23 40.07-1.3-4.61-1.58-9.91-.93-15.73a87.96 87.96 0 0 1-15.63-9.87c.79-6.61 2.79-13.82 6-21.36 4.42-10.66 4.35-15.14 4.35-15.19.03.07 5.48 12.43 12.95 22.08 4.23-8.84 9.46-16.08 13.67-21.83l-3.77-6.75a143.73 143.73 0 0 1 18.19-18.75c2.05 1.07 4.79 2.47 6.84 3.58 8.68-7.27 19.25-14.05 30.56-18.29-7-11.49-16.02-19.27-16.02-19.27s27.7 2.74 42.02 15.69a25.8 25.8 0 0 1 8.65 2.89ZM28.58 107.52a70.1 70.1 0 0 0-2.74 12.52 55.65 55.65 0 0 1-6.19-8.84 69.17 69.17 0 0 1 2.65-12.1c1.77-5.31 3.35-5.91 5.86-2.23v-.05c2.14 3.07 1.81 6.14.42 10.7ZM61.69 72.2l-.05.05a221.85 221.85 0 0 1-7.77-18.1l.14-.14a194.51 194.51 0 0 1 18.56 6.98 144.44 144.44 0 0 0-10.88 11.22Zm54.84-47.38c-4.42.7-9.02 1.95-13.67 3.72a65.03 65.03 0 0 0-7.81-5.31 66.04 66.04 0 0 1 13.02-3.54c1.53-.19 6.23-.79 10.32 2.42v-.05c2.47 1.91.14 2.37-1.86 2.75Z" style="fill:url(#h)"/>'
));
}
/// @notice Transfer ownership to a new owner.
/// @param newOwner The address to transfer ownership to.
function transferOwnership(address newOwner) external onlyOwner {
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
/// @notice Write data to be accessed by a given file key.
/// @param key The key to access the written data.
/// @param data The data to be written.
function writeFile(uint256 key, string memory data) external onlyOwner {
files[key] = SSTORE2.write(bytes(data));
}
/// @notice Read data using a given file key.
/// @param key The key to access the stored data.
/// @return data The data stored at the given key.
function readFile(uint256 key) external view returns (string memory data) {
return string(SSTORE2.read(files[key]));
}
/// @notice Create or set a customization preset for renderers to use.
/// @param id The ID of the customization preset.
/// @param customizationData Data decoded by renderers used to render the SVG according to the preset.
function createCustomizationPreset(uint256 id, bytes memory customizationData) external onlyOwner {
customizationPresets[id] = customizationData;
}
/// @notice For crowdfund or party instances to set the customization preset they want to use.
/// @param id The ID of the customization preset.
function useCustomizationPreset(uint256 id) external {
getPresetFor[msg.sender] = id;
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8;
import "../vendor/solmate/ERC1155.sol";
import "../utils/EIP165.sol";
abstract contract ERC1155Receiver is EIP165, ERC1155TokenReceiverBase {
/// @inheritdoc EIP165
function supportsInterface(bytes4 interfaceId)
public
override
virtual
pure
returns (bool)
{
return super.supportsInterface(interfaceId) ||
interfaceId == type(ERC1155TokenReceiverBase).interfaceId;
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8;
import "./IERC721Receiver.sol";
import "../utils/EIP165.sol";
import "../vendor/solmate/ERC721.sol";
/// @notice Mixin for contracts that want to receive ERC721 tokens.
/// @dev Use this instead of solmate's ERC721TokenReceiver because the
/// compiler has issues when overriding EIP165/IERC721Receiver functions.
abstract contract ERC721Receiver is IERC721Receiver, EIP165, ERC721TokenReceiver {
/// @inheritdoc IERC721Receiver
function onERC721Received(address, address, uint256, bytes memory)
public
virtual
override(IERC721Receiver, ERC721TokenReceiver)
returns (bytes4)
{
return IERC721Receiver.onERC721Received.selector;
}
/// @inheritdoc EIP165
function supportsInterface(bytes4 interfaceId)
public
pure
virtual
override
returns (bool)
{
return EIP165.supportsInterface(interfaceId) ||
interfaceId == type(IERC721Receiver).interfaceId;
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8;
// Minimal ERC1155 interface.
interface IERC1155 {
event TransferSingle(
address indexed operator,
address indexed from,
address indexed to,
uint256 id,
uint256 amount
);
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] amounts
);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function setApprovalForAll(address operator, bool approved) external;
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
function balanceOf(address owner, uint256 tokenId) external view returns (uint256);
function isApprovedForAll(address owner, address spender) external view returns (bool);
function balanceOfBatch(address[] calldata owners, uint256[] calldata ids)
external
view
returns (uint256[] memory balances);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8;
// Minimal ERC20 interface.
interface IERC20 {
event Transfer(address indexed owner, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 allowance);
function transfer(address to, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
function approve(address spender, uint256 allowance) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8;
// Minimal ERC721 interface.
interface IERC721 {
event Transfer(address indexed owner, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed operator, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function transferFrom(address from, address to, uint256 tokenId) external;
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function approve(address operator, uint256 tokenId) external;
function setApprovalForAll(address operator, bool isApproved) external;
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function getApproved(uint256 tokenId) external view returns (address);
function isApprovedForAll(address owner, address operator) external view returns (bool);
function ownerOf(uint256 tokenId) external view returns (address);
function balanceOf(address owner) external view returns (uint256);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes memory data
) external returns (bytes4);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
abstract contract EIP165 {
/// @notice Query if a contract implements an interface.
/// @param interfaceId The interface identifier, as specified in ERC-165
/// @return `true` if the contract implements `interfaceId` and
/// `interfaceId` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceId)
public
virtual
pure
returns (bool)
{
return interfaceId == this.supportsInterface.selector;
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
// Base contract for all contracts intended to be delegatecalled into.
abstract contract Implementation {
error OnlyDelegateCallError();
error OnlyConstructorError();
address public immutable IMPL;
constructor() { IMPL = address(this); }
// Reverts if the current function context is not inside of a delegatecall.
modifier onlyDelegateCall() virtual {
if (address(this) == IMPL) {
revert OnlyDelegateCallError();
}
_;
}
// Reverts if the current function context is not inside of a constructor.
modifier onlyConstructor() {
uint256 codeSize;
assembly { codeSize := extcodesize(address()) }
if (codeSize != 0) {
revert OnlyConstructorError();
}
_;
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
import "../tokens/IERC20.sol";
// Compatibility helpers for ERC20s.
library LibERC20Compat {
error NotATokenError(IERC20 token);
error TokenTransferFailedError(IERC20 token, address to, uint256 amount);
// Perform an `IERC20.transfer()` handling non-compliant implementations.
function compatTransfer(IERC20 token, address to, uint256 amount)
internal
{
(bool s, bytes memory r) =
address(token).call(abi.encodeCall(IERC20.transfer, (to, amount)));
if (s) {
if (r.length == 0) {
uint256 cs;
assembly { cs := extcodesize(token) }
if (cs == 0) {
revert NotATokenError(token);
}
return;
}
if (abi.decode(r, (bool))) {
return;
}
}
revert TokenTransferFailedError(token, to, amount);
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
library LibRawResult {
// Revert with the data in `b`.
function rawRevert(bytes memory b)
internal
pure
{
assembly { revert(add(b, 32), mload(b)) }
}
// Return with the data in `b`.
function rawReturn(bytes memory b)
internal
pure
{
assembly { return(add(b, 32), mload(b)) }
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
library LibSafeCast {
error Uint256ToUint96CastOutOfRange(uint256 v);
error Uint256ToInt192CastOutOfRange(uint256 v);
error Int192ToUint96CastOutOfRange(int192 i192);
error Uint256ToInt128CastOutOfRangeError(uint256 u256);
error Uint256ToUint128CastOutOfRangeError(uint256 u256);
error Uint256ToUint40CastOutOfRangeError(uint256 u256);
function safeCastUint256ToUint96(uint256 v) internal pure returns (uint96) {
if (v > uint256(type(uint96).max)) {
revert Uint256ToUint96CastOutOfRange(v);
}
return uint96(v);
}
function safeCastUint256ToUint128(uint256 v) internal pure returns (uint128) {
if (v > uint256(type(uint128).max)) {
revert Uint256ToUint128CastOutOfRangeError(v);
}
return uint128(v);
}
function safeCastUint256ToInt192(uint256 v) internal pure returns (int192) {
if (v > uint256(uint192(type(int192).max))) {
revert Uint256ToInt192CastOutOfRange(v);
}
return int192(uint192(v));
}
function safeCastUint96ToInt192(uint96 v) internal pure returns (int192) {
return int192(uint192(v));
}
function safeCastInt192ToUint96(int192 i192) internal pure returns (uint96) {
if (i192 < 0 || i192 > int192(uint192(type(uint96).max))) {
revert Int192ToUint96CastOutOfRange(i192);
}
return uint96(uint192(i192));
}
function safeCastUint256ToInt128(uint256 x)
internal
pure
returns (int128)
{
if (x > uint256(uint128(type(int128).max))) {
revert Uint256ToInt128CastOutOfRangeError(x);
}
return int128(uint128(x));
}
function safeCastUint256ToUint40(uint256 x)
internal
pure
returns (uint40)
{
if (x > uint256(type(uint40).max)) {
revert Uint256ToUint40CastOutOfRangeError(x);
}
return uint40(x);
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
import "../utils/LibRawResult.sol";
abstract contract Multicall {
using LibRawResult for bytes;
/// @notice Perform multiple delegatecalls on ourselves.
function multicall(bytes[] calldata multicallData) external {
for (uint256 i; i < multicallData.length; ++i) {
(bool s, bytes memory r) = address(this).delegatecall(multicallData[i]);
if (!s) {
r.rawRevert();
}
}
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
import "./LibRawResult.sol";
interface IReadOnlyDelegateCall {
// Marked `view` so that `_readOnlyDelegateCall` can be `view` as well.
function delegateCallAndRevert(address impl, bytes memory callData)
external
view;
}
// Inherited by contracts to perform read-only delegate calls.
abstract contract ReadOnlyDelegateCall {
using LibRawResult for bytes;
// Delegatecall into implement and revert with the raw result.
function delegateCallAndRevert(address impl, bytes memory callData) external {
// Attempt to gate to only `_readOnlyDelegateCall()` invocations.
require(msg.sender == address(this));
(bool s, bytes memory r) = impl.delegatecall(callData);
// Revert with success status and return data.
abi.encode(s, r).rawRevert();
}
// Perform a `delegateCallAndRevert()` then return the raw result data.
function _readOnlyDelegateCall(address impl, bytes memory callData) internal view {
try IReadOnlyDelegateCall(address(this)).delegateCallAndRevert(impl, callData) {
// Should never happen.
assert(false);
}
catch (bytes memory r) {
(bool success, bytes memory resultData) = abi.decode(r, (bool, bytes));
if (!success) {
resultData.rawRevert();
}
resultData.rawReturn();
}
}
}// SPDX-License-Identifier: AGPL-3.0-only
// Based on solmate commit 1681dc505f4897ef636f0435d01b1aa027fdafaf (v6.4.0)
// @ https://github.com/Rari-Capital/solmate/blob/1681dc505f4897ef636f0435d01b1aa027fdafaf/src/tokens/ERC1155.sol
// Only modified to inherit IERC1155 and rename ERC1155TokenReceiver -> ERC1155TokenReceiverBase.
pragma solidity ^0.8;
import "../../tokens/IERC1155.sol";
/// @notice Minimalist and gas efficient standard ERC1155 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC1155.sol)
abstract contract ERC1155 is IERC1155 {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event URI(string value, uint256 indexed id);
/*//////////////////////////////////////////////////////////////
ERC1155 STORAGE
//////////////////////////////////////////////////////////////*/
mapping(address => mapping(uint256 => uint256)) public balanceOf;
mapping(address => mapping(address => bool)) public isApprovedForAll;
/*//////////////////////////////////////////////////////////////
METADATA LOGIC
//////////////////////////////////////////////////////////////*/
function uri(uint256 id) public view virtual returns (string memory);
/*//////////////////////////////////////////////////////////////
ERC1155 LOGIC
//////////////////////////////////////////////////////////////*/
function setApprovalForAll(address operator, bool approved) public virtual {
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) public virtual {
require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");
balanceOf[from][id] -= amount;
balanceOf[to][id] += amount;
emit TransferSingle(msg.sender, from, to, id, amount);
require(
to.code.length == 0
? to != address(0)
: ERC1155TokenReceiverBase(to).onERC1155Received(msg.sender, from, id, amount, data) ==
ERC1155TokenReceiverBase.onERC1155Received.selector,
"UNSAFE_RECIPIENT"
);
}
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) public virtual {
require(ids.length == amounts.length, "LENGTH_MISMATCH");
require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");
// Storing these outside the loop saves ~15 gas per iteration.
uint256 id;
uint256 amount;
for (uint256 i; i < ids.length; ) {
id = ids[i];
amount = amounts[i];
balanceOf[from][id] -= amount;
balanceOf[to][id] += amount;
// An array can't have a total length
// larger than the max uint256 value.
unchecked {
++i;
}
}
emit TransferBatch(msg.sender, from, to, ids, amounts);
require(
to.code.length == 0
? to != address(0)
: ERC1155TokenReceiverBase(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) ==
ERC1155TokenReceiverBase.onERC1155BatchReceived.selector,
"UNSAFE_RECIPIENT"
);
}
function balanceOfBatch(address[] calldata owners, uint256[] calldata ids)
public
view
virtual
returns (uint256[] memory balances)
{
require(owners.length == ids.length, "LENGTH_MISMATCH");
balances = new uint256[](owners.length);
// Unchecked because the only math done is incrementing
// the array index counter which cannot possibly overflow.
unchecked {
for (uint256 i; i < owners.length; ++i) {
balances[i] = balanceOf[owners[i]][ids[i]];
}
}
}
/*//////////////////////////////////////////////////////////////
ERC165 LOGIC
//////////////////////////////////////////////////////////////*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return
interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155
interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(
address to,
uint256 id,
uint256 amount,
bytes memory data
) internal virtual {
balanceOf[to][id] += amount;
emit TransferSingle(msg.sender, address(0), to, id, amount);
require(
to.code.length == 0
? to != address(0)
: ERC1155TokenReceiverBase(to).onERC1155Received(msg.sender, address(0), id, amount, data) ==
ERC1155TokenReceiverBase.onERC1155Received.selector,
"UNSAFE_RECIPIENT"
);
}
function _batchMint(
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {
uint256 idsLength = ids.length; // Saves MLOADs.
require(idsLength == amounts.length, "LENGTH_MISMATCH");
for (uint256 i; i < idsLength; ) {
balanceOf[to][ids[i]] += amounts[i];
// An array can't have a total length
// larger than the max uint256 value.
unchecked {
++i;
}
}
emit TransferBatch(msg.sender, address(0), to, ids, amounts);
require(
to.code.length == 0
? to != address(0)
: ERC1155TokenReceiverBase(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) ==
ERC1155TokenReceiverBase.onERC1155BatchReceived.selector,
"UNSAFE_RECIPIENT"
);
}
function _batchBurn(
address from,
uint256[] memory ids,
uint256[] memory amounts
) internal virtual {
uint256 idsLength = ids.length; // Saves MLOADs.
require(idsLength == amounts.length, "LENGTH_MISMATCH");
for (uint256 i; i < idsLength; ) {
balanceOf[from][ids[i]] -= amounts[i];
// An array can't have a total length
// larger than the max uint256 value.
unchecked {
++i;
}
}
emit TransferBatch(msg.sender, from, address(0), ids, amounts);
}
function _burn(
address from,
uint256 id,
uint256 amount
) internal virtual {
balanceOf[from][id] -= amount;
emit TransferSingle(msg.sender, from, address(0), id, amount);
}
}
/// @notice A generic interface for a contract which properly accepts ERC1155 tokens.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC1155.sol)
abstract contract ERC1155TokenReceiverBase {
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes calldata
) external virtual returns (bytes4) {
return ERC1155TokenReceiverBase.onERC1155Received.selector;
}
function onERC1155BatchReceived(
address,
address,
uint256[] calldata,
uint256[] calldata,
bytes calldata
) external virtual returns (bytes4) {
return ERC1155TokenReceiverBase.onERC1155BatchReceived.selector;
}
}// SPDX-License-Identifier: AGPL-3.0-only
// Based on solmate commit 1681dc505f4897ef636f0435d01b1aa027fdafaf (v6.4.0)
// @ https://github.com/Rari-Capital/solmate/blob/1681dc505f4897ef636f0435d01b1aa027fdafaf/src/tokens/ERC1155.sol
// Only modified to inherit IERC721 and EIP165.
pragma solidity >=0.8.0;
// NOTE: Only modified to inherit IERC20 and EIP165
import "../../tokens/IERC721.sol";
import "../../utils/EIP165.sol";
/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721 is IERC721, EIP165 {
/*//////////////////////////////////////////////////////////////
METADATA STORAGE/LOGIC
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
function tokenURI(uint256 id) public /* view */ virtual returns (string memory);
/*//////////////////////////////////////////////////////////////
ERC721 BALANCE/OWNER STORAGE
//////////////////////////////////////////////////////////////*/
mapping(uint256 => address) internal _ownerOf;
mapping(address => uint256) internal _balanceOf;
function ownerOf(uint256 id) public view virtual returns (address owner) {
require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
}
function balanceOf(address owner) public view virtual returns (uint256) {
require(owner != address(0), "ZERO_ADDRESS");
return _balanceOf[owner];
}
/*//////////////////////////////////////////////////////////////
ERC721 APPROVAL STORAGE
//////////////////////////////////////////////////////////////*/
mapping(uint256 => address) public getApproved;
mapping(address => mapping(address => bool)) public isApprovedForAll;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(string memory _name, string memory _symbol) {
name = _name;
symbol = _symbol;
}
/*//////////////////////////////////////////////////////////////
ERC721 LOGIC
//////////////////////////////////////////////////////////////*/
function approve(address spender, uint256 id) public virtual {
address owner = _ownerOf[id];
require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");
getApproved[id] = spender;
emit Approval(owner, spender, id);
}
function setApprovalForAll(address operator, bool approved) public virtual {
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
function transferFrom(
address from,
address to,
uint256 id
) public virtual {
require(from == _ownerOf[id], "WRONG_FROM");
require(to != address(0), "INVALID_RECIPIENT");
require(
msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],
"NOT_AUTHORIZED"
);
// Underflow of the sender's balance is impossible because we check for
// ownership above and the recipient's balance can't realistically overflow.
unchecked {
_balanceOf[from]--;
_balanceOf[to]++;
}
_ownerOf[id] = to;
delete getApproved[id];
emit Transfer(from, to, id);
}
function safeTransferFrom(
address from,
address to,
uint256 id
) public virtual {
transferFrom(from, to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
function safeTransferFrom(
address from,
address to,
uint256 id,
bytes calldata data
) public virtual {
transferFrom(from, to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
/*//////////////////////////////////////////////////////////////
ERC165 LOGIC
//////////////////////////////////////////////////////////////*/
function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) {
// NOTE: modified from original to call super.
return super.supportsInterface(interfaceId) ||
interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address to, uint256 id) internal virtual {
require(to != address(0), "INVALID_RECIPIENT");
require(_ownerOf[id] == address(0), "ALREADY_MINTED");
// Counter overflow is incredibly unrealistic.
unchecked {
_balanceOf[to]++;
}
_ownerOf[id] = to;
emit Transfer(address(0), to, id);
}
function _burn(uint256 id) internal virtual {
address owner = _ownerOf[id];
require(owner != address(0), "NOT_MINTED");
// Ownership check above ensures no underflow.
unchecked {
_balanceOf[owner]--;
}
delete _ownerOf[id];
delete getApproved[id];
emit Transfer(owner, address(0), id);
}
/*//////////////////////////////////////////////////////////////
INTERNAL SAFE MINT LOGIC
//////////////////////////////////////////////////////////////*/
function _safeMint(address to, uint256 id) internal virtual {
_mint(to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
function _safeMint(
address to,
uint256 id,
bytes memory data
) internal virtual {
_mint(to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
}
/// @notice A generic interface for a contract which properly accepts ERC721 tokens.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721TokenReceiver {
function onERC721Received(
address,
address,
uint256,
bytes calldata
) external virtual returns (bytes4) {
return ERC721TokenReceiver.onERC721Received.selector;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)
pragma solidity ^0.8.0;
import "../utils/introspection/IERC165.sol";
/**
* @dev Interface for the NFT Royalty Standard.
*
* A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
* support for royalty payments across all NFT marketplaces and ecosystem participants.
*
* _Available since v4.5._
*/
interface IERC2981 is IERC165 {
/**
* @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
* exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
*/
function royaltyInfo(uint256 tokenId, uint256 salePrice)
external
view
returns (address receiver, uint256 royaltyAmount);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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 IERC165 {
/**
* @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);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Read and write to persistent storage at a fraction of the cost.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SSTORE2.sol)
/// @author Modified from 0xSequence (https://github.com/0xSequence/sstore2/blob/master/contracts/SSTORE2.sol)
library SSTORE2 {
uint256 internal constant DATA_OFFSET = 1; // We skip the first byte as it's a STOP opcode to ensure the contract can't be called.
/*//////////////////////////////////////////////////////////////
WRITE LOGIC
//////////////////////////////////////////////////////////////*/
function write(bytes memory data) internal returns (address pointer) {
// Prefix the bytecode with a STOP opcode to ensure it cannot be called.
bytes memory runtimeCode = abi.encodePacked(hex"00", data);
bytes memory creationCode = abi.encodePacked(
//---------------------------------------------------------------------------------------------------------------//
// Opcode | Opcode + Arguments | Description | Stack View //
//---------------------------------------------------------------------------------------------------------------//
// 0x60 | 0x600B | PUSH1 11 | codeOffset //
// 0x59 | 0x59 | MSIZE | 0 codeOffset //
// 0x81 | 0x81 | DUP2 | codeOffset 0 codeOffset //
// 0x38 | 0x38 | CODESIZE | codeSize codeOffset 0 codeOffset //
// 0x03 | 0x03 | SUB | (codeSize - codeOffset) 0 codeOffset //
// 0x80 | 0x80 | DUP | (codeSize - codeOffset) (codeSize - codeOffset) 0 codeOffset //
// 0x92 | 0x92 | SWAP3 | codeOffset (codeSize - codeOffset) 0 (codeSize - codeOffset) //
// 0x59 | 0x59 | MSIZE | 0 codeOffset (codeSize - codeOffset) 0 (codeSize - codeOffset) //
// 0x39 | 0x39 | CODECOPY | 0 (codeSize - codeOffset) //
// 0xf3 | 0xf3 | RETURN | //
//---------------------------------------------------------------------------------------------------------------//
hex"60_0B_59_81_38_03_80_92_59_39_F3", // Returns all code in the contract except for the first 11 (0B in hex) bytes.
runtimeCode // The bytecode we want the contract to have after deployment. Capped at 1 byte less than the code size limit.
);
assembly {
// Deploy a new contract with the generated creation code.
// We start 32 bytes into the code to avoid copying the byte length.
pointer := create(0, add(creationCode, 32), mload(creationCode))
}
require(pointer != address(0), "DEPLOYMENT_FAILED");
}
/*//////////////////////////////////////////////////////////////
READ LOGIC
//////////////////////////////////////////////////////////////*/
function read(address pointer) internal view returns (bytes memory) {
return readBytecode(pointer, DATA_OFFSET, pointer.code.length - DATA_OFFSET);
}
function read(address pointer, uint256 start) internal view returns (bytes memory) {
start += DATA_OFFSET;
return readBytecode(pointer, start, pointer.code.length - start);
}
function read(
address pointer,
uint256 start,
uint256 end
) internal view returns (bytes memory) {
start += DATA_OFFSET;
end += DATA_OFFSET;
require(pointer.code.length >= end, "OUT_OF_BOUNDS");
return readBytecode(pointer, start, end - start);
}
/*//////////////////////////////////////////////////////////////
INTERNAL HELPER LOGIC
//////////////////////////////////////////////////////////////*/
function readBytecode(
address pointer,
uint256 start,
uint256 size
) private view returns (bytes memory data) {
assembly {
// Get a pointer to some free memory.
data := mload(0x40)
// Update the free memory pointer to prevent overriding our data.
// We use and(x, not(31)) as a cheaper equivalent to sub(x, mod(x, 32)).
// Adding 31 to size and running the result through the logic above ensures
// the memory pointer remains word-aligned, following the Solidity convention.
mstore(0x40, add(data, and(add(add(size, 32), 31), not(31))))
// Store the size of the data in the first 32 byte chunk of free memory.
mstore(data, size)
// Copy the code into memory right after the 32 bytes we used to store the size.
extcodecopy(pointer, add(data, 32), start, size)
}
}
}{
"remappings": [
"ds-test/=lib/solmate/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"openzeppelin/=lib/openzeppelin-contracts/",
"solmate/=lib/solmate/src/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IGlobals","name":"globals","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"voter","type":"address"}],"name":"AlreadyVotedError","type":"error"},{"inputs":[],"name":"BadPreciousListError","type":"error"},{"inputs":[{"internalType":"bytes32","name":"proposalHash","type":"bytes32"},{"internalType":"bytes32","name":"actualHash","type":"bytes32"}],"name":"BadProposalHashError","type":"error"},{"inputs":[{"internalType":"enum PartyGovernance.ProposalStatus","name":"status","type":"uint8"}],"name":"BadProposalStatusError","type":"error"},{"inputs":[{"internalType":"uint40","name":"maxExecutableTime","type":"uint40"},{"internalType":"uint40","name":"timestamp","type":"uint40"}],"name":"ExecutionTimeExceededError","type":"error"},{"inputs":[{"internalType":"int192","name":"i192","type":"int192"}],"name":"Int192ToUint96CastOutOfRange","type":"error"},{"inputs":[{"internalType":"uint16","name":"bps","type":"uint16"}],"name":"InvalidBpsError","type":"error"},{"inputs":[],"name":"InvalidDelegateError","type":"error"},{"inputs":[],"name":"InvalidNewHostError","type":"error"},{"inputs":[],"name":"MismatchedPreciousListLengths","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"NotATokenError","type":"error"},{"inputs":[],"name":"OnlyActiveMemberError","type":"error"},{"inputs":[],"name":"OnlyConstructorError","type":"error"},{"inputs":[],"name":"OnlyDelegateCallError","type":"error"},{"inputs":[{"internalType":"address","name":"actual","type":"address"},{"internalType":"address","name":"expected","type":"address"}],"name":"OnlyMintAuthorityError","type":"error"},{"inputs":[{"internalType":"address","name":"notDao","type":"address"},{"internalType":"address","name":"partyDao","type":"address"}],"name":"OnlyPartyDaoError","type":"error"},{"inputs":[{"internalType":"address","name":"notDao","type":"address"},{"internalType":"address","name":"partyDao","type":"address"}],"name":"OnlyPartyDaoOrHostError","type":"error"},{"inputs":[],"name":"OnlyPartyHostError","type":"error"},{"inputs":[],"name":"OnlyWhenEmergencyActionsAllowedError","type":"error"},{"inputs":[],"name":"OnlyWhenEnabledError","type":"error"},{"inputs":[{"internalType":"uint40","name":"currentTime","type":"uint40"},{"internalType":"uint40","name":"cancelTime","type":"uint40"}],"name":"ProposalCannotBeCancelledYetError","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenTransferFailedError","type":"error"},{"inputs":[{"internalType":"uint256","name":"v","type":"uint256"}],"name":"Uint256ToInt192CastOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"v","type":"uint256"}],"name":"Uint256ToUint96CastOutOfRange","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","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":[{"indexed":false,"internalType":"enum ITokenDistributor.TokenType","name":"tokenType","type":"uint8"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"DistributionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"amountEth","type":"uint256"}],"name":"EmergencyExecute","type":"event"},{"anonymous":false,"inputs":[],"name":"EmergencyExecuteDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldHost","type":"address"},{"indexed":false,"internalType":"address","name":"newHost","type":"address"}],"name":"HostStatusTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"}],"name":"ProposalAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"address","name":"executor","type":"address"},{"indexed":false,"internalType":"bytes","name":"nextProgressData","type":"bytes"}],"name":"ProposalExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalPassed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"address","name":"host","type":"address"}],"name":"ProposalVetoed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"address","name":"proposer","type":"address"},{"components":[{"internalType":"uint40","name":"maxExecutableTime","type":"uint40"},{"internalType":"uint40","name":"cancelDelay","type":"uint40"},{"internalType":"bytes","name":"proposalData","type":"bytes"}],"indexed":false,"internalType":"struct PartyGovernance.Proposal","name":"proposal","type":"tuple"}],"name":"Proposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","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":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"delegate","type":"address"}],"name":"VotingPowerDelegated","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"IMPL","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"abdicate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPartyHost","type":"address"}],"name":"abdicate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"snapIndex","type":"uint256"}],"name":"accept","outputs":[{"internalType":"uint256","name":"totalVotes","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"components":[{"internalType":"uint40","name":"maxExecutableTime","type":"uint40"},{"internalType":"uint40","name":"cancelDelay","type":"uint40"},{"internalType":"bytes","name":"proposalData","type":"bytes"}],"internalType":"struct PartyGovernance.Proposal","name":"proposal","type":"tuple"}],"name":"cancel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"impl","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"name":"delegateCallAndRevert","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"}],"name":"delegateVotingPower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"delegationsByVoter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"disableEmergencyExecute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum ITokenDistributor.TokenType","name":"tokenType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"distribute","outputs":[{"components":[{"internalType":"enum ITokenDistributor.TokenType","name":"tokenType","type":"uint8"},{"internalType":"uint256","name":"distributionId","type":"uint256"},{"internalType":"contract ITokenDistributorParty","name":"party","type":"address"},{"internalType":"address payable","name":"feeRecipient","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint128","name":"memberSupply","type":"uint128"},{"internalType":"uint128","name":"fee","type":"uint128"}],"internalType":"struct ITokenDistributor.DistributionInfo","name":"distInfo","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"targetAddress","type":"address"},{"internalType":"bytes","name":"targetCallData","type":"bytes"},{"internalType":"uint256","name":"amountEth","type":"uint256"}],"name":"emergencyExecute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"emergencyExecuteDisabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"components":[{"internalType":"uint40","name":"maxExecutableTime","type":"uint40"},{"internalType":"uint40","name":"cancelDelay","type":"uint40"},{"internalType":"bytes","name":"proposalData","type":"bytes"}],"internalType":"struct PartyGovernance.Proposal","name":"proposal","type":"tuple"},{"internalType":"contract IERC721[]","name":"preciousTokens","type":"address[]"},{"internalType":"uint256[]","name":"preciousTokenIds","type":"uint256[]"},{"internalType":"bytes","name":"progressData","type":"bytes"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"feeBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeRecipient","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"voter","type":"address"},{"internalType":"uint40","name":"timestamp","type":"uint40"}],"name":"findVotingPowerSnapshotIndex","outputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getDistributionShareOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGovernanceValues","outputs":[{"components":[{"internalType":"uint40","name":"voteDuration","type":"uint40"},{"internalType":"uint40","name":"executionDelay","type":"uint40"},{"internalType":"uint16","name":"passThresholdBps","type":"uint16"},{"internalType":"uint96","name":"totalVotingPower","type":"uint96"}],"internalType":"struct PartyGovernance.GovernanceValues","name":"gv","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProposalExecutionEngine","outputs":[{"internalType":"contract IProposalExecutionEngine","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint40","name":"maxExecutableTime","type":"uint40"},{"internalType":"uint40","name":"cancelDelay","type":"uint40"},{"internalType":"bytes","name":"proposalData","type":"bytes"}],"internalType":"struct PartyGovernance.Proposal","name":"proposal","type":"tuple"}],"name":"getProposalHash","outputs":[{"internalType":"bytes32","name":"proposalHash","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"getProposalStateInfo","outputs":[{"internalType":"enum PartyGovernance.ProposalStatus","name":"status","type":"uint8"},{"components":[{"internalType":"uint40","name":"proposedTime","type":"uint40"},{"internalType":"uint40","name":"passedTime","type":"uint40"},{"internalType":"uint40","name":"executedTime","type":"uint40"},{"internalType":"uint40","name":"completedTime","type":"uint40"},{"internalType":"uint96","name":"votes","type":"uint96"}],"internalType":"struct PartyGovernance.ProposalStateValues","name":"values","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"voter","type":"address"},{"internalType":"uint40","name":"timestamp","type":"uint40"}],"name":"getVotingPowerAt","outputs":[{"internalType":"uint96","name":"votingPower","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"voter","type":"address"},{"internalType":"uint40","name":"timestamp","type":"uint40"},{"internalType":"uint256","name":"snapIndex","type":"uint256"}],"name":"getVotingPowerAt","outputs":[{"internalType":"uint96","name":"votingPower","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"components":[{"internalType":"address[]","name":"hosts","type":"address[]"},{"internalType":"uint40","name":"voteDuration","type":"uint40"},{"internalType":"uint40","name":"executionDelay","type":"uint40"},{"internalType":"uint16","name":"passThresholdBps","type":"uint16"},{"internalType":"uint96","name":"totalVotingPower","type":"uint96"},{"internalType":"uint16","name":"feeBps","type":"uint16"},{"internalType":"address payable","name":"feeRecipient","type":"address"}],"internalType":"struct PartyGovernance.GovernanceOpts","name":"governance","type":"tuple"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"customizationPresetId","type":"uint256"}],"internalType":"struct Party.PartyOptions","name":"options","type":"tuple"},{"internalType":"contract IERC721[]","name":"preciousTokens","type":"address[]"},{"internalType":"uint256[]","name":"preciousTokenIds","type":"uint256[]"},{"internalType":"address","name":"mintAuthority","type":"address"}],"internalType":"struct Party.PartyInitData","name":"initData","type":"tuple"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isHost","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastProposalId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"votingPower","type":"uint256"},{"internalType":"address","name":"delegate","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintAuthority","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintedVotingPower","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"preciousListHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint40","name":"maxExecutableTime","type":"uint40"},{"internalType":"uint40","name":"cancelDelay","type":"uint40"},{"internalType":"bytes","name":"proposalData","type":"bytes"}],"internalType":"struct PartyGovernance.Proposal","name":"proposal","type":"tuple"},{"internalType":"uint256","name":"latestSnapIndex","type":"uint256"}],"name":"propose","outputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","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":"owner","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":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenCount","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"veto","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"votingPowerByTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60e06040523480156200001157600080fd5b5060405162005f5838038062005f58833981016040819052620000349162000095565b604080516020808201835260008083528351918201909352918252306080526001600160a01b03831660a052829160086200007083826200016c565b5060096200007f82826200016c565b5050506001600160a01b031660c0525062000238565b600060208284031215620000a857600080fd5b81516001600160a01b0381168114620000c057600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620000f257607f821691505b6020821081036200011357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200016757600081815260208120601f850160051c81016020861015620001425750805b601f850160051c820191505b8181101562000163578281556001016200014e565b5050505b505050565b81516001600160401b03811115620001885762000188620000c7565b620001a081620001998454620000dd565b8462000119565b602080601f831160018114620001d85760008415620001bf5750858301515b600019600386901b1c1916600185901b17855562000163565b600085815260208120601f198616915b828110156200020957888601518255948401946001909101908401620001e8565b5085821015620002285787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c051615c4f620003096000396000818161346a01526135430152600081816115b101528181611b4a01528181611bfc0152818161249e0152818161291901528181612a0c01528181612cc301526143540152600081816106b601528181610d72015281816111fc01528181611390015281816115140152818161168f015281816117cd01528181611a2c01528181611df001528181611fd7015281816121860152818161220c01528181612539015281816127ea015281816129b40152612d9a0152615c4f6000f3fe6080604052600436106103035760003560e01c806378cfabac11610190578063caf6aa4b116100dc578063e985e9c511610095578063f23a6e611161006f578063f23a6e6114610b19578063f3ff955a14610b46578063fa3dd61e14610b66578063fea44a5614610b935761030a565b8063e985e9c514610a9b578063eb2931b714610ad6578063f0689b4714610b065761030a565b8063caf6aa4b146109d4578063cd36324914610a01578063cf67f34414610a21578063d7faa26214610a56578063e6f26d9a14610a6c578063e8a3d48514610a865761030a565b8063a25632fd11610149578063b9fa1e9211610123578063b9fa1e9214610937578063bc197c8114610957578063c43683a114610986578063c87b56dd146109b45761030a565b8063a25632fd14610822578063b20240ee14610842578063b88d4fde146109175761030a565b806378cfabac146107665780638a415268146107865780639340b21e146107a657806395d89b41146107c65780639f181b5e146107db578063a22cb465146108025761030a565b806333b9d8c41161024f57806346904840116102085780636352211e116101e25780636352211e146106d85780636fd44cfd146106f857806370a082311461073057806374cb3041146107505761030a565b8063469048401461064757806352a702b51461066e57806356973ee5146106a45761030a565b806333b9d8c4146105925780633846b6d2146105a75780633c481576146105c75780633e4011b9146105e75780634121c9311461060757806342842e0e146106275761030a565b8063150b7a02116102bc57806324a9d8531161029657806324a9d853146104f85780632a55205a1461052b578063305a07211461056a578063314e99a21461057d5761030a565b8063150b7a02146104745780631d28dec7146104b857806323b872dd146104d85761030a565b806301ffc9a71461036157806306fdde0314610396578063081812fc146103b85780630935847914610406578063095ea7b3146104345780630d4d1513146104545761030a565b3661030a57005b34801561031657600080fd5b5061035f610322610ba8565b6000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610bd692505050565b005b34801561036d57600080fd5b5061038161037c366004614690565b610c9d565b60405190151581526020015b60405180910390f35b3480156103a257600080fd5b506103ab610cd8565b60405161038d91906146fd565b3480156103c457600080fd5b506103ee6103d3366004614710565b600c602052600090815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161038d565b34801561041257600080fd5b50610426610421366004614729565b610d66565b60405190815260200161038d565b34801561044057600080fd5b5061035f61044f36600461476b565b6110d0565b34801561046057600080fd5b5061042661046f366004614797565b6111b2565b34801561048057600080fd5b5061049f61048f3660046148e6565b630a85bd0160e11b949350505050565b6040516001600160e01b0319909116815260200161038d565b3480156104c457600080fd5b5061035f6104d3366004614710565b611356565b3480156104e457600080fd5b5061035f6104f3366004614951565b61150a565b34801561050457600080fd5b5060005461051890610100900461ffff1681565b60405161ffff909116815260200161038d565b34801561053757600080fd5b5061054b610546366004614729565b61157f565b604080516001600160a01b03909316835260208301919091520161038d565b61035f6105783660046149d3565b611598565b34801561058957600080fd5b5061035f611786565b34801561059e57600080fd5b506103ee61181f565b3480156105b357600080fd5b506104266105c2366004614a43565b61182e565b3480156105d357600080fd5b5061035f6105e2366004614bf2565b6118df565b3480156105f357600080fd5b5061035f610602366004614dc4565b611932565b34801561061357600080fd5b5061035f610622366004614e13565b6119ce565b34801561063357600080fd5b5061035f610642366004614951565b611de6565b34801561065357600080fd5b506000546103ee90630100000090046001600160a01b031681565b34801561067a57600080fd5b506103ee610689366004614e60565b6004602052600090815260409020546001600160a01b031681565b3480156106b057600080fd5b506103ee7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106e457600080fd5b506103ee6106f3366004614710565b611e3a565b34801561070457600080fd5b50600f54610718906001600160601b031681565b6040516001600160601b03909116815260200161038d565b34801561073c57600080fd5b5061042661074b366004614e60565b611e45565b34801561075c57600080fd5b5061042660025481565b34801561077257600080fd5b50610426610781366004614710565b611ea8565b34801561079257600080fd5b506107186107a1366004614a43565b611ee9565b3480156107b257600080fd5b50600e546103ee906001600160a01b031681565b3480156107d257600080fd5b506103ab611eff565b3480156107e757600080fd5b50600e5461071890600160a01b90046001600160601b031681565b34801561080e57600080fd5b5061035f61081d366004614e8b565b611f0c565b34801561082e57600080fd5b5061042661083d366004614f3f565b611f78565b34801561084e57600080fd5b506108c7604080516080810182526000808252602082018190529181018290526060810191909152506040805160808101825260055464ffffffffff8082168352600160281b8204166020830152600160501b810461ffff1692820192909252600160601b9091046001600160601b0316606082015290565b60405161038d9190600060808201905064ffffffffff8084511683528060208501511660208401525061ffff60408401511660408301526001600160601b03606084015116606083015292915050565b34801561092357600080fd5b5061035f610932366004614f83565b61217c565b34801561094357600080fd5b5061035f610952366004614e60565b6121d2565b34801561096357600080fd5b5061049f610972366004615039565b63bc197c8160e01b98975050505050505050565b34801561099257600080fd5b506109a66109a1366004614710565b612314565b60405161038d929190615121565b3480156109c057600080fd5b506103ab6109cf366004614710565b6123bb565b3480156109e057600080fd5b506104266109ef366004614710565b60106020526000908152604090205481565b348015610a0d57600080fd5b50610718610a1c36600461517d565b6123d9565b348015610a2d57600080fd5b50610426610a3c3660046151bb565b604081018051805160208201208252606090922091905290565b348015610a6257600080fd5b5061042660015481565b348015610a7857600080fd5b506000546103819060ff1681565b348015610a9257600080fd5b506103ab612417565b348015610aa757600080fd5b50610381610ab63660046151f7565b600d60209081526000928352604080842090915290825290205460ff1681565b348015610ae257600080fd5b50610381610af1366004614e60565b60036020526000908152604090205460ff1681565b61035f610b14366004615225565b612434565b348015610b2557600080fd5b5061049f610b343660046152ea565b63f23a6e6160e01b9695505050505050565b348015610b5257600080fd5b5061035f610b61366004614e60565b6127e0565b348015610b7257600080fd5b50610b86610b81366004615372565b61286e565b60405161038d91906153a2565b348015610b9f57600080fd5b5061035f612caa565b7feb054550c406db3b89dc7016369a66aff0ce40188133281942b92e6188c6b1ef546001600160a01b031690565b604051633e4011b960e01b81523090633e4011b990610bfb9085908590600401615416565b60006040518083038186803b158015610c1357600080fd5b505afa925050508015610c24575060015b610c91573d808015610c52576040519150601f19603f3d011682016040523d82523d6000602084013e610c57565b606091505b5060008082806020019051810190610c6f919061547f565b9150915081610c8157610c8181612e10565b610c8a81612e18565b5050505050565b610c996154c5565b5050565b6000610ca882612e20565b80610cb75750610cb782612e3a565b80610cd257506001600160e01b0319821663152a902d60e11b145b92915050565b60088054610ce5906154db565b80601f0160208091040260200160405190810160405280929190818152602001828054610d11906154db565b8015610d5e5780601f10610d3357610100808354040283529160200191610d5e565b820191906000526020600020905b815481529060010190602001808311610d4157829003601f168201915b505050505081565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610db15760405163ea2cbbd560e01b815260040160405180910390fd5b6000838152600660209081526040808320815160a081018352815464ffffffffff8082168352600160281b8204811695830195909552600160501b8104851693820193909352600160781b83049093166060840152600160a01b9091046001600160601b0316608083015291610e2682612e7d565b90506001816007811115610e3c57610e3c6150f7565b14158015610e5c57506003816007811115610e5957610e596150f7565b14155b8015610e7a57506004816007811115610e7757610e776150f7565b14155b15610ea35780604051630821641d60e21b8152600401610e9a9190615515565b60405180910390fd5b5033600090815260028301602052604090205460ff1615610ed957604051630b517d8f60e41b8152336004820152602401610e9a565b3360008181526002840160205260408120805460ff1916600190811790915583519192610f11929091610f0b91615539565b876123d9565b90508082608001818151610f259190615557565b6001600160601b03908116909152835185546020860151604080880151606089015160808a0151909616600160a01b026001600160a01b0364ffffffffff978816600160781b0264ffffffffff60781b19938916600160501b029390931669ffffffffffffffffffff60501b19958916600160281b0269ffffffffffffffffffff1990971698909716979097179490941792909216939093171792909216919091178555517fea45672a2d92b09ff2dd48aa67615f8b5c79d7808b7282fc026a24e00283f78d915061101f908890339085909283526001600160a01b039190911660208301526001600160601b0316604082015260600190565b60405180910390a1602082015164ffffffffff16158015611069575060808201516005546110699190600160601b81046001600160601b031690600160501b900461ffff16613002565b156110ba57825469ffffffffff00000000001916600160281b4264ffffffffff160217835560405186907fe36f8b7448daff4a52e2945db0d1d7a436279cc1d527a45c27835dcbd27f336d90600090a25b50608001516001600160601b0316949350505050565b6000818152600a60205260409020546001600160a01b03163381148061111957506001600160a01b0381166000908152600d6020908152604080832033845290915290205460ff165b6111565760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610e9a565b6000828152600c602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b600e546000906001600160a01b03163381146111f257604051633a33dca760e11b81523360048201526001600160a01b0382166024820152604401610e9a565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361123b5760405163ea2cbbd560e01b815260040160405180910390fd5b600e54600f546005546001600160601b03600160a01b90930483169291821691600160601b90910416600061126f8861303e565b90506001600160601b0381166112858484615577565b6001600160601b031610156112a15761129e8383615577565b90505b6112ab8184615557565b92506112b8846001615557565b600e80546001600160601b03928316600160a01b81026001600160a01b0392831617909255600f80548785166bffffffffffffffffffffffff1990911617905560008281526010602090815260408083209587169095558d8316825260049052929092205490975016801561132b578097505b61133f8a6001600160601b0384168a61306f565b6113498a88613191565b5050505050509392505050565b3360009081526003602052604090205460ff1661138657604051633641391960e21b815260040160405180910390fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036113cf5760405163ea2cbbd560e01b815260040160405180910390fd5b6000818152600660209081526040808320815160a081018352815464ffffffffff8082168352600160281b8204811695830195909552600160501b8104851693820193909352600160781b83049093166060840152600160a01b9091046001600160601b031660808301529161144482612e7d565b9050600181600781111561145a5761145a6150f7565b1415801561147a57506003816007811115611477576114776150f7565b14155b801561149857506004816007811115611495576114956150f7565b14155b156114b85780604051630821641d60e21b8152600401610e9a9190615515565b5081546001600160a01b03166001600160a01b031917825560405133815283907fc2131db10d833d6b93ae553fa450ea0f6c0c2dfb0160cb3309468bf72718f3eb9060200160405180910390a2505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036115535760405163ea2cbbd560e01b815260040160405180910390fd5b60008181526010602052604090205461156f908490849061325d565b61157a83838361328a565b505050565b60008061158a613451565b5060009050805b9250929050565b604051635c9fcd8560e11b8152600b60048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b93f9b0a90602401602060405180830381865afa158015611600573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116249190615597565b9050336001600160a01b038216146116605760405163520b6b7560e01b81523360048201526001600160a01b0382166024820152604401610e9a565b5060005460ff1615611685576040516304e71fd360e31b815260040160405180910390fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036116ce5760405163ea2cbbd560e01b815260040160405180910390fd5b600080856001600160a01b03168386866040516116ec9291906155b4565b60006040518083038185875af1925050503d8060008114611729576040519150601f19603f3d011682016040523d82523d6000602084013e61172e565b606091505b5091509150816117415761174181612e10565b7f66cf5924183d7d44caa75d9268a169d7c1422fef43848743d5e1ba32d5833acf8686868660405161177694939291906155ed565b60405180910390a1505050505050565b600e546001600160a01b03163381146117c357604051633a33dca760e11b81523360048201526001600160a01b0382166024820152604401610e9a565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361180c5760405163ea2cbbd560e01b815260040160405180910390fd5b50600e80546001600160a01b0319169055565b6000611829610ba8565b905090565b6001600160a01b03821660009081526007602052604081208054825b818110156118bb57600060026118608484615623565b61186a919061564c565b90508564ffffffffff1684828154811061188657611886615660565b60009182526020909120015464ffffffffff1611156118a7578092506118b5565b6118b2816001615623565b91505b5061184a565b81156118d1576118cc600183615676565b6118d5565b6000195b9695505050505050565b303b8015611900576040516304a41c4d60e51b815260040160405180910390fd5b81516020808201516040808401516060808601519551948801519288015190880151610c9996949592949391906134e7565b33301461193e57600080fd5b600080836001600160a01b0316836040516119599190615689565b600060405180830381855af49150503d8060008114611994576040519150601f19603f3d011682016040523d82523d6000602084013e611999565b606091505b50915091506119c882826040516020016119b49291906156a5565b604051602081830303815290604052612e10565b50505050565b60006119d93361361f565b905080604001516001600160601b03166000148015611a03575060208101516001600160601b0316155b15611a215760405163e6de1cdd60e01b815260040160405180910390fd5b506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611a6b5760405163ea2cbbd560e01b815260040160405180910390fd5b6000828152600660205260409020611a8f611a85836156c0565b82600101546136e2565b6040805160a081018252825464ffffffffff8082168352600160281b820481166020840152600160501b8204811693830193909352600160781b81049092166060820152600160a01b9091046001600160601b031660808201526000611af482612e7d565b90506005816007811115611b0a57611b0a6150f7565b14611b2a5780604051630821641d60e21b8152600401610e9a9190615515565b506000611b3d60408501602086016156cc565b64ffffffffff16905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663441abbac600f6040518263ffffffff1660e01b8152600401611b9791815260200190565b602060405180830381865afa158015611bb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd891906156e7565b604051631106aeeb60e21b8152601760048201529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063441abbac90602401602060405180830381865afa158015611c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6791906156e7565b90508115611c7b5781831115611c7b578192505b8015611c8d5780831015611c8d578092505b600083856040015164ffffffffff16611ca69190615623565b905080421015611cda576040516303861c4b60e41b815264ffffffffff428116600483015282166024820152604401610e9a565b5050835464ffffffffff60781b1916600160781b648000000000421764ffffffffff1602178455506000905080611d0f610ba8565b6001600160a01b031686604051602401611d2b91815260200190565b60408051601f198184030181529181526020820180516001600160e01b031663e0a8f6f560e01b17905251611d609190615689565b600060405180830381855af49150503d8060008114611d9b576040519150601f19603f3d011682016040523d82523d6000602084013e611da0565b606091505b509150915081611db357611db381612e10565b505060405184907f416e669c63d9a3a5e36ee7cc7e2104b8db28ccd286aa18966e98fa230c73b08c90600090a250505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611e2f5760405163ea2cbbd560e01b815260040160405180910390fd5b61157a838383613721565b6000610cd2826137f1565b60006001600160a01b038216611e8c5760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606401610e9a565b506001600160a01b03166000908152600b602052604090205490565b600554600090600160601b90046001600160601b0316600083815260106020526040902054611edf90670de0b6b3a7640000615700565b610cd2919061564c565b6000611ef883836000196123d9565b9392505050565b60098054610ce5906154db565b336000818152600d602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b600080611f843361361f565b905080604001516001600160601b03166000148015611fae575060208101516001600160601b0316155b15611fcc5760405163e6de1cdd60e01b815260040160405180910390fd5b506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036120165760405163ea2cbbd560e01b815260040160405180910390fd5b60026000815461202590615717565b91829055506040805160a08101825264ffffffffff4216815260006020820181905291810182905260608101829052608081019190915290915061207d84604081018051805160208201208252606090922091905290565b600083815260066020908152604091829020600181019390935583518354918501518584015160608701516080909701516001600160601b0316600160a01b026001600160a01b0364ffffffffff988916600160781b0264ffffffffff60781b19938a16600160501b029390931669ffffffffffffffffffff60501b19948a16600160281b0269ffffffffffffffffffff1990971699909516989098179490941791909116919091171793909316929092179055517fea77d064c7d953e57748855e7b0751ea190d1df7505615a4e39336d4d548f6889061216390839033908790615730565b60405180910390a16121758183610d66565b5092915050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036121c55760405163ea2cbbd560e01b815260040160405180910390fd5b610c8a8585858585613848565b3360009081526003602052604090205460ff1661220257604051633641391960e21b815260040160405180910390fd5b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361224b5760405163ea2cbbd560e01b815260040160405180910390fd5b6001600160a01b038116156122b8576001600160a01b03811660009081526003602052604090205460ff16156122945760405163640c1a3360e01b815260040160405180910390fd5b6001600160a01b0381166000908152600360205260409020805460ff191660011790555b33600081815260036020908152604091829020805460ff1916905581519283526001600160a01b038416908301527fddffcdb3bb07c5efc18b0918cf4e3e88c7d42cc05156cdadb2ec12c3b5ff892f910160405180910390a150565b6040805160a081018252600080825260208201819052918101829052606081018290526080810182905250600082815260066020908152604091829020825160a081018452905464ffffffffff8082168352600160281b8204811693830193909352600160501b8104831693820193909352600160781b83049091166060820152600160a01b9091046001600160601b031660808201526123b481612e7d565b9150915091565b60606123c5613451565b505060408051602081019091526000815290565b6000806123e7858585613906565b905080602001518160600151612401578160400151612404565b60005b61240e9190615557565b95945050505050565b6060612421613451565b5060408051602081019091526000815290565b600061243f3361361f565b905080604001516001600160601b03166000148015612469575060208101516001600160601b0316155b156124875760405163e6de1cdd60e01b815260040160405180910390fd5b506040516331a1aa3360e11b8152601560048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636343546690602401602060405180830381865afa1580156124ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612511919061577f565b1561252f57604051632fb3e88560e01b815260040160405180910390fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036125785760405163ea2cbbd560e01b815260040160405180910390fd5b600088815260066020526040902060018101546125969089906136e2565b6040805160a081018252825464ffffffffff8082168352600160281b820481166020840152600160501b8204811693830193909352600160781b81049092166060820152600160a01b9091046001600160601b0316608082015260006125fb82612e7d565b90506004816007811115612611576126116150f7565b141580156126315750600581600781111561262e5761262e6150f7565b14155b156126515780604051630821641d60e21b8152600401610e9a9190615515565b6004816007811115612665576126656150f7565b036126ca57428a6000015164ffffffffff1610156126ab578951604051632f7e600560e21b815264ffffffffff9182166004820152429091166024820152604401610e9a565b825464ffffffffff60501b1916600160501b4264ffffffffff16021783555b88516020908102818b0120600090815289518202828b0120909152604090206001541461270a57604051633b43666f60e01b815260040160405180910390fd5b825464ffffffffff60781b1916600160781b4264ffffffffff160217835560006127bb8c8c8c8c61273a88613a81565b8d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613aba92505050565b9050806127d257835464ffffffffff60781b191684555b505050505050505050505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036128295760405163ea2cbbd560e01b815260040160405180910390fd5b6128353360008361306f565b6040516001600160a01b0382169033907fbfa9be947969a7d4f47eceedb207379702a5e9e8b82ec09d564da75195f8689e90600090a350565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c08101919091523330146129035760006128b93361361f565b905080604001516001600160601b031660001480156128e3575060208101516001600160601b0316155b156129015760405163e6de1cdd60e01b815260040160405180910390fd5b505b6040516331a1aa3360e11b8152601560048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636343546690602401602060405180830381865afa158015612968573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298c919061577f565b156129aa57604051632fb3e88560e01b815260040160405180910390fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036129f35760405163ea2cbbd560e01b815260040160405180910390fd5b604051635c9fcd8560e11b8152600c60048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b93f9b0a90602401602060405180830381865afa158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190615597565b90507fdda962f630bf2f85c8412f305206a4f363688481dd632689f88ad7022e4cc233858585604051612ab49392919061579c565b60405180910390a160008054630100000081046001600160a01b03169161010090910461ffff1690876001811115612aee57612aee6150f7565b03612b7b57604051631d1972a760e11b81523060048201526001600160a01b03838116602483015261ffff83166044830152841690633a32e54e90479060640160e06040518083038185885af1158015612b4c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612b7191906157db565b9350505050611ef8565b6001876001811115612b8f57612b8f6150f7565b14612b9c57612b9c6154c5565b6040516370a0823160e01b8152306004820152612c1b9084906001600160a01b038916906370a0823190602401602060405180830381865afa158015612be6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c0a91906156e7565b6001600160a01b0389169190613c06565b60405163eedaf00d60e01b81526001600160a01b038781166004830152306024830152838116604483015261ffff8316606483015284169063eedaf00d9060840160e0604051808303816000875af1158015612c7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c9f91906157db565b979650505050505050565b604051635c9fcd8560e11b8152600b60048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b93f9b0a90602401602060405180830381865afa158015612d12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d369190615597565b9050336001600160a01b03821614801590612d6157503360009081526003602052604090205460ff16155b15612d905760405163e670248160e01b81523360048201526001600160a01b0382166024820152604401610e9a565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003612dd95760405163ea2cbbd560e01b815260040160405180910390fd5b6000805460ff191660011781556040517f447e75484d6bdb571b4a92ae14018db7b6dd41f3f02360690c554e1d48f46f879190a150565b805160208201fd5b805160208201f35b6000612e2b82613d38565b80610cd25750610cd282613d6e565b6000612e4582612e20565b80612e6057506380ac58cd60e01b6001600160e01b03198316145b80610cd25750506001600160e01b031916635b5e139f60e01b1490565b805160009064ffffffffff168103612e9757506000919050565b604082015164ffffffffff1615612eec57816060015164ffffffffff16600003612ec357506005919050565b64800000000080836060015164ffffffffff161603612ee457506007919050565b506006919050565b6001600160601b03801682608001516001600160601b031603612f1157506002919050565b6040805160808101825260055464ffffffffff8082168352600160281b82048116602080850191909152600160501b830461ffff1694840194909452600160601b9091046001600160601b031660608301529184015142921615612fcc578164ffffffffff1681602001518560200151612f8b919061588b565b64ffffffffff1611612fa1575060049392505050565b612fb384608001518260600151613d99565b15612fc2575060049392505050565b5060039392505050565b8051845164ffffffffff841691612fe29161588b565b64ffffffffff1611612ff8575060029392505050565b5060019392505050565b60008161ffff16836001600160601b0316856001600160601b031661271061302a9190615700565b613034919061564c565b1015949350505050565b60006001600160601b0382111561306b57604051636f55e21560e11b815260048101839052602401610e9a565b5090565b600061307a8461361f565b6001600160a01b038086166000908152600460205260409020549192501680156130a457806130a6565b845b90506001600160a01b038316156130bd57826130bf565b805b9250600060405180608001604052804264ffffffffff16815260200184602001516001600160601b031681526020016131218761310f87604001516001600160601b03166001600160601b031690565b61311991906158a9565b60170b613dcc565b6001600160601b031681526001600160a01b038681169089161415602090910152905061314e8682613e0d565b6001600160a01b03868116600090815260046020526040902080546001600160a01b0319169186169190911790556131898683868685613fe6565b505050505050565b61319b8282614194565b6001600160a01b0382163b15806132415750604051630a85bd0160e11b80825233600483015260006024830181905260448301849052608060648401526084830152906001600160a01b0384169063150b7a029060a4016020604051808303816000875af1158015613211573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061323591906158d6565b6001600160e01b031916145b610c995760405162461bcd60e51b8152600401610e9a906158f3565b60006132688261429f565b905061327e846132778361591d565b600061306f565b6119c88382600061306f565b6000818152600a60205260409020546001600160a01b038481169116146132e05760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b6044820152606401610e9a565b6001600160a01b03821661332a5760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610e9a565b336001600160a01b038416148061336457506001600160a01b0383166000908152600d6020908152604080832033845290915290205460ff165b8061338557506000818152600c60205260409020546001600160a01b031633145b6133c25760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610e9a565b6001600160a01b038084166000818152600b60209081526040808320805460001901905593861680835284832080546001019055858352600a825284832080546001600160a01b03199081168317909155600c90925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b604051635c9fcd8560e11b81526004808201526134dd907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b93f9b0a90602401602060405180830381865afa1580156134b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103229190615597565b6134e56154c5565b565b6134f28484846142cc565b60086134fe8882615986565b50600961350b8782615986565b50600e80546001600160a01b0319166001600160a01b038316179055841561361657604051635c9fcd8560e11b8152601660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b93f9b0a90602401602060405180830381865afa158015613592573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135b69190615597565b6001600160a01b031663fc9968df866040518263ffffffff1660e01b81526004016135e391815260200190565b600060405180830381600087803b1580156135fd57600080fd5b505af1158015613611573d6000803e3d6000fd5b505050505b50505050505050565b6040805160808101825260008082526020808301829052828401829052606083018290526001600160a01b03851682526007905291909120805480156136db578161366b600183615676565b8154811061367b5761367b615660565b600091825260209182902060408051608081018252929091015464ffffffffff81168352600160281b81046001600160601b0390811694840194909452600160881b810490931690820152600160e81b90910460ff161515606082015292505b5050919050565b60408201805180516020820120825260608420915280821461157a57604051630267877160e11b81526004810182905260248101839052604401610e9a565b61372c83838361150a565b6001600160a01b0382163b15806137d55750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af11580156137a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c991906158d6565b6001600160e01b031916145b61157a5760405162461bcd60e51b8152600401610e9a906158f3565b6000818152600a60205260409020546001600160a01b0316806138435760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b6044820152606401610e9a565b919050565b61385385858561150a565b6001600160a01b0384163b15806138ea5750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a029061389b9033908a90899089908990600401615a45565b6020604051808303816000875af11580156138ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138de91906158d6565b6001600160e01b031916145b610c8a5760405162461bcd60e51b8152600401610e9a906158f3565b6040805160808101825260008082526020808301829052828401829052606083018290526001600160a01b0387168252600790529190912080548015613a7857808410801561398057508464ffffffffff1682858154811061396a5761396a615660565b60009182526020909120015464ffffffffff1611155b80156139d35750613992600182615676565b8414806139d3575064ffffffffff8516826139ae866001615623565b815481106139be576139be615660565b60009182526020909120015464ffffffffff16115b15613a51578184815481106139ea576139ea615660565b600091825260209182902060408051608081018252929091015464ffffffffff81168352600160281b81046001600160601b0390811694840194909452600160881b810490931690820152600160e81b90910460ff16151560608201529250611ef8915050565b613a5b868661182e565b93506000198414613a78578184815481106139ea576139ea615660565b50509392505050565b6080810151600554600091613aa591600160601b90046001600160601b0316613d99565b15613ab257506001919050565b506000919050565b6000806040518060e001604052808a8152602001896040015181526020018581526020018481526020018681526020018881526020018781525090506060600080613b03610ba8565b6001600160a01b031684604051602401613b1d9190615ab4565b60408051601f198184030181529181526020820180516001600160e01b031663a7c8a3f960e01b17905251613b529190615689565b600060405180830381855af49150503d8060008114613b8d576040519150601f19603f3d011682016040523d82523d6000602084013e613b92565b606091505b509150915081613ba557613ba581612e10565b80806020019051810190613bb99190615b94565b92505050897fc98fbf8f20b11b050a9541d12aee1c11fcd31e8e42975cc885fb3d33a6accc823383604051613bef929190615416565b60405180910390a251159998505050505050505050565b6040516001600160a01b03838116602483015260448201839052600091829186169060640160408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b17905251613c609190615689565b6000604051808303816000865af19150503d8060008114613c9d576040519150601f19603f3d011682016040523d82523d6000602084013e613ca2565b606091505b50915091508115613d05578051600003613ce557843b600081900361318957604051639fe23a3960e01b81526001600160a01b0387166004820152602401610e9a565b80806020019051810190613cf9919061577f565b15613d05575050505050565b604051631702a98760e11b81526001600160a01b0380871660048301528516602482015260448101849052606401610e9a565b60006301ffc9a760e01b6001600160e01b031983161480610cd257506001600160e01b03198216630a85bd0160e11b1492915050565b6000613d7982613d38565b80610cd257506001600160e01b03198216630271189760e51b1492915050565b60008082613da985612710615bc8565b613db39190615bf3565b61270f6001600160601b03919091161015949350505050565b6000808260170b1280613de957506001600160601b03601783900b135b1561306b576040516394e08f6160e01b8152601783900b6004820152602401610e9a565b6001600160a01b038216600090815260076020526040902080548015613f5c57600082613e3b600184615676565b81548110613e4b57613e4b615660565b600091825260209182902060408051608081018252919092015464ffffffffff8082168084526001600160601b03600160281b8404811696850196909652600160881b83049095169383019390935260ff600160e81b90910416151560608201528651909350169003613f5a578383613ec5600185615676565b81548110613ed557613ed5615660565b60009182526020918290208351910180549284015160408501516060909501511515600160e81b0260ff60e81b196001600160601b03968716600160881b0216600160881b600160f01b031996909216600160281b026001600160881b031990951664ffffffffff909416939093179390931793909316919091171790555050505050565b505b50805460018101825560009182526020918290208351910180549284015160408501516060909501511515600160e81b0260ff60e81b196001600160601b03968716600160881b0216600160881b600160f01b031996909216600160281b026001600160881b031990951664ffffffffff9094169390931793909317939093169190911717905550565b6001600160a01b038316158061400357506001600160a01b038416155b156140215760405163e5ec2d2560e01b815260040160405180910390fd5b846001600160a01b0316846001600160a01b0316141580156140555750826001600160a01b0316846001600160a01b031614155b156140cf5760006140658561361f565b9050600060405180608001604052804264ffffffffff168152602001856040015184602001516140959190615577565b6001600160601b0316815260200183604001516001600160601b031681526020018360600151151581525090506140cc8682613e0d565b50505b846001600160a01b0316836001600160a01b031614610c8a5760006140f38461361f565b905060008260400151826020015161410b9190615557565b9050856001600160a01b0316856001600160a01b0316036141385760408401516141359082615577565b90505b600060405180608001604052804264ffffffffff168152602001836001600160601b0316815260200184604001516001600160601b0316815260200184606001511515815250905061418a8682613e0d565b5050505050505050565b6001600160a01b0382166141de5760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610e9a565b6000818152600a60205260409020546001600160a01b0316156142345760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b6044820152606401610e9a565b6001600160a01b0382166000818152600b6020908152604080832080546001019055848352600a90915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006001600160bf1b0382111561306b5760405163e9a5989b60e01b815260048101839052602401610e9a565b6127108360a0015161ffff1611156143035760a08301516040516323dd0d6d60e11b815261ffff9091166004820152602401610e9a565b612710836060015161ffff16111561433a5760608301516040516323dd0d6d60e11b815261ffff9091166004820152602401610e9a565b604051635c9fcd8560e11b8152600260048201526143dc907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b93f9b0a90602401602060405180830381865afa1580156143a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143c79190615597565b6040518060200160405280600081525061454e565b604080516080808201835260208681015164ffffffffff9081168085528886015190911691840182905260608089015161ffff908116968601879052938901516001600160601b031694018490526005805469ffffffffffffffffffff1916909117600160281b909202919091176dffffffffffffffffffffffffffff60501b1916600160501b9094026bffffffffffffffffffffffff60601b191693909317600160601b9092029190911790915560a08401516000805460c0870151610100600160b81b031990911661010093909416929092026301000000600160b81b0319169290921763010000006001600160a01b03909216919091021790556144e3828261462f565b60005b8351518110156119c8576001600360008660000151848151811061450c5761450c615660565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905561454781615717565b90506144e6565b7feb054550c406db3b89dc7016369a66aff0ce40188133281942b92e6188c6b1ef80546001600160a01b031981166001600160a01b03858116918217845560405192169160009182916145a79085908890602401615416565b60408051601f198184030181529181526020820180516001600160e01b031663347d5e2560e21b179052516145dc9190615689565b600060405180830381855af49150503d8060008114614617576040519150601f19603f3d011682016040523d82523d6000602084013e61461c565b606091505b5091509150816131895761318981612e10565b8051825114614651576040516357cc2fc760e01b815260040160405180910390fd5b815160209081028184012060009081528251820282840120909152604090206001555050565b6001600160e01b03198116811461468d57600080fd5b50565b6000602082840312156146a257600080fd5b8135611ef881614677565b60005b838110156146c85781810151838201526020016146b0565b50506000910152565b600081518084526146e98160208601602086016146ad565b601f01601f19169290920160200192915050565b602081526000611ef860208301846146d1565b60006020828403121561472257600080fd5b5035919050565b6000806040838503121561473c57600080fd5b50508035926020909101359150565b6001600160a01b038116811461468d57600080fd5b80356138438161474b565b6000806040838503121561477e57600080fd5b82356147898161474b565b946020939093013593505050565b6000806000606084860312156147ac57600080fd5b83356147b78161474b565b92506020840135915060408401356147ce8161474b565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715614811576148116147d9565b60405290565b60405160e081016001600160401b0381118282101715614811576148116147d9565b604051601f8201601f191681016001600160401b0381118282101715614861576148616147d9565b604052919050565b60006001600160401b03821115614882576148826147d9565b50601f01601f191660200190565b600082601f8301126148a157600080fd5b81356148b46148af82614869565b614839565b8181528460208386010111156148c957600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080608085870312156148fc57600080fd5b84356149078161474b565b935060208501356149178161474b565b92506040850135915060608501356001600160401b0381111561493957600080fd5b61494587828801614890565b91505092959194509250565b60008060006060848603121561496657600080fd5b83356149718161474b565b925060208401356149818161474b565b929592945050506040919091013590565b60008083601f8401126149a457600080fd5b5081356001600160401b038111156149bb57600080fd5b60208301915083602082850101111561159157600080fd5b600080600080606085870312156149e957600080fd5b84356149f48161474b565b935060208501356001600160401b03811115614a0f57600080fd5b614a1b87828801614992565b9598909750949560400135949350505050565b803564ffffffffff8116811461384357600080fd5b60008060408385031215614a5657600080fd5b8235614a618161474b565b9150614a6f60208401614a2e565b90509250929050565b60006001600160401b03821115614a9157614a916147d9565b5060051b60200190565b600082601f830112614aac57600080fd5b81356020614abc6148af83614a78565b82815260059290921b84018101918181019086841115614adb57600080fd5b8286015b84811015614aff578035614af28161474b565b8352918301918301614adf565b509695505050505050565b803561ffff8116811461384357600080fd5b80356001600160601b038116811461384357600080fd5b600082601f830112614b4457600080fd5b81356020614b546148af83614a78565b82815260059290921b84018101918181019086841115614b7357600080fd5b8286015b84811015614aff578035614b8a8161474b565b8352918301918301614b77565b600082601f830112614ba857600080fd5b81356020614bb86148af83614a78565b82815260059290921b84018101918181019086841115614bd757600080fd5b8286015b84811015614aff5780358352918301918301614bdb565b60006020808385031215614c0557600080fd5b82356001600160401b0380821115614c1c57600080fd5b9084019060808287031215614c3057600080fd5b614c386147ef565b823582811115614c4757600080fd5b830160808189031215614c5957600080fd5b614c616147ef565b813584811115614c7057600080fd5b820160e0818b031215614c8257600080fd5b614c8a614817565b813586811115614c9957600080fd5b614ca58c828501614a9b565b825250614cb3888301614a2e565b888201526040614cc4818401614a2e565b818301526060614cd5818501614b0a565b81840152614ce560808501614b1c565b6080840152614cf660a08501614b0a565b60a0840152614d0760c08501614760565b60c084015282855289860135935087841115614d2257600080fd5b614d2e8d858801614890565b8a86015281860135935087841115614d4557600080fd5b614d518d858801614890565b858301529485013585850152838652878901359487861115614d7257600080fd5b614d7e8d878b01614b33565b8a880152818901359950878a1115614d9557600080fd5b614da18d8b8b01614b97565b82880152614db0818a01614760565b9087015250939a9950505050505050505050565b60008060408385031215614dd757600080fd5b8235614de28161474b565b915060208301356001600160401b03811115614dfd57600080fd5b614e0985828601614890565b9150509250929050565b60008060408385031215614e2657600080fd5b8235915060208301356001600160401b03811115614e4357600080fd5b830160608186031215614e5557600080fd5b809150509250929050565b600060208284031215614e7257600080fd5b8135611ef88161474b565b801515811461468d57600080fd5b60008060408385031215614e9e57600080fd5b8235614ea98161474b565b91506020830135614e5581614e7d565b600060608284031215614ecb57600080fd5b604051606081016001600160401b038282108183111715614eee57614eee6147d9565b81604052829350614efe85614a2e565b8352614f0c60208601614a2e565b60208401526040850135915080821115614f2557600080fd5b50614f3285828601614890565b6040830152505092915050565b60008060408385031215614f5257600080fd5b82356001600160401b03811115614f6857600080fd5b614f7485828601614eb9565b95602094909401359450505050565b600080600080600060808688031215614f9b57600080fd5b8535614fa68161474b565b94506020860135614fb68161474b565b93506040860135925060608601356001600160401b03811115614fd857600080fd5b614fe488828901614992565b969995985093965092949392505050565b60008083601f84011261500757600080fd5b5081356001600160401b0381111561501e57600080fd5b6020830191508360208260051b850101111561159157600080fd5b60008060008060008060008060a0898b03121561505557600080fd5b88356150608161474b565b975060208901356150708161474b565b965060408901356001600160401b038082111561508c57600080fd5b6150988c838d01614ff5565b909850965060608b01359150808211156150b157600080fd5b6150bd8c838d01614ff5565b909650945060808b01359150808211156150d657600080fd5b506150e38b828c01614992565b999c989b5096995094979396929594505050565b634e487b7160e01b600052602160045260246000fd5b6008811061511d5761511d6150f7565b9052565b60c0810161512f828561510d565b64ffffffffff808451166020840152806020850151166040840152806040850151166060840152806060850151166080840152506001600160601b0360808401511660a08301529392505050565b60008060006060848603121561519257600080fd5b833561519d8161474b565b92506151ab60208501614a2e565b9150604084013590509250925092565b6000602082840312156151cd57600080fd5b81356001600160401b038111156151e357600080fd5b6151ef84828501614eb9565b949350505050565b6000806040838503121561520a57600080fd5b82356152158161474b565b91506020830135614e558161474b565b60008060008060008060008060c0898b03121561524157600080fd5b8835975060208901356001600160401b038082111561525f57600080fd5b61526b8c838d01614eb9565b985060408b013591508082111561528157600080fd5b61528d8c838d01614b33565b975060608b01359150808211156152a357600080fd5b6152af8c838d01614b97565b965060808b01359150808211156152c557600080fd5b6152d18c838d01614992565b909650945060a08b01359150808211156150d657600080fd5b60008060008060008060a0878903121561530357600080fd5b863561530e8161474b565b9550602087013561531e8161474b565b9450604087013593506060870135925060808701356001600160401b0381111561534757600080fd5b61535389828a01614992565b979a9699509497509295939492505050565b6002811061468d57600080fd5b60008060006060848603121561538757600080fd5b833561497181615365565b6002811061511d5761511d6150f7565b600060e0820190506153b5828451615392565b60208301516020830152604083015160018060a01b038082166040850152806060860151166060850152806080860151166080850152505060a08301516001600160801b0380821660a08501528060c08601511660c0850152505092915050565b6001600160a01b03831681526040602082018190526000906151ef908301846146d1565b600082601f83011261544b57600080fd5b81516154596148af82614869565b81815284602083860101111561546e57600080fd5b6151ef8260208301602087016146ad565b6000806040838503121561549257600080fd5b825161549d81614e7d565b60208401519092506001600160401b038111156154b957600080fd5b614e098582860161543a565b634e487b7160e01b600052600160045260246000fd5b600181811c908216806154ef57607f821691505b60208210810361550f57634e487b7160e01b600052602260045260246000fd5b50919050565b60208101610cd2828461510d565b634e487b7160e01b600052601160045260246000fd5b64ffffffffff82811682821603908082111561217557612175615523565b6001600160601b0381811683821601908082111561217557612175615523565b6001600160601b0382811682821603908082111561217557612175615523565b6000602082840312156155a957600080fd5b8151611ef88161474b565b8183823760009101908152919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b038516815260606020820181905260009061561290830185876155c4565b905082604083015295945050505050565b80820180821115610cd257610cd2615523565b634e487b7160e01b600052601260045260246000fd5b60008261565b5761565b615636565b500490565b634e487b7160e01b600052603260045260246000fd5b81810381811115610cd257610cd2615523565b6000825161569b8184602087016146ad565b9190910192915050565b82151581526040602082015260006151ef60408301846146d1565b6000610cd23683614eb9565b6000602082840312156156de57600080fd5b611ef882614a2e565b6000602082840312156156f957600080fd5b5051919050565b8082028115828204841417610cd257610cd2615523565b60006001820161572957615729615523565b5060010190565b83815260018060a01b038316602082015260606040820152600064ffffffffff808451166060840152806020850151166080840152506040830151606060a08401526118d560c08401826146d1565b60006020828403121561579157600080fd5b8151611ef881614e7d565b606081016157aa8286615392565b6001600160a01b0393909316602082015260400152919050565b80516001600160801b038116811461384357600080fd5b600060e082840312156157ed57600080fd5b60405160e081018181106001600160401b038211171561580f5761580f6147d9565b604052825161581d81615365565b81526020838101519082015260408301516158378161474b565b6040820152606083015161584a8161474b565b6060820152608083015161585d8161474b565b608082015261586e60a084016157c4565b60a082015261587f60c084016157c4565b60c08201529392505050565b64ffffffffff81811683821601908082111561217557612175615523565b601781810b9083900b016001600160bf1b0381136001600160bf1b031982121715610cd257610cd2615523565b6000602082840312156158e857600080fd5b8151611ef881614677565b60208082526010908201526f155394d0519157d49150d2541251539560821b604082015260600190565b6000601782900b600160bf1b810161593757615937615523565b60000392915050565b601f82111561157a57600081815260208120601f850160051c810160208610156159675750805b601f850160051c820191505b8181101561318957828155600101615973565b81516001600160401b0381111561599f5761599f6147d9565b6159b3816159ad84546154db565b84615940565b602080601f8311600181146159e857600084156159d05750858301515b600019600386901b1c1916600185901b178555613189565b600085815260208120601f198616915b82811015615a17578886015182559484019460019091019084016159f8565b5085821015615a355787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b0386811682528516602082015260408101849052608060608201819052600090612c9f90830184866155c4565b600081518084526020808501945080840160005b83811015615aa957815187529582019590820190600101615a8d565b509495945050505050565b600060208083528351818401528084015160e06040850152615ada6101008501826146d1565b90506040850151601f1980868403016060870152615af883836146d1565b92506060870151915080868403016080870152615b1583836146d1565b608088015160a088810191909152880151878203830160c08901528051808352908601945060009350908501905b80841015615b6c5784516001600160a01b03168252938501936001939093019290850190615b43565b5060c08801519450818782030160e0880152615b888186615a79565b98975050505050505050565b600060208284031215615ba657600080fd5b81516001600160401b03811115615bbc57600080fd5b6151ef8482850161543a565b6001600160601b03818116838216028082169190828114615beb57615beb615523565b505092915050565b60006001600160601b0380841680615c0d57615c0d615636565b9216919091049291505056fea26469706673582212200be9ace9cf91e260ff128ec1313e3ba1d8ac3af33e7e0d741297e426349a86d664736f6c634300081100330000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade
Deployed Bytecode
0x6080604052600436106103035760003560e01c806378cfabac11610190578063caf6aa4b116100dc578063e985e9c511610095578063f23a6e611161006f578063f23a6e6114610b19578063f3ff955a14610b46578063fa3dd61e14610b66578063fea44a5614610b935761030a565b8063e985e9c514610a9b578063eb2931b714610ad6578063f0689b4714610b065761030a565b8063caf6aa4b146109d4578063cd36324914610a01578063cf67f34414610a21578063d7faa26214610a56578063e6f26d9a14610a6c578063e8a3d48514610a865761030a565b8063a25632fd11610149578063b9fa1e9211610123578063b9fa1e9214610937578063bc197c8114610957578063c43683a114610986578063c87b56dd146109b45761030a565b8063a25632fd14610822578063b20240ee14610842578063b88d4fde146109175761030a565b806378cfabac146107665780638a415268146107865780639340b21e146107a657806395d89b41146107c65780639f181b5e146107db578063a22cb465146108025761030a565b806333b9d8c41161024f57806346904840116102085780636352211e116101e25780636352211e146106d85780636fd44cfd146106f857806370a082311461073057806374cb3041146107505761030a565b8063469048401461064757806352a702b51461066e57806356973ee5146106a45761030a565b806333b9d8c4146105925780633846b6d2146105a75780633c481576146105c75780633e4011b9146105e75780634121c9311461060757806342842e0e146106275761030a565b8063150b7a02116102bc57806324a9d8531161029657806324a9d853146104f85780632a55205a1461052b578063305a07211461056a578063314e99a21461057d5761030a565b8063150b7a02146104745780631d28dec7146104b857806323b872dd146104d85761030a565b806301ffc9a71461036157806306fdde0314610396578063081812fc146103b85780630935847914610406578063095ea7b3146104345780630d4d1513146104545761030a565b3661030a57005b34801561031657600080fd5b5061035f610322610ba8565b6000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610bd692505050565b005b34801561036d57600080fd5b5061038161037c366004614690565b610c9d565b60405190151581526020015b60405180910390f35b3480156103a257600080fd5b506103ab610cd8565b60405161038d91906146fd565b3480156103c457600080fd5b506103ee6103d3366004614710565b600c602052600090815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161038d565b34801561041257600080fd5b50610426610421366004614729565b610d66565b60405190815260200161038d565b34801561044057600080fd5b5061035f61044f36600461476b565b6110d0565b34801561046057600080fd5b5061042661046f366004614797565b6111b2565b34801561048057600080fd5b5061049f61048f3660046148e6565b630a85bd0160e11b949350505050565b6040516001600160e01b0319909116815260200161038d565b3480156104c457600080fd5b5061035f6104d3366004614710565b611356565b3480156104e457600080fd5b5061035f6104f3366004614951565b61150a565b34801561050457600080fd5b5060005461051890610100900461ffff1681565b60405161ffff909116815260200161038d565b34801561053757600080fd5b5061054b610546366004614729565b61157f565b604080516001600160a01b03909316835260208301919091520161038d565b61035f6105783660046149d3565b611598565b34801561058957600080fd5b5061035f611786565b34801561059e57600080fd5b506103ee61181f565b3480156105b357600080fd5b506104266105c2366004614a43565b61182e565b3480156105d357600080fd5b5061035f6105e2366004614bf2565b6118df565b3480156105f357600080fd5b5061035f610602366004614dc4565b611932565b34801561061357600080fd5b5061035f610622366004614e13565b6119ce565b34801561063357600080fd5b5061035f610642366004614951565b611de6565b34801561065357600080fd5b506000546103ee90630100000090046001600160a01b031681565b34801561067a57600080fd5b506103ee610689366004614e60565b6004602052600090815260409020546001600160a01b031681565b3480156106b057600080fd5b506103ee7f00000000000000000000000052010e220e5c8ef2217d86cfa58da51da39e8ec481565b3480156106e457600080fd5b506103ee6106f3366004614710565b611e3a565b34801561070457600080fd5b50600f54610718906001600160601b031681565b6040516001600160601b03909116815260200161038d565b34801561073c57600080fd5b5061042661074b366004614e60565b611e45565b34801561075c57600080fd5b5061042660025481565b34801561077257600080fd5b50610426610781366004614710565b611ea8565b34801561079257600080fd5b506107186107a1366004614a43565b611ee9565b3480156107b257600080fd5b50600e546103ee906001600160a01b031681565b3480156107d257600080fd5b506103ab611eff565b3480156107e757600080fd5b50600e5461071890600160a01b90046001600160601b031681565b34801561080e57600080fd5b5061035f61081d366004614e8b565b611f0c565b34801561082e57600080fd5b5061042661083d366004614f3f565b611f78565b34801561084e57600080fd5b506108c7604080516080810182526000808252602082018190529181018290526060810191909152506040805160808101825260055464ffffffffff8082168352600160281b8204166020830152600160501b810461ffff1692820192909252600160601b9091046001600160601b0316606082015290565b60405161038d9190600060808201905064ffffffffff8084511683528060208501511660208401525061ffff60408401511660408301526001600160601b03606084015116606083015292915050565b34801561092357600080fd5b5061035f610932366004614f83565b61217c565b34801561094357600080fd5b5061035f610952366004614e60565b6121d2565b34801561096357600080fd5b5061049f610972366004615039565b63bc197c8160e01b98975050505050505050565b34801561099257600080fd5b506109a66109a1366004614710565b612314565b60405161038d929190615121565b3480156109c057600080fd5b506103ab6109cf366004614710565b6123bb565b3480156109e057600080fd5b506104266109ef366004614710565b60106020526000908152604090205481565b348015610a0d57600080fd5b50610718610a1c36600461517d565b6123d9565b348015610a2d57600080fd5b50610426610a3c3660046151bb565b604081018051805160208201208252606090922091905290565b348015610a6257600080fd5b5061042660015481565b348015610a7857600080fd5b506000546103819060ff1681565b348015610a9257600080fd5b506103ab612417565b348015610aa757600080fd5b50610381610ab63660046151f7565b600d60209081526000928352604080842090915290825290205460ff1681565b348015610ae257600080fd5b50610381610af1366004614e60565b60036020526000908152604090205460ff1681565b61035f610b14366004615225565b612434565b348015610b2557600080fd5b5061049f610b343660046152ea565b63f23a6e6160e01b9695505050505050565b348015610b5257600080fd5b5061035f610b61366004614e60565b6127e0565b348015610b7257600080fd5b50610b86610b81366004615372565b61286e565b60405161038d91906153a2565b348015610b9f57600080fd5b5061035f612caa565b7feb054550c406db3b89dc7016369a66aff0ce40188133281942b92e6188c6b1ef546001600160a01b031690565b604051633e4011b960e01b81523090633e4011b990610bfb9085908590600401615416565b60006040518083038186803b158015610c1357600080fd5b505afa925050508015610c24575060015b610c91573d808015610c52576040519150601f19603f3d011682016040523d82523d6000602084013e610c57565b606091505b5060008082806020019051810190610c6f919061547f565b9150915081610c8157610c8181612e10565b610c8a81612e18565b5050505050565b610c996154c5565b5050565b6000610ca882612e20565b80610cb75750610cb782612e3a565b80610cd257506001600160e01b0319821663152a902d60e11b145b92915050565b60088054610ce5906154db565b80601f0160208091040260200160405190810160405280929190818152602001828054610d11906154db565b8015610d5e5780601f10610d3357610100808354040283529160200191610d5e565b820191906000526020600020905b815481529060010190602001808311610d4157829003601f168201915b505050505081565b60006001600160a01b037f00000000000000000000000052010e220e5c8ef2217d86cfa58da51da39e8ec4163003610db15760405163ea2cbbd560e01b815260040160405180910390fd5b6000838152600660209081526040808320815160a081018352815464ffffffffff8082168352600160281b8204811695830195909552600160501b8104851693820193909352600160781b83049093166060840152600160a01b9091046001600160601b0316608083015291610e2682612e7d565b90506001816007811115610e3c57610e3c6150f7565b14158015610e5c57506003816007811115610e5957610e596150f7565b14155b8015610e7a57506004816007811115610e7757610e776150f7565b14155b15610ea35780604051630821641d60e21b8152600401610e9a9190615515565b60405180910390fd5b5033600090815260028301602052604090205460ff1615610ed957604051630b517d8f60e41b8152336004820152602401610e9a565b3360008181526002840160205260408120805460ff1916600190811790915583519192610f11929091610f0b91615539565b876123d9565b90508082608001818151610f259190615557565b6001600160601b03908116909152835185546020860151604080880151606089015160808a0151909616600160a01b026001600160a01b0364ffffffffff978816600160781b0264ffffffffff60781b19938916600160501b029390931669ffffffffffffffffffff60501b19958916600160281b0269ffffffffffffffffffff1990971698909716979097179490941792909216939093171792909216919091178555517fea45672a2d92b09ff2dd48aa67615f8b5c79d7808b7282fc026a24e00283f78d915061101f908890339085909283526001600160a01b039190911660208301526001600160601b0316604082015260600190565b60405180910390a1602082015164ffffffffff16158015611069575060808201516005546110699190600160601b81046001600160601b031690600160501b900461ffff16613002565b156110ba57825469ffffffffff00000000001916600160281b4264ffffffffff160217835560405186907fe36f8b7448daff4a52e2945db0d1d7a436279cc1d527a45c27835dcbd27f336d90600090a25b50608001516001600160601b0316949350505050565b6000818152600a60205260409020546001600160a01b03163381148061111957506001600160a01b0381166000908152600d6020908152604080832033845290915290205460ff165b6111565760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610e9a565b6000828152600c602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b600e546000906001600160a01b03163381146111f257604051633a33dca760e11b81523360048201526001600160a01b0382166024820152604401610e9a565b6001600160a01b037f00000000000000000000000052010e220e5c8ef2217d86cfa58da51da39e8ec416300361123b5760405163ea2cbbd560e01b815260040160405180910390fd5b600e54600f546005546001600160601b03600160a01b90930483169291821691600160601b90910416600061126f8861303e565b90506001600160601b0381166112858484615577565b6001600160601b031610156112a15761129e8383615577565b90505b6112ab8184615557565b92506112b8846001615557565b600e80546001600160601b03928316600160a01b81026001600160a01b0392831617909255600f80548785166bffffffffffffffffffffffff1990911617905560008281526010602090815260408083209587169095558d8316825260049052929092205490975016801561132b578097505b61133f8a6001600160601b0384168a61306f565b6113498a88613191565b5050505050509392505050565b3360009081526003602052604090205460ff1661138657604051633641391960e21b815260040160405180910390fd5b6001600160a01b037f00000000000000000000000052010e220e5c8ef2217d86cfa58da51da39e8ec41630036113cf5760405163ea2cbbd560e01b815260040160405180910390fd5b6000818152600660209081526040808320815160a081018352815464ffffffffff8082168352600160281b8204811695830195909552600160501b8104851693820193909352600160781b83049093166060840152600160a01b9091046001600160601b031660808301529161144482612e7d565b9050600181600781111561145a5761145a6150f7565b1415801561147a57506003816007811115611477576114776150f7565b14155b801561149857506004816007811115611495576114956150f7565b14155b156114b85780604051630821641d60e21b8152600401610e9a9190615515565b5081546001600160a01b03166001600160a01b031917825560405133815283907fc2131db10d833d6b93ae553fa450ea0f6c0c2dfb0160cb3309468bf72718f3eb9060200160405180910390a2505050565b6001600160a01b037f00000000000000000000000052010e220e5c8ef2217d86cfa58da51da39e8ec41630036115535760405163ea2cbbd560e01b815260040160405180910390fd5b60008181526010602052604090205461156f908490849061325d565b61157a83838361328a565b505050565b60008061158a613451565b5060009050805b9250929050565b604051635c9fcd8560e11b8152600b60048201526000907f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade6001600160a01b03169063b93f9b0a90602401602060405180830381865afa158015611600573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116249190615597565b9050336001600160a01b038216146116605760405163520b6b7560e01b81523360048201526001600160a01b0382166024820152604401610e9a565b5060005460ff1615611685576040516304e71fd360e31b815260040160405180910390fd5b6001600160a01b037f00000000000000000000000052010e220e5c8ef2217d86cfa58da51da39e8ec41630036116ce5760405163ea2cbbd560e01b815260040160405180910390fd5b600080856001600160a01b03168386866040516116ec9291906155b4565b60006040518083038185875af1925050503d8060008114611729576040519150601f19603f3d011682016040523d82523d6000602084013e61172e565b606091505b5091509150816117415761174181612e10565b7f66cf5924183d7d44caa75d9268a169d7c1422fef43848743d5e1ba32d5833acf8686868660405161177694939291906155ed565b60405180910390a1505050505050565b600e546001600160a01b03163381146117c357604051633a33dca760e11b81523360048201526001600160a01b0382166024820152604401610e9a565b6001600160a01b037f00000000000000000000000052010e220e5c8ef2217d86cfa58da51da39e8ec416300361180c5760405163ea2cbbd560e01b815260040160405180910390fd5b50600e80546001600160a01b0319169055565b6000611829610ba8565b905090565b6001600160a01b03821660009081526007602052604081208054825b818110156118bb57600060026118608484615623565b61186a919061564c565b90508564ffffffffff1684828154811061188657611886615660565b60009182526020909120015464ffffffffff1611156118a7578092506118b5565b6118b2816001615623565b91505b5061184a565b81156118d1576118cc600183615676565b6118d5565b6000195b9695505050505050565b303b8015611900576040516304a41c4d60e51b815260040160405180910390fd5b81516020808201516040808401516060808601519551948801519288015190880151610c9996949592949391906134e7565b33301461193e57600080fd5b600080836001600160a01b0316836040516119599190615689565b600060405180830381855af49150503d8060008114611994576040519150601f19603f3d011682016040523d82523d6000602084013e611999565b606091505b50915091506119c882826040516020016119b49291906156a5565b604051602081830303815290604052612e10565b50505050565b60006119d93361361f565b905080604001516001600160601b03166000148015611a03575060208101516001600160601b0316155b15611a215760405163e6de1cdd60e01b815260040160405180910390fd5b506001600160a01b037f00000000000000000000000052010e220e5c8ef2217d86cfa58da51da39e8ec4163003611a6b5760405163ea2cbbd560e01b815260040160405180910390fd5b6000828152600660205260409020611a8f611a85836156c0565b82600101546136e2565b6040805160a081018252825464ffffffffff8082168352600160281b820481166020840152600160501b8204811693830193909352600160781b81049092166060820152600160a01b9091046001600160601b031660808201526000611af482612e7d565b90506005816007811115611b0a57611b0a6150f7565b14611b2a5780604051630821641d60e21b8152600401610e9a9190615515565b506000611b3d60408501602086016156cc565b64ffffffffff16905060007f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade6001600160a01b031663441abbac600f6040518263ffffffff1660e01b8152600401611b9791815260200190565b602060405180830381865afa158015611bb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd891906156e7565b604051631106aeeb60e21b8152601760048201529091506000906001600160a01b037f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade169063441abbac90602401602060405180830381865afa158015611c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6791906156e7565b90508115611c7b5781831115611c7b578192505b8015611c8d5780831015611c8d578092505b600083856040015164ffffffffff16611ca69190615623565b905080421015611cda576040516303861c4b60e41b815264ffffffffff428116600483015282166024820152604401610e9a565b5050835464ffffffffff60781b1916600160781b648000000000421764ffffffffff1602178455506000905080611d0f610ba8565b6001600160a01b031686604051602401611d2b91815260200190565b60408051601f198184030181529181526020820180516001600160e01b031663e0a8f6f560e01b17905251611d609190615689565b600060405180830381855af49150503d8060008114611d9b576040519150601f19603f3d011682016040523d82523d6000602084013e611da0565b606091505b509150915081611db357611db381612e10565b505060405184907f416e669c63d9a3a5e36ee7cc7e2104b8db28ccd286aa18966e98fa230c73b08c90600090a250505050565b6001600160a01b037f00000000000000000000000052010e220e5c8ef2217d86cfa58da51da39e8ec4163003611e2f5760405163ea2cbbd560e01b815260040160405180910390fd5b61157a838383613721565b6000610cd2826137f1565b60006001600160a01b038216611e8c5760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606401610e9a565b506001600160a01b03166000908152600b602052604090205490565b600554600090600160601b90046001600160601b0316600083815260106020526040902054611edf90670de0b6b3a7640000615700565b610cd2919061564c565b6000611ef883836000196123d9565b9392505050565b60098054610ce5906154db565b336000818152600d602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b600080611f843361361f565b905080604001516001600160601b03166000148015611fae575060208101516001600160601b0316155b15611fcc5760405163e6de1cdd60e01b815260040160405180910390fd5b506001600160a01b037f00000000000000000000000052010e220e5c8ef2217d86cfa58da51da39e8ec41630036120165760405163ea2cbbd560e01b815260040160405180910390fd5b60026000815461202590615717565b91829055506040805160a08101825264ffffffffff4216815260006020820181905291810182905260608101829052608081019190915290915061207d84604081018051805160208201208252606090922091905290565b600083815260066020908152604091829020600181019390935583518354918501518584015160608701516080909701516001600160601b0316600160a01b026001600160a01b0364ffffffffff988916600160781b0264ffffffffff60781b19938a16600160501b029390931669ffffffffffffffffffff60501b19948a16600160281b0269ffffffffffffffffffff1990971699909516989098179490941791909116919091171793909316929092179055517fea77d064c7d953e57748855e7b0751ea190d1df7505615a4e39336d4d548f6889061216390839033908790615730565b60405180910390a16121758183610d66565b5092915050565b6001600160a01b037f00000000000000000000000052010e220e5c8ef2217d86cfa58da51da39e8ec41630036121c55760405163ea2cbbd560e01b815260040160405180910390fd5b610c8a8585858585613848565b3360009081526003602052604090205460ff1661220257604051633641391960e21b815260040160405180910390fd5b6001600160a01b037f00000000000000000000000052010e220e5c8ef2217d86cfa58da51da39e8ec416300361224b5760405163ea2cbbd560e01b815260040160405180910390fd5b6001600160a01b038116156122b8576001600160a01b03811660009081526003602052604090205460ff16156122945760405163640c1a3360e01b815260040160405180910390fd5b6001600160a01b0381166000908152600360205260409020805460ff191660011790555b33600081815260036020908152604091829020805460ff1916905581519283526001600160a01b038416908301527fddffcdb3bb07c5efc18b0918cf4e3e88c7d42cc05156cdadb2ec12c3b5ff892f910160405180910390a150565b6040805160a081018252600080825260208201819052918101829052606081018290526080810182905250600082815260066020908152604091829020825160a081018452905464ffffffffff8082168352600160281b8204811693830193909352600160501b8104831693820193909352600160781b83049091166060820152600160a01b9091046001600160601b031660808201526123b481612e7d565b9150915091565b60606123c5613451565b505060408051602081019091526000815290565b6000806123e7858585613906565b905080602001518160600151612401578160400151612404565b60005b61240e9190615557565b95945050505050565b6060612421613451565b5060408051602081019091526000815290565b600061243f3361361f565b905080604001516001600160601b03166000148015612469575060208101516001600160601b0316155b156124875760405163e6de1cdd60e01b815260040160405180910390fd5b506040516331a1aa3360e11b8152601560048201527f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade6001600160a01b031690636343546690602401602060405180830381865afa1580156124ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612511919061577f565b1561252f57604051632fb3e88560e01b815260040160405180910390fd5b6001600160a01b037f00000000000000000000000052010e220e5c8ef2217d86cfa58da51da39e8ec41630036125785760405163ea2cbbd560e01b815260040160405180910390fd5b600088815260066020526040902060018101546125969089906136e2565b6040805160a081018252825464ffffffffff8082168352600160281b820481166020840152600160501b8204811693830193909352600160781b81049092166060820152600160a01b9091046001600160601b0316608082015260006125fb82612e7d565b90506004816007811115612611576126116150f7565b141580156126315750600581600781111561262e5761262e6150f7565b14155b156126515780604051630821641d60e21b8152600401610e9a9190615515565b6004816007811115612665576126656150f7565b036126ca57428a6000015164ffffffffff1610156126ab578951604051632f7e600560e21b815264ffffffffff9182166004820152429091166024820152604401610e9a565b825464ffffffffff60501b1916600160501b4264ffffffffff16021783555b88516020908102818b0120600090815289518202828b0120909152604090206001541461270a57604051633b43666f60e01b815260040160405180910390fd5b825464ffffffffff60781b1916600160781b4264ffffffffff160217835560006127bb8c8c8c8c61273a88613a81565b8d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613aba92505050565b9050806127d257835464ffffffffff60781b191684555b505050505050505050505050565b6001600160a01b037f00000000000000000000000052010e220e5c8ef2217d86cfa58da51da39e8ec41630036128295760405163ea2cbbd560e01b815260040160405180910390fd5b6128353360008361306f565b6040516001600160a01b0382169033907fbfa9be947969a7d4f47eceedb207379702a5e9e8b82ec09d564da75195f8689e90600090a350565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c08101919091523330146129035760006128b93361361f565b905080604001516001600160601b031660001480156128e3575060208101516001600160601b0316155b156129015760405163e6de1cdd60e01b815260040160405180910390fd5b505b6040516331a1aa3360e11b8152601560048201527f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade6001600160a01b031690636343546690602401602060405180830381865afa158015612968573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298c919061577f565b156129aa57604051632fb3e88560e01b815260040160405180910390fd5b6001600160a01b037f00000000000000000000000052010e220e5c8ef2217d86cfa58da51da39e8ec41630036129f35760405163ea2cbbd560e01b815260040160405180910390fd5b604051635c9fcd8560e11b8152600c60048201526000907f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade6001600160a01b03169063b93f9b0a90602401602060405180830381865afa158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190615597565b90507fdda962f630bf2f85c8412f305206a4f363688481dd632689f88ad7022e4cc233858585604051612ab49392919061579c565b60405180910390a160008054630100000081046001600160a01b03169161010090910461ffff1690876001811115612aee57612aee6150f7565b03612b7b57604051631d1972a760e11b81523060048201526001600160a01b03838116602483015261ffff83166044830152841690633a32e54e90479060640160e06040518083038185885af1158015612b4c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612b7191906157db565b9350505050611ef8565b6001876001811115612b8f57612b8f6150f7565b14612b9c57612b9c6154c5565b6040516370a0823160e01b8152306004820152612c1b9084906001600160a01b038916906370a0823190602401602060405180830381865afa158015612be6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c0a91906156e7565b6001600160a01b0389169190613c06565b60405163eedaf00d60e01b81526001600160a01b038781166004830152306024830152838116604483015261ffff8316606483015284169063eedaf00d9060840160e0604051808303816000875af1158015612c7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c9f91906157db565b979650505050505050565b604051635c9fcd8560e11b8152600b60048201526000907f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade6001600160a01b03169063b93f9b0a90602401602060405180830381865afa158015612d12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d369190615597565b9050336001600160a01b03821614801590612d6157503360009081526003602052604090205460ff16155b15612d905760405163e670248160e01b81523360048201526001600160a01b0382166024820152604401610e9a565b6001600160a01b037f00000000000000000000000052010e220e5c8ef2217d86cfa58da51da39e8ec4163003612dd95760405163ea2cbbd560e01b815260040160405180910390fd5b6000805460ff191660011781556040517f447e75484d6bdb571b4a92ae14018db7b6dd41f3f02360690c554e1d48f46f879190a150565b805160208201fd5b805160208201f35b6000612e2b82613d38565b80610cd25750610cd282613d6e565b6000612e4582612e20565b80612e6057506380ac58cd60e01b6001600160e01b03198316145b80610cd25750506001600160e01b031916635b5e139f60e01b1490565b805160009064ffffffffff168103612e9757506000919050565b604082015164ffffffffff1615612eec57816060015164ffffffffff16600003612ec357506005919050565b64800000000080836060015164ffffffffff161603612ee457506007919050565b506006919050565b6001600160601b03801682608001516001600160601b031603612f1157506002919050565b6040805160808101825260055464ffffffffff8082168352600160281b82048116602080850191909152600160501b830461ffff1694840194909452600160601b9091046001600160601b031660608301529184015142921615612fcc578164ffffffffff1681602001518560200151612f8b919061588b565b64ffffffffff1611612fa1575060049392505050565b612fb384608001518260600151613d99565b15612fc2575060049392505050565b5060039392505050565b8051845164ffffffffff841691612fe29161588b565b64ffffffffff1611612ff8575060029392505050565b5060019392505050565b60008161ffff16836001600160601b0316856001600160601b031661271061302a9190615700565b613034919061564c565b1015949350505050565b60006001600160601b0382111561306b57604051636f55e21560e11b815260048101839052602401610e9a565b5090565b600061307a8461361f565b6001600160a01b038086166000908152600460205260409020549192501680156130a457806130a6565b845b90506001600160a01b038316156130bd57826130bf565b805b9250600060405180608001604052804264ffffffffff16815260200184602001516001600160601b031681526020016131218761310f87604001516001600160601b03166001600160601b031690565b61311991906158a9565b60170b613dcc565b6001600160601b031681526001600160a01b038681169089161415602090910152905061314e8682613e0d565b6001600160a01b03868116600090815260046020526040902080546001600160a01b0319169186169190911790556131898683868685613fe6565b505050505050565b61319b8282614194565b6001600160a01b0382163b15806132415750604051630a85bd0160e11b80825233600483015260006024830181905260448301849052608060648401526084830152906001600160a01b0384169063150b7a029060a4016020604051808303816000875af1158015613211573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061323591906158d6565b6001600160e01b031916145b610c995760405162461bcd60e51b8152600401610e9a906158f3565b60006132688261429f565b905061327e846132778361591d565b600061306f565b6119c88382600061306f565b6000818152600a60205260409020546001600160a01b038481169116146132e05760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b6044820152606401610e9a565b6001600160a01b03821661332a5760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610e9a565b336001600160a01b038416148061336457506001600160a01b0383166000908152600d6020908152604080832033845290915290205460ff165b8061338557506000818152600c60205260409020546001600160a01b031633145b6133c25760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610e9a565b6001600160a01b038084166000818152600b60209081526040808320805460001901905593861680835284832080546001019055858352600a825284832080546001600160a01b03199081168317909155600c90925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b604051635c9fcd8560e11b81526004808201526134dd907f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade6001600160a01b03169063b93f9b0a90602401602060405180830381865afa1580156134b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103229190615597565b6134e56154c5565b565b6134f28484846142cc565b60086134fe8882615986565b50600961350b8782615986565b50600e80546001600160a01b0319166001600160a01b038316179055841561361657604051635c9fcd8560e11b8152601660048201527f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade6001600160a01b03169063b93f9b0a90602401602060405180830381865afa158015613592573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135b69190615597565b6001600160a01b031663fc9968df866040518263ffffffff1660e01b81526004016135e391815260200190565b600060405180830381600087803b1580156135fd57600080fd5b505af1158015613611573d6000803e3d6000fd5b505050505b50505050505050565b6040805160808101825260008082526020808301829052828401829052606083018290526001600160a01b03851682526007905291909120805480156136db578161366b600183615676565b8154811061367b5761367b615660565b600091825260209182902060408051608081018252929091015464ffffffffff81168352600160281b81046001600160601b0390811694840194909452600160881b810490931690820152600160e81b90910460ff161515606082015292505b5050919050565b60408201805180516020820120825260608420915280821461157a57604051630267877160e11b81526004810182905260248101839052604401610e9a565b61372c83838361150a565b6001600160a01b0382163b15806137d55750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af11580156137a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c991906158d6565b6001600160e01b031916145b61157a5760405162461bcd60e51b8152600401610e9a906158f3565b6000818152600a60205260409020546001600160a01b0316806138435760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b6044820152606401610e9a565b919050565b61385385858561150a565b6001600160a01b0384163b15806138ea5750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a029061389b9033908a90899089908990600401615a45565b6020604051808303816000875af11580156138ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138de91906158d6565b6001600160e01b031916145b610c8a5760405162461bcd60e51b8152600401610e9a906158f3565b6040805160808101825260008082526020808301829052828401829052606083018290526001600160a01b0387168252600790529190912080548015613a7857808410801561398057508464ffffffffff1682858154811061396a5761396a615660565b60009182526020909120015464ffffffffff1611155b80156139d35750613992600182615676565b8414806139d3575064ffffffffff8516826139ae866001615623565b815481106139be576139be615660565b60009182526020909120015464ffffffffff16115b15613a51578184815481106139ea576139ea615660565b600091825260209182902060408051608081018252929091015464ffffffffff81168352600160281b81046001600160601b0390811694840194909452600160881b810490931690820152600160e81b90910460ff16151560608201529250611ef8915050565b613a5b868661182e565b93506000198414613a78578184815481106139ea576139ea615660565b50509392505050565b6080810151600554600091613aa591600160601b90046001600160601b0316613d99565b15613ab257506001919050565b506000919050565b6000806040518060e001604052808a8152602001896040015181526020018581526020018481526020018681526020018881526020018781525090506060600080613b03610ba8565b6001600160a01b031684604051602401613b1d9190615ab4565b60408051601f198184030181529181526020820180516001600160e01b031663a7c8a3f960e01b17905251613b529190615689565b600060405180830381855af49150503d8060008114613b8d576040519150601f19603f3d011682016040523d82523d6000602084013e613b92565b606091505b509150915081613ba557613ba581612e10565b80806020019051810190613bb99190615b94565b92505050897fc98fbf8f20b11b050a9541d12aee1c11fcd31e8e42975cc885fb3d33a6accc823383604051613bef929190615416565b60405180910390a251159998505050505050505050565b6040516001600160a01b03838116602483015260448201839052600091829186169060640160408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b17905251613c609190615689565b6000604051808303816000865af19150503d8060008114613c9d576040519150601f19603f3d011682016040523d82523d6000602084013e613ca2565b606091505b50915091508115613d05578051600003613ce557843b600081900361318957604051639fe23a3960e01b81526001600160a01b0387166004820152602401610e9a565b80806020019051810190613cf9919061577f565b15613d05575050505050565b604051631702a98760e11b81526001600160a01b0380871660048301528516602482015260448101849052606401610e9a565b60006301ffc9a760e01b6001600160e01b031983161480610cd257506001600160e01b03198216630a85bd0160e11b1492915050565b6000613d7982613d38565b80610cd257506001600160e01b03198216630271189760e51b1492915050565b60008082613da985612710615bc8565b613db39190615bf3565b61270f6001600160601b03919091161015949350505050565b6000808260170b1280613de957506001600160601b03601783900b135b1561306b576040516394e08f6160e01b8152601783900b6004820152602401610e9a565b6001600160a01b038216600090815260076020526040902080548015613f5c57600082613e3b600184615676565b81548110613e4b57613e4b615660565b600091825260209182902060408051608081018252919092015464ffffffffff8082168084526001600160601b03600160281b8404811696850196909652600160881b83049095169383019390935260ff600160e81b90910416151560608201528651909350169003613f5a578383613ec5600185615676565b81548110613ed557613ed5615660565b60009182526020918290208351910180549284015160408501516060909501511515600160e81b0260ff60e81b196001600160601b03968716600160881b0216600160881b600160f01b031996909216600160281b026001600160881b031990951664ffffffffff909416939093179390931793909316919091171790555050505050565b505b50805460018101825560009182526020918290208351910180549284015160408501516060909501511515600160e81b0260ff60e81b196001600160601b03968716600160881b0216600160881b600160f01b031996909216600160281b026001600160881b031990951664ffffffffff9094169390931793909317939093169190911717905550565b6001600160a01b038316158061400357506001600160a01b038416155b156140215760405163e5ec2d2560e01b815260040160405180910390fd5b846001600160a01b0316846001600160a01b0316141580156140555750826001600160a01b0316846001600160a01b031614155b156140cf5760006140658561361f565b9050600060405180608001604052804264ffffffffff168152602001856040015184602001516140959190615577565b6001600160601b0316815260200183604001516001600160601b031681526020018360600151151581525090506140cc8682613e0d565b50505b846001600160a01b0316836001600160a01b031614610c8a5760006140f38461361f565b905060008260400151826020015161410b9190615557565b9050856001600160a01b0316856001600160a01b0316036141385760408401516141359082615577565b90505b600060405180608001604052804264ffffffffff168152602001836001600160601b0316815260200184604001516001600160601b0316815260200184606001511515815250905061418a8682613e0d565b5050505050505050565b6001600160a01b0382166141de5760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610e9a565b6000818152600a60205260409020546001600160a01b0316156142345760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b6044820152606401610e9a565b6001600160a01b0382166000818152600b6020908152604080832080546001019055848352600a90915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006001600160bf1b0382111561306b5760405163e9a5989b60e01b815260048101839052602401610e9a565b6127108360a0015161ffff1611156143035760a08301516040516323dd0d6d60e11b815261ffff9091166004820152602401610e9a565b612710836060015161ffff16111561433a5760608301516040516323dd0d6d60e11b815261ffff9091166004820152602401610e9a565b604051635c9fcd8560e11b8152600260048201526143dc907f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade6001600160a01b03169063b93f9b0a90602401602060405180830381865afa1580156143a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143c79190615597565b6040518060200160405280600081525061454e565b604080516080808201835260208681015164ffffffffff9081168085528886015190911691840182905260608089015161ffff908116968601879052938901516001600160601b031694018490526005805469ffffffffffffffffffff1916909117600160281b909202919091176dffffffffffffffffffffffffffff60501b1916600160501b9094026bffffffffffffffffffffffff60601b191693909317600160601b9092029190911790915560a08401516000805460c0870151610100600160b81b031990911661010093909416929092026301000000600160b81b0319169290921763010000006001600160a01b03909216919091021790556144e3828261462f565b60005b8351518110156119c8576001600360008660000151848151811061450c5761450c615660565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905561454781615717565b90506144e6565b7feb054550c406db3b89dc7016369a66aff0ce40188133281942b92e6188c6b1ef80546001600160a01b031981166001600160a01b03858116918217845560405192169160009182916145a79085908890602401615416565b60408051601f198184030181529181526020820180516001600160e01b031663347d5e2560e21b179052516145dc9190615689565b600060405180830381855af49150503d8060008114614617576040519150601f19603f3d011682016040523d82523d6000602084013e61461c565b606091505b5091509150816131895761318981612e10565b8051825114614651576040516357cc2fc760e01b815260040160405180910390fd5b815160209081028184012060009081528251820282840120909152604090206001555050565b6001600160e01b03198116811461468d57600080fd5b50565b6000602082840312156146a257600080fd5b8135611ef881614677565b60005b838110156146c85781810151838201526020016146b0565b50506000910152565b600081518084526146e98160208601602086016146ad565b601f01601f19169290920160200192915050565b602081526000611ef860208301846146d1565b60006020828403121561472257600080fd5b5035919050565b6000806040838503121561473c57600080fd5b50508035926020909101359150565b6001600160a01b038116811461468d57600080fd5b80356138438161474b565b6000806040838503121561477e57600080fd5b82356147898161474b565b946020939093013593505050565b6000806000606084860312156147ac57600080fd5b83356147b78161474b565b92506020840135915060408401356147ce8161474b565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715614811576148116147d9565b60405290565b60405160e081016001600160401b0381118282101715614811576148116147d9565b604051601f8201601f191681016001600160401b0381118282101715614861576148616147d9565b604052919050565b60006001600160401b03821115614882576148826147d9565b50601f01601f191660200190565b600082601f8301126148a157600080fd5b81356148b46148af82614869565b614839565b8181528460208386010111156148c957600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080608085870312156148fc57600080fd5b84356149078161474b565b935060208501356149178161474b565b92506040850135915060608501356001600160401b0381111561493957600080fd5b61494587828801614890565b91505092959194509250565b60008060006060848603121561496657600080fd5b83356149718161474b565b925060208401356149818161474b565b929592945050506040919091013590565b60008083601f8401126149a457600080fd5b5081356001600160401b038111156149bb57600080fd5b60208301915083602082850101111561159157600080fd5b600080600080606085870312156149e957600080fd5b84356149f48161474b565b935060208501356001600160401b03811115614a0f57600080fd5b614a1b87828801614992565b9598909750949560400135949350505050565b803564ffffffffff8116811461384357600080fd5b60008060408385031215614a5657600080fd5b8235614a618161474b565b9150614a6f60208401614a2e565b90509250929050565b60006001600160401b03821115614a9157614a916147d9565b5060051b60200190565b600082601f830112614aac57600080fd5b81356020614abc6148af83614a78565b82815260059290921b84018101918181019086841115614adb57600080fd5b8286015b84811015614aff578035614af28161474b565b8352918301918301614adf565b509695505050505050565b803561ffff8116811461384357600080fd5b80356001600160601b038116811461384357600080fd5b600082601f830112614b4457600080fd5b81356020614b546148af83614a78565b82815260059290921b84018101918181019086841115614b7357600080fd5b8286015b84811015614aff578035614b8a8161474b565b8352918301918301614b77565b600082601f830112614ba857600080fd5b81356020614bb86148af83614a78565b82815260059290921b84018101918181019086841115614bd757600080fd5b8286015b84811015614aff5780358352918301918301614bdb565b60006020808385031215614c0557600080fd5b82356001600160401b0380821115614c1c57600080fd5b9084019060808287031215614c3057600080fd5b614c386147ef565b823582811115614c4757600080fd5b830160808189031215614c5957600080fd5b614c616147ef565b813584811115614c7057600080fd5b820160e0818b031215614c8257600080fd5b614c8a614817565b813586811115614c9957600080fd5b614ca58c828501614a9b565b825250614cb3888301614a2e565b888201526040614cc4818401614a2e565b818301526060614cd5818501614b0a565b81840152614ce560808501614b1c565b6080840152614cf660a08501614b0a565b60a0840152614d0760c08501614760565b60c084015282855289860135935087841115614d2257600080fd5b614d2e8d858801614890565b8a86015281860135935087841115614d4557600080fd5b614d518d858801614890565b858301529485013585850152838652878901359487861115614d7257600080fd5b614d7e8d878b01614b33565b8a880152818901359950878a1115614d9557600080fd5b614da18d8b8b01614b97565b82880152614db0818a01614760565b9087015250939a9950505050505050505050565b60008060408385031215614dd757600080fd5b8235614de28161474b565b915060208301356001600160401b03811115614dfd57600080fd5b614e0985828601614890565b9150509250929050565b60008060408385031215614e2657600080fd5b8235915060208301356001600160401b03811115614e4357600080fd5b830160608186031215614e5557600080fd5b809150509250929050565b600060208284031215614e7257600080fd5b8135611ef88161474b565b801515811461468d57600080fd5b60008060408385031215614e9e57600080fd5b8235614ea98161474b565b91506020830135614e5581614e7d565b600060608284031215614ecb57600080fd5b604051606081016001600160401b038282108183111715614eee57614eee6147d9565b81604052829350614efe85614a2e565b8352614f0c60208601614a2e565b60208401526040850135915080821115614f2557600080fd5b50614f3285828601614890565b6040830152505092915050565b60008060408385031215614f5257600080fd5b82356001600160401b03811115614f6857600080fd5b614f7485828601614eb9565b95602094909401359450505050565b600080600080600060808688031215614f9b57600080fd5b8535614fa68161474b565b94506020860135614fb68161474b565b93506040860135925060608601356001600160401b03811115614fd857600080fd5b614fe488828901614992565b969995985093965092949392505050565b60008083601f84011261500757600080fd5b5081356001600160401b0381111561501e57600080fd5b6020830191508360208260051b850101111561159157600080fd5b60008060008060008060008060a0898b03121561505557600080fd5b88356150608161474b565b975060208901356150708161474b565b965060408901356001600160401b038082111561508c57600080fd5b6150988c838d01614ff5565b909850965060608b01359150808211156150b157600080fd5b6150bd8c838d01614ff5565b909650945060808b01359150808211156150d657600080fd5b506150e38b828c01614992565b999c989b5096995094979396929594505050565b634e487b7160e01b600052602160045260246000fd5b6008811061511d5761511d6150f7565b9052565b60c0810161512f828561510d565b64ffffffffff808451166020840152806020850151166040840152806040850151166060840152806060850151166080840152506001600160601b0360808401511660a08301529392505050565b60008060006060848603121561519257600080fd5b833561519d8161474b565b92506151ab60208501614a2e565b9150604084013590509250925092565b6000602082840312156151cd57600080fd5b81356001600160401b038111156151e357600080fd5b6151ef84828501614eb9565b949350505050565b6000806040838503121561520a57600080fd5b82356152158161474b565b91506020830135614e558161474b565b60008060008060008060008060c0898b03121561524157600080fd5b8835975060208901356001600160401b038082111561525f57600080fd5b61526b8c838d01614eb9565b985060408b013591508082111561528157600080fd5b61528d8c838d01614b33565b975060608b01359150808211156152a357600080fd5b6152af8c838d01614b97565b965060808b01359150808211156152c557600080fd5b6152d18c838d01614992565b909650945060a08b01359150808211156150d657600080fd5b60008060008060008060a0878903121561530357600080fd5b863561530e8161474b565b9550602087013561531e8161474b565b9450604087013593506060870135925060808701356001600160401b0381111561534757600080fd5b61535389828a01614992565b979a9699509497509295939492505050565b6002811061468d57600080fd5b60008060006060848603121561538757600080fd5b833561497181615365565b6002811061511d5761511d6150f7565b600060e0820190506153b5828451615392565b60208301516020830152604083015160018060a01b038082166040850152806060860151166060850152806080860151166080850152505060a08301516001600160801b0380821660a08501528060c08601511660c0850152505092915050565b6001600160a01b03831681526040602082018190526000906151ef908301846146d1565b600082601f83011261544b57600080fd5b81516154596148af82614869565b81815284602083860101111561546e57600080fd5b6151ef8260208301602087016146ad565b6000806040838503121561549257600080fd5b825161549d81614e7d565b60208401519092506001600160401b038111156154b957600080fd5b614e098582860161543a565b634e487b7160e01b600052600160045260246000fd5b600181811c908216806154ef57607f821691505b60208210810361550f57634e487b7160e01b600052602260045260246000fd5b50919050565b60208101610cd2828461510d565b634e487b7160e01b600052601160045260246000fd5b64ffffffffff82811682821603908082111561217557612175615523565b6001600160601b0381811683821601908082111561217557612175615523565b6001600160601b0382811682821603908082111561217557612175615523565b6000602082840312156155a957600080fd5b8151611ef88161474b565b8183823760009101908152919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b038516815260606020820181905260009061561290830185876155c4565b905082604083015295945050505050565b80820180821115610cd257610cd2615523565b634e487b7160e01b600052601260045260246000fd5b60008261565b5761565b615636565b500490565b634e487b7160e01b600052603260045260246000fd5b81810381811115610cd257610cd2615523565b6000825161569b8184602087016146ad565b9190910192915050565b82151581526040602082015260006151ef60408301846146d1565b6000610cd23683614eb9565b6000602082840312156156de57600080fd5b611ef882614a2e565b6000602082840312156156f957600080fd5b5051919050565b8082028115828204841417610cd257610cd2615523565b60006001820161572957615729615523565b5060010190565b83815260018060a01b038316602082015260606040820152600064ffffffffff808451166060840152806020850151166080840152506040830151606060a08401526118d560c08401826146d1565b60006020828403121561579157600080fd5b8151611ef881614e7d565b606081016157aa8286615392565b6001600160a01b0393909316602082015260400152919050565b80516001600160801b038116811461384357600080fd5b600060e082840312156157ed57600080fd5b60405160e081018181106001600160401b038211171561580f5761580f6147d9565b604052825161581d81615365565b81526020838101519082015260408301516158378161474b565b6040820152606083015161584a8161474b565b6060820152608083015161585d8161474b565b608082015261586e60a084016157c4565b60a082015261587f60c084016157c4565b60c08201529392505050565b64ffffffffff81811683821601908082111561217557612175615523565b601781810b9083900b016001600160bf1b0381136001600160bf1b031982121715610cd257610cd2615523565b6000602082840312156158e857600080fd5b8151611ef881614677565b60208082526010908201526f155394d0519157d49150d2541251539560821b604082015260600190565b6000601782900b600160bf1b810161593757615937615523565b60000392915050565b601f82111561157a57600081815260208120601f850160051c810160208610156159675750805b601f850160051c820191505b8181101561318957828155600101615973565b81516001600160401b0381111561599f5761599f6147d9565b6159b3816159ad84546154db565b84615940565b602080601f8311600181146159e857600084156159d05750858301515b600019600386901b1c1916600185901b178555613189565b600085815260208120601f198616915b82811015615a17578886015182559484019460019091019084016159f8565b5085821015615a355787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b0386811682528516602082015260408101849052608060608201819052600090612c9f90830184866155c4565b600081518084526020808501945080840160005b83811015615aa957815187529582019590820190600101615a8d565b509495945050505050565b600060208083528351818401528084015160e06040850152615ada6101008501826146d1565b90506040850151601f1980868403016060870152615af883836146d1565b92506060870151915080868403016080870152615b1583836146d1565b608088015160a088810191909152880151878203830160c08901528051808352908601945060009350908501905b80841015615b6c5784516001600160a01b03168252938501936001939093019290850190615b43565b5060c08801519450818782030160e0880152615b888186615a79565b98975050505050505050565b600060208284031215615ba657600080fd5b81516001600160401b03811115615bbc57600080fd5b6151ef8482850161543a565b6001600160601b03818116838216028082169190828114615beb57615beb615523565b505092915050565b60006001600160601b0380841680615c0d57615c0d615636565b9216919091049291505056fea26469706673582212200be9ace9cf91e260ff128ec1313e3ba1d8ac3af33e7e0d741297e426349a86d664736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade
-----Decoded View---------------
Arg [0] : globals (address): 0x1cA20040cE6aD406bC2A6c89976388829E7fbAde
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.