Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 7 from a total of 7 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Batch Claim | 19688815 | 89 days ago | IN | 0 ETH | 0.0003724 | ||||
Batch Claim | 19615793 | 99 days ago | IN | 0 ETH | 0.00071776 | ||||
Batch Claim | 19614322 | 99 days ago | IN | 0 ETH | 0.00053384 | ||||
Batch Claim | 19614081 | 99 days ago | IN | 0 ETH | 0.00085566 | ||||
Batch Claim | 19574397 | 105 days ago | IN | 0 ETH | 0.00085882 | ||||
Batch Claim | 19573967 | 105 days ago | IN | 0 ETH | 0.00085355 | ||||
0x60e03462 | 19164362 | 162 days ago | IN | Create: Party | 0 ETH | 0.258052 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
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.20+commit.a1b79de6
Optimization Enabled:
Yes with 50 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.20; 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; ProposalStorage.ProposalEngineOpts proposalEngine; string name; string symbol; uint256 customizationPresetId; } // Arguments used to initialize the `PartyGovernanceNFT`. struct PartyInitData { PartyOptions options; IERC721[] preciousTokens; uint256[] preciousTokenIds; address[] authorities; uint40 rageQuitTimestamp; } /// @notice Version ID of the party implementation contract. uint16 public constant VERSION_ID = 2; // Set the `Globals` contract. constructor(IGlobals globals) PartyGovernanceNFT(globals) {} /// @notice Initializer to be called prior to using the contract. /// @param initData Options used to initialize the party governance. function initialize(PartyInitData memory initData) external onlyInitialize { PartyGovernanceNFT._initialize( initData.options.name, initData.options.symbol, initData.options.customizationPresetId, initData.options.governance, initData.options.proposalEngine, initData.preciousTokens, initData.preciousTokenIds, initData.authorities, initData.rageQuitTimestamp ); } receive() external payable {} }
// 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: GPL-3.0 pragma solidity 0.8.20; import "../utils/LibSafeCast.sol"; import "../utils/LibAddress.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`. abstract contract PartyGovernanceNFT is PartyGovernance, ERC721, IERC2981 { using LibSafeCast for uint256; using LibSafeCast for uint96; using LibERC20Compat for IERC20; using LibAddress for address payable; error FixedRageQuitTimestampError(uint40 rageQuitTimestamp); error CannotRageQuitError(uint40 rageQuitTimestamp); error CannotDisableRageQuitAfterInitializationError(); error CannotEnableRageQuitIfNotDistributionsRequireVoteError(); error InvalidTokenOrderError(); error BelowMinWithdrawAmountError(uint256 amount, uint256 minAmount); error NothingToBurnError(); event AuthorityAdded(address indexed authority); event AuthorityRemoved(address indexed authority); event RageQuitSet(uint40 oldRageQuitTimestamp, uint40 newRageQuitTimestamp); event Burn(address caller, uint256 tokenId, uint256 votingPower); event RageQuit(address caller, uint256[] tokenIds, IERC20[] withdrawTokens, address receiver); event PartyCardIntrinsicVotingPowerSet(uint256 indexed tokenId, uint256 intrinsicVotingPower); uint40 private constant ENABLE_RAGEQUIT_PERMANENTLY = 0x6b5b567bfe; // uint40(uint256(keccak256("ENABLE_RAGEQUIT_PERMANENTLY"))) uint40 private constant DISABLE_RAGEQUIT_PERMANENTLY = 0xab2cb21860; // uint40(uint256(keccak256("DISABLE_RAGEQUIT_PERMANENTLY"))) // Token address used to indicate ETH. address private constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; // The `Globals` contract storing global configuration values. This contract // is immutable and its address will never change. IGlobals private immutable _GLOBALS; /// @notice The number of tokens that have been minted. uint96 public tokenCount; /// @notice The total minted voting power. /// Capped to `_governanceValues.totalVotingPower` unless minting /// party cards for initial crowdfund. uint96 public mintedVotingPower; /// @notice The timestamp until which ragequit is enabled. Can be set to the /// `ENABLE_RAGEQUIT_PERMANENTLY`/`DISABLE_RAGEQUIT_PERMANENTLY` /// values to enable/disable ragequit permanently. /// `DISABLE_RAGEQUIT_PERMANENTLY` can only be set during /// initialization. uint40 public rageQuitTimestamp; /// @notice The voting power of `tokenId`. mapping(uint256 => uint256) public votingPowerByTokenId; /// @notice Address with authority to mint cards and update voting power for the party. mapping(address => bool) public isAuthority; function _assertAuthority() internal view { if (!isAuthority[msg.sender]) { revert NotAuthorized(); } } modifier onlySelf() { if (msg.sender != address(this)) { revert NotAuthorized(); } _; } // Set the `Globals` contract. The name or symbol of ERC721 does not matter; // it will be set in `_initialize()`. constructor(IGlobals globals) payable PartyGovernance(globals) ERC721("", "") { _GLOBALS = globals; } // Initialize storage for proxy contracts. function _initialize( string memory name_, string memory symbol_, uint256 customizationPresetId, PartyGovernance.GovernanceOpts memory governanceOpts, ProposalStorage.ProposalEngineOpts memory proposalEngineOpts, IERC721[] memory preciousTokens, uint256[] memory preciousTokenIds, address[] memory authorities, uint40 rageQuitTimestamp_ ) internal { PartyGovernance._initialize( governanceOpts, proposalEngineOpts, preciousTokens, preciousTokenIds ); name = name_; symbol = symbol_; if (rageQuitTimestamp_ != 0) { if (proposalEngineOpts.distributionsConfig == DistributionsConfig.AllowedWithoutVote) { revert CannotEnableRageQuitIfNotDistributionsRequireVoteError(); } rageQuitTimestamp = rageQuitTimestamp_; } unchecked { for (uint256 i; i < authorities.length; ++i) { isAuthority[authorities[i]] = true; } } if (customizationPresetId != 0) { RendererStorage(_GLOBALS.getAddress(LibGlobals.GLOBAL_RENDERER_STORAGE)) .useCustomizationPreset(customizationPresetId); } } /// @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 view override 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. } /// @notice Return the distribution share amount of a token. Included as an alias /// for `votePowerByTokenId` for backwards compatibility with old /// `TokenDistributor` implementations. /// @param tokenId The token ID to query. /// @return share The distribution shares of `tokenId`. function getDistributionShareOf(uint256 tokenId) external view returns (uint256) { return votingPowerByTokenId[tokenId]; } /// @notice Return the voting power share of a token. Denominated /// fractions of 1e18. I.e., 1e18 = 100%. /// @param tokenId The token ID to query. /// @return share The voting power percentage of `tokenId`. function getVotingPowerShareOf(uint256 tokenId) public view returns (uint256) { uint256 totalVotingPower = _getSharedProposalStorage().governanceValues.totalVotingPower; return totalVotingPower == 0 ? 0 : (votingPowerByTokenId[tokenId] * 1e18) / totalVotingPower; } /// @notice Mint a governance NFT for `owner` with `votingPower` and /// immediately delegate voting power to `delegate.` Only callable /// by an authority. /// @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 returns (uint256 tokenId) { _assertAuthority(); uint96 mintedVotingPower_ = mintedVotingPower; uint96 totalVotingPower = _getSharedProposalStorage().governanceValues.totalVotingPower; // Cap voting power to remaining unminted voting power supply. uint96 votingPower_ = votingPower.safeCastUint256ToUint96(); // Allow minting past total voting power if minting party cards for // initial crowdfund when there is no total voting power. if (totalVotingPower != 0 && totalVotingPower - mintedVotingPower_ < votingPower_) { unchecked { votingPower_ = totalVotingPower - mintedVotingPower_; } } // Update state. unchecked { tokenId = ++tokenCount; } mintedVotingPower += votingPower_; votingPowerByTokenId[tokenId] = votingPower_; emit PartyCardIntrinsicVotingPowerSet(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); } /// @notice Add voting power to an existing NFT. Only callable by an /// authority. /// @param tokenId The ID of the NFT to add voting power to. /// @param votingPower The amount of voting power to add. function increaseVotingPower(uint256 tokenId, uint96 votingPower) external { _assertAuthority(); uint96 mintedVotingPower_ = mintedVotingPower; uint96 totalVotingPower = _getSharedProposalStorage().governanceValues.totalVotingPower; // Cap voting power to remaining unminted voting power supply. Allow // minting past total voting power if minting party cards for initial // crowdfund when there is no total voting power. if (totalVotingPower != 0 && totalVotingPower - mintedVotingPower_ < votingPower) { unchecked { votingPower = totalVotingPower - mintedVotingPower_; } } // Update state. mintedVotingPower += votingPower; uint256 newIntrinsicVotingPower = votingPowerByTokenId[tokenId] + votingPower; votingPowerByTokenId[tokenId] = newIntrinsicVotingPower; emit PartyCardIntrinsicVotingPowerSet(tokenId, newIntrinsicVotingPower); _adjustVotingPower(ownerOf(tokenId), votingPower.safeCastUint96ToInt192(), address(0)); // Notify third-party platforms that the party NFT metadata has updated. emit MetadataUpdate(tokenId); } /// @notice Remove voting power from an existing NFT. Only callable by an /// authority. /// @param tokenId The ID of the NFT to remove voting power from. /// @param votingPower The amount of voting power to remove. function decreaseVotingPower(uint256 tokenId, uint96 votingPower) external { _assertAuthority(); mintedVotingPower -= votingPower; votingPowerByTokenId[tokenId] -= votingPower; _adjustVotingPower(ownerOf(tokenId), -votingPower.safeCastUint96ToInt192(), address(0)); // Notify third-party platforms that the party NFT metadata has updated. emit MetadataUpdate(tokenId); } /// @notice Increase the total voting power of the party. Only callable by /// an authority. /// @param votingPower The new total voting power to add. function increaseTotalVotingPower(uint96 votingPower) external { _assertAuthority(); _getSharedProposalStorage().governanceValues.totalVotingPower += votingPower; lastTotalVotingPowerChangeTimestamp == uint40(block.timestamp); // Notify third-party platforms that the party NFT metadata has updated // for all tokens. emit BatchMetadataUpdate(0, type(uint256).max); } /// @notice Decrease the total voting power of the party. Only callable by /// an authority. /// @param votingPower The new total voting power to add. function decreaseTotalVotingPower(uint96 votingPower) external { _assertAuthority(); _getSharedProposalStorage().governanceValues.totalVotingPower -= votingPower; lastTotalVotingPowerChangeTimestamp == uint40(block.timestamp); // Notify third-party platforms that the party NFT metadata has updated // for all tokens. emit BatchMetadataUpdate(0, type(uint256).max); } /// @notice Burn governance NFTs and remove their voting power. /// @param tokenIds The IDs of the governance NFTs to burn. function burn(uint256[] memory tokenIds) public { _assertAuthority(); _burnAndUpdateVotingPower(tokenIds, false); } function _burnAndUpdateVotingPower( uint256[] memory tokenIds, bool checkIfAuthorizedToBurn ) private returns (uint96 totalVotingPowerBurned) { for (uint256 i; i < tokenIds.length; ++i) { uint256 tokenId = tokenIds[i]; address owner = ownerOf(tokenId); // Check if caller is authorized to burn the token. if (checkIfAuthorizedToBurn) { if ( msg.sender != owner && getApproved[tokenId] != msg.sender && !isApprovedForAll[owner][msg.sender] ) { revert NotAuthorized(); } } // Must be retrieved before updating voting power for token to be burned. uint96 votingPower = votingPowerByTokenId[tokenId].safeCastUint256ToUint96(); totalVotingPowerBurned += votingPower; // Update voting power for token to be burned. delete votingPowerByTokenId[tokenId]; emit PartyCardIntrinsicVotingPowerSet(tokenId, 0); _adjustVotingPower(owner, -votingPower.safeCastUint96ToInt192(), address(0)); // Burn token. _burn(tokenId); emit Burn(msg.sender, tokenId, votingPower); } // Update minted voting power. mintedVotingPower -= totalVotingPowerBurned; emit BatchMetadataUpdate(0, type(uint256).max); } /// @notice Burn governance NFT and remove its voting power. /// @param tokenId The ID of the governance NFTs to burn. function burn(uint256 tokenId) external { uint256[] memory tokenIds = new uint256[](1); tokenIds[0] = tokenId; burn(tokenIds); } /// @notice Set the timestamp until which ragequit is enabled. /// @param newRageQuitTimestamp The new ragequit timestamp. function setRageQuit(uint40 newRageQuitTimestamp) external { _assertHost(); // Prevent disabling ragequit after initialization. if (newRageQuitTimestamp == DISABLE_RAGEQUIT_PERMANENTLY) { revert CannotDisableRageQuitAfterInitializationError(); } // Prevent enabling ragequit if distributions can be created without a vote. if ( _getSharedProposalStorage().opts.distributionsConfig == DistributionsConfig.AllowedWithoutVote ) revert CannotEnableRageQuitIfNotDistributionsRequireVoteError(); uint40 oldRageQuitTimestamp = rageQuitTimestamp; // Prevent setting timestamp if it is permanently enabled/disabled. if ( oldRageQuitTimestamp == ENABLE_RAGEQUIT_PERMANENTLY || oldRageQuitTimestamp == DISABLE_RAGEQUIT_PERMANENTLY ) { revert FixedRageQuitTimestampError(oldRageQuitTimestamp); } rageQuitTimestamp = newRageQuitTimestamp; emit RageQuitSet(oldRageQuitTimestamp, newRageQuitTimestamp); } /// @notice Burn a governance NFT and withdraw a fair share of fungible tokens from the party. /// @param tokenIds The IDs of the governance NFTs to burn. /// @param withdrawTokens The fungible tokens to withdraw. Specify the /// `ETH_ADDRESS` value to withdraw ETH. /// @param minWithdrawAmounts The minimum amount of to withdraw for each token. /// @param receiver The address to receive the withdrawn tokens. function rageQuit( uint256[] calldata tokenIds, IERC20[] calldata withdrawTokens, uint256[] calldata minWithdrawAmounts, address receiver ) external { if (tokenIds.length == 0) revert NothingToBurnError(); // Check if called by an authority. bool isAuthority_ = isAuthority[msg.sender]; // Check if ragequit is allowed. uint40 currentRageQuitTimestamp = rageQuitTimestamp; if (!isAuthority_) { if (currentRageQuitTimestamp != ENABLE_RAGEQUIT_PERMANENTLY) { if ( currentRageQuitTimestamp == DISABLE_RAGEQUIT_PERMANENTLY || currentRageQuitTimestamp < block.timestamp ) { revert CannotRageQuitError(currentRageQuitTimestamp); } } } // Used as a reentrancy guard. Will be updated back after ragequit. rageQuitTimestamp = DISABLE_RAGEQUIT_PERMANENTLY; lastTotalVotingPowerChangeTimestamp = uint40(block.timestamp); // Sum up total amount of each token to withdraw. uint256[] memory withdrawAmounts = new uint256[](withdrawTokens.length); { IERC20 prevToken; for (uint256 i; i < withdrawTokens.length; ++i) { // Check if order of tokens to transfer is valid. // Prevent null and duplicate transfers. if (prevToken >= withdrawTokens[i]) revert InvalidTokenOrderError(); prevToken = withdrawTokens[i]; // Check token's balance. uint256 balance = address(withdrawTokens[i]) == ETH_ADDRESS ? address(this).balance : withdrawTokens[i].balanceOf(address(this)); // Add fair share of tokens from the party to total. for (uint256 j; j < tokenIds.length; ++j) { // Must be retrieved before burning the token. withdrawAmounts[i] += (balance * getVotingPowerShareOf(tokenIds[j])) / 1e18; } } } { // Burn caller's party cards. This will revert if caller is not the // the owner or approved for any of the card they are attempting to // burn, not an authority, or if there are duplicate token IDs. uint96 totalVotingPowerBurned = _burnAndUpdateVotingPower(tokenIds, !isAuthority_); // Update total voting power of party. _getSharedProposalStorage().governanceValues.totalVotingPower -= totalVotingPowerBurned; } { uint16 feeBps_ = feeBps; for (uint256 i; i < withdrawTokens.length; ++i) { IERC20 token = withdrawTokens[i]; uint256 amount = withdrawAmounts[i]; // Take fee from amount. uint256 fee = (amount * feeBps_) / 1e4; if (fee > 0) { amount -= fee; // Transfer fee to fee recipient. if (address(token) == ETH_ADDRESS) { payable(feeRecipient).transferEth(fee); } else { token.compatTransfer(feeRecipient, fee); } } // Check amount is at least minimum. uint256 minAmount = minWithdrawAmounts[i]; if (amount < minAmount) { revert BelowMinWithdrawAmountError(amount, minAmount); } if (amount > 0) { // Transfer token from party to recipient. if (address(token) == ETH_ADDRESS) { payable(receiver).transferEth(amount); } else { token.compatTransfer(receiver, amount); } } } } // Update ragequit timestamp back to before. rageQuitTimestamp = currentRageQuitTimestamp; emit RageQuit(msg.sender, tokenIds, withdrawTokens, receiver); } /// @inheritdoc ERC721 function transferFrom(address owner, address to, uint256 tokenId) public override { // 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 { // 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 { // super.safeTransferFrom() will call transferFrom() first which will // transfer voting power. super.safeTransferFrom(owner, to, tokenId, data); } /// @notice Add a new authority. /// @dev Used in `AddAuthorityProposal`. Only the party itself can add /// authorities to prevent it from being used anywhere else. function addAuthority(address authority) external onlySelf { isAuthority[authority] = true; emit AuthorityAdded(authority); } /// @notice Relinquish the authority role. function abdicateAuthority() external { _assertAuthority(); delete isAuthority[msg.sender]; emit AuthorityRemoved(msg.sender); } 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.20; import { ITokenDistributor } from "../distribution/ITokenDistributor.sol"; import { ReadOnlyDelegateCall } from "../utils/ReadOnlyDelegateCall.sol"; import { IERC721 } from "../tokens/IERC721.sol"; import { IERC20 } from "../tokens/IERC20.sol"; import { IERC721Receiver } from "../tokens/IERC721Receiver.sol"; import { ERC1155TokenReceiverBase } from "../vendor/solmate/ERC1155.sol"; import { LibERC20Compat } from "../utils/LibERC20Compat.sol"; import { LibRawResult } from "../utils/LibRawResult.sol"; import { LibSafeCast } from "../utils/LibSafeCast.sol"; import { IERC4906 } from "../utils/IERC4906.sol"; import { IGlobals } from "../globals/IGlobals.sol"; import { LibGlobals } from "../globals/LibGlobals.sol"; import { IProposalExecutionEngine } from "../proposals/IProposalExecutionEngine.sol"; import { LibProposal } from "../proposals/LibProposal.sol"; import { ProposalStorage } from "../proposals/ProposalStorage.sol"; import { Implementation } from "../utils/Implementation.sol"; import { Party } from "./Party.sol"; /// @notice Base contract for a Party encapsulating all governance functionality. /// @dev This contract uses IERC4906 however does not comply with the standard /// since it does emit metadata events when distributions are claimed or /// when a MetadaProvider changes its URI. This decision was made /// intentionally which is why ERC4906 is not included in `supportsInterface`. abstract contract PartyGovernance is ProposalStorage, Implementation, IERC4906, 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 recipient for distributions. address payable feeRecipient; } // 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. 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 // Number of total voting power at time proposal created. uint96 totalVotingPower; // Number of hosts at time proposal created uint8 numHosts; // Number of hosts that accepted proposal uint8 numHostsAccepted; // Cached vote duration from proposal creation. uint40 voteDuration; // Cached execution delay from proposal creation. uint40 executionDelay; // Cached pass threshold bps from proposal creation. uint16 passThresholdBps; } // 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 PartyDelegateUpdated(address indexed owner, address indexed delegate); event HostStatusTransferred(address oldHost, address newHost); event EmergencyExecuteDisabled(); event PartyVotingSnapshotCreated( address indexed voter, uint40 timestamp, uint96 delegatedVotingPower, uint96 intrinsicVotingPower, bool isDelegated ); error MismatchedPreciousListLengths(); error BadProposalStatusError(ProposalStatus status); error BadProposalHashError(bytes32 proposalHash, bytes32 actualHash); error ExecutionTimeExceededError(uint40 maxExecutableTime, uint40 timestamp); error NotAuthorized(); error InvalidDelegateError(); error BadPreciousListError(); error OnlyWhenEmergencyActionsAllowedError(); error OnlyWhenEnabledError(); error AlreadyVotedError(address voter); error InvalidNewHostError(); error ProposalCannotBeCancelledYetError(uint40 currentTime, uint40 cancelTime); error InvalidBpsError(uint16 bps); error InvalidGovernanceParameter(uint256 value); error DistributionsRequireVoteError(); error PartyNotStartedError(); error CannotModifyTotalVotingPowerAndAcceptError(); error TooManyHosts(); uint256 private constant UINT40_HIGH_BIT = 1 << 39; uint96 private constant 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 timestamp of the last time total voting power changed in the party. uint40 public lastTotalVotingPowerChangeTimestamp; /// @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; /// @notice Number of hosts for this party uint8 public numHosts; /// @notice ProposalState by proposal ID. mapping(uint256 => ProposalState) private _proposalStateByProposalId; /// @notice Snapshots of voting power per user, each sorted by increasing time. mapping(address => VotingPowerSnapshot[]) private _votingPowerSnapshotsByVoter; function _assertHost() internal view { if (!isHost[msg.sender]) { revert NotAuthorized(); } } function _assertActiveMember() internal view { VotingPowerSnapshot memory snap = _getLastVotingPowerSnapshotForVoter(msg.sender); // Must have either delegated voting power or intrinsic voting power. if (snap.intrinsicVotingPower == 0 && snap.delegatedVotingPower == 0) { revert NotAuthorized(); } } // Only the party DAO multisig can call. modifier onlyPartyDao() { { address partyDao = _GLOBALS.getAddress(LibGlobals.GLOBAL_DAO_WALLET); if (msg.sender != partyDao) { revert NotAuthorized(); } } _; } // 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 NotAuthorized(); } _; } // Only if `emergencyExecuteDisabled` is not true. modifier onlyWhenEmergencyExecuteAllowed() { if (emergencyExecuteDisabled) { revert OnlyWhenEmergencyActionsAllowedError(); } _; } function _assertNotGloballyDisabled() internal view { 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 govOpts, ProposalStorage.ProposalEngineOpts memory proposalEngineOpts, IERC721[] memory preciousTokens, uint256[] memory preciousTokenIds ) internal virtual { // Check BPS are valid. if (govOpts.feeBps > 1e4) { revert InvalidBpsError(govOpts.feeBps); } if (govOpts.voteDuration < 1 hours) { revert InvalidGovernanceParameter(govOpts.voteDuration); } if (govOpts.passThresholdBps == 0 || govOpts.passThresholdBps > 1e4) { revert InvalidBpsError(govOpts.passThresholdBps); } if (govOpts.executionDelay == 0 || govOpts.executionDelay > 30 days) { revert InvalidGovernanceParameter(govOpts.executionDelay); } // Initialize the proposal execution engine. _initProposalImpl( IProposalExecutionEngine(_GLOBALS.getAddress(LibGlobals.GLOBAL_PROPOSAL_ENGINE_IMPL)), abi.encode(proposalEngineOpts) ); // Set the governance parameters. _getSharedProposalStorage().governanceValues = GovernanceValues({ voteDuration: govOpts.voteDuration, executionDelay: govOpts.executionDelay, passThresholdBps: govOpts.passThresholdBps, totalVotingPower: govOpts.totalVotingPower }); numHosts = uint8(govOpts.hosts.length); // Set fees. feeBps = govOpts.feeBps; feeRecipient = govOpts.feeRecipient; // Set the precious list. _setPreciousList(preciousTokens, preciousTokenIds); // Set the party hosts. if (govOpts.hosts.length > type(uint8).max) { revert TooManyHosts(); } for (uint256 i = 0; i < govOpts.hosts.length; ++i) { isHost[govOpts.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 { bytes4 functionSelector = bytes4(msg.data[0:4]); if ( functionSelector == ERC1155TokenReceiverBase.onERC1155BatchReceived.selector || functionSelector == ERC1155TokenReceiverBase.onERC1155Received.selector || functionSelector == IERC721Receiver.onERC721Received.selector ) { assembly { let freeMem := mload(0x40) mstore(freeMem, functionSelector) mstore(0x40, add(freeMem, 0x20)) return(freeMem, 0x20) } } _readOnlyDelegateCall(address(_getSharedProposalStorage().engineImpl), msg.data); } /// @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 pure virtual returns (bool) { return interfaceId == type(IERC721Receiver).interfaceId || interfaceId == type(ERC1155TokenReceiverBase).interfaceId; } /// @notice Get the current `ProposalExecutionEngine` instance. function getProposalExecutionEngine() external view returns (IProposalExecutionEngine) { return _getSharedProposalStorage().engineImpl; } /// @notice Get the current `ProposalEngineOpts` options. function getProposalEngineOpts() external view returns (ProposalEngineOpts memory) { return _getSharedProposalStorage().opts; } /// @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) { return _getSharedProposalStorage().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 { _adjustVotingPower(msg.sender, 0, delegate); } /// @notice Transfer party host status to another. /// @param newPartyHost The address of the new host. function abdicateHost(address newPartyHost) external { _assertHost(); // 0 is a special case burn address. if (newPartyHost != address(0)) { // Can only abdicate host revert InvalidNewHostError(); } else { // Burned the host status --numHosts; } 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( uint256 amount, ITokenDistributor.TokenType tokenType, address token, uint256 tokenId ) external returns (ITokenDistributor.DistributionInfo memory distInfo) { _assertNotGloballyDisabled(); // Ignore if the party is calling functions on itself, like with // `FractionalizeProposal` and `DistributionProposal`. if (msg.sender != address(this)) { // Must not require a vote to create a distribution, otherwise // distributions can only be created through a distribution // proposal. if ( _getSharedProposalStorage().opts.distributionsConfig != DistributionsConfig.AllowedWithoutVote ) { revert DistributionsRequireVoteError(); } // Must be an active member. VotingPowerSnapshot memory snap = _getLastVotingPowerSnapshotForVoter(msg.sender); if (snap.intrinsicVotingPower == 0 && snap.delegatedVotingPower == 0) { revert NotAuthorized(); } } // Prevent creating a distribution if the party has not started. if (_getSharedProposalStorage().governanceValues.totalVotingPower == 0) { revert PartyNotStartedError(); } // Get the address of the token distributor. ITokenDistributor distributor = ITokenDistributor( _GLOBALS.getAddress(LibGlobals.GLOBAL_TOKEN_DISTRIBUTOR) ); emit DistributionCreated(tokenType, token, tokenId); _emitMetadataUpdateEvent(); // Create a native token distribution. address payable feeRecipient_ = feeRecipient; uint16 feeBps_ = feeBps; if (tokenType == ITokenDistributor.TokenType.Native) { return distributor.createNativeDistribution{ value: amount }( Party(payable(address(this))), feeRecipient_, feeBps_ ); } // Otherwise must be an ERC20 token distribution. assert(tokenType == ITokenDistributor.TokenType.Erc20); IERC20(token).compatTransfer(address(distributor), amount); return distributor.createErc20Distribution( IERC20(token), Party(payable(address(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 returns (uint256 proposalId) { _assertActiveMember(); proposalId = ++lastProposalId; ProposalStorage.GovernanceValues memory gv = _getSharedProposalStorage().governanceValues; // 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, totalVotingPower: gv.totalVotingPower, numHosts: numHosts, numHostsAccepted: 0, voteDuration: gv.voteDuration, executionDelay: gv.executionDelay, passThresholdBps: gv.passThresholdBps }), getProposalHash(proposal) ); emit Proposed(proposalId, msg.sender, proposal); accept(proposalId, latestSnapIndex); _emitMetadataUpdateEvent(); } /// @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 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); } } // Prevent voting in the same block as the last total voting power // change. This is to prevent an exploit where a member can, for // example, rage quit to reduce the total voting power of the party, // then propose and vote in the same block since `getVotingPowerAt()` // uses `values.proposedTime - 1`. This would allow them to use the // voting power snapshot just before their card was burned to vote, // potentially passing a proposal that would have otherwise not passed. if (lastTotalVotingPowerChangeTimestamp == block.timestamp) { revert CannotModifyTotalVotingPowerAndAcceptError(); } // 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; if (isHost[msg.sender]) { ++values.numHostsAccepted; } info.values = values; emit ProposalAccepted(proposalId, msg.sender, votingPower); // Update the proposal status if it has reached the pass threshold. if ( values.passedTime == 0 && (uint256(values.votes) * 1e4) / uint256(values.totalVotingPower) >= uint256(values.passThresholdBps) ) { info.values.passedTime = uint40(block.timestamp); emit ProposalPassed(proposalId); _emitMetadataUpdateEvent(); } 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 { _assertHost(); // 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); _emitMetadataUpdateEvent(); } /// @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 { _assertNotGloballyDisabled(); _assertActiveMember(); // 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 { _assertActiveMember(); // 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(_getSharedProposalStorage().engineImpl) ).delegatecall(abi.encodeCall(IProposalExecutionEngine.cancelProposal, (proposalId))); if (!success) { resultData.rawRevert(); } } emit ProposalCancelled(proposalId); _emitMetadataUpdateEvent(); } /// @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 { (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 { 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( _getSharedProposalStorage().engineImpl ).delegatecall( abi.encodeCall(IProposalExecutionEngine.executeProposal, (executeParams)) ); if (!success) { resultData.rawRevert(); } nextProgressData = abi.decode(resultData, (bytes)); } emit ProposalExecuted(proposalId, msg.sender, nextProgressData); _emitMetadataUpdateEvent(); // 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; // This event is emitted even if the delegate did not change. emit PartyDelegateUpdated(voter, delegate); // Handle rebalancing delegates. _rebalanceDelegates(voter, oldDelegate, delegate, oldSnap, newSnap); } // 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 { emit PartyVotingSnapshotCreated( voter, snap.timestamp, snap.delegatedVotingPower, snap.intrinsicVotingPower, snap.isDelegated ); 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 pure returns (uint256) { uint256 flags = 0; if (_isUnanimousVotes(pv.votes, pv.totalVotingPower)) { flags = flags | LibProposal.PROPOSAL_FLAG_UNANIMOUS; } if (_hostsAccepted(pv.numHosts, pv.numHostsAccepted)) { flags = flags | LibProposal.PROPOSAL_FLAG_HOSTS_ACCEPT; } return flags; } 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); if (pv.passedTime != 0) { // Ready. if (pv.passedTime + pv.executionDelay <= t) { return ProposalStatus.Ready; } // If unanimous, we skip the execution delay. if (_isUnanimousVotes(pv.votes, pv.totalVotingPower)) { return ProposalStatus.Ready; } // If all hosts voted, skip execution delay if (_hostsAccepted(pv.numHosts, pv.numHostsAccepted)) { return ProposalStatus.Ready; } // Passed. return ProposalStatus.Passed; } // Voting window expired. if (pv.proposedTime + pv.voteDuration <= t) { return ProposalStatus.Defeated; } return ProposalStatus.Voting; } function _isUnanimousVotes( uint96 totalVotes, uint96 totalVotingPower ) private pure returns (bool) { uint256 acceptanceRatio = (uint256(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 _hostsAccepted( uint8 snapshotNumHosts, uint8 numHostsAccepted ) private pure returns (bool) { return snapshotNumHosts > 0 && snapshotNumHosts == numHostsAccepted; } 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) } } function _emitMetadataUpdateEvent() internal { emit BatchMetadataUpdate(0, type(uint256).max); } // 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.20; 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); error Uint96ToUint16CastOutOfRange(uint96 u96); 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 safeCastUint256ToUint160(uint256 v) internal pure returns (uint160) { if (v > uint256(type(uint160).max)) { revert Uint256ToUint128CastOutOfRangeError(v); } return uint160(v); } function safeCastUint256ToInt192(uint256 v) internal pure returns (int192) { if (v > uint256(uint192(type(int192).max))) { revert Uint256ToInt192CastOutOfRange(v); } return int192(uint192(v)); } function safeCastUint96ToUint16(uint96 v) internal pure returns (uint16) { if (v > uint96(type(uint16).max)) { revert Uint96ToUint16CastOutOfRange(v); } return uint16(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.20; library LibAddress { error EthTransferFailed(address receiver, bytes errData); // Transfer ETH with full gas stipend. function transferEth(address payable receiver, uint256 amount) internal { if (amount == 0) return; (bool s, bytes memory r) = receiver.call{ value: amount }(""); if (!s) { revert EthTransferFailed(receiver, r); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.19; 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: GPL-3.0 pragma solidity 0.8.20; import "../utils/Implementation.sol"; // Single registry of global values controlled by multisig. // See `LibGlobals` for all valid keys. interface IGlobals { function multiSig() external view returns (address); 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: AGPL-3.0-only pragma solidity >=0.8.0; 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) /// @dev Modified from Solmate abstract contract ERC721 is IERC721, EIP165 { error NotMinted(); error ZeroAddress(); error UnsafeRecipient(); error Unauthorized(); /*////////////////////////////////////////////////////////////// METADATA STORAGE/LOGIC //////////////////////////////////////////////////////////////*/ string public name; string public symbol; function tokenURI(uint256 id /* view */) public 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) { owner = _ownerOf[id]; if (owner == address(0)) { revert NotMinted(); } } function balanceOf(address owner) public view virtual returns (uint256) { if (owner == address(0)) { revert ZeroAddress(); } 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]; if (msg.sender != owner && !isApprovedForAll[owner][msg.sender]) { revert Unauthorized(); } 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 { if (from != _ownerOf[id]) { revert Unauthorized(); } if (to == address(0)) { revert ZeroAddress(); } if ( msg.sender != from && !isApprovedForAll[from][msg.sender] && msg.sender != getApproved[id] ) { revert Unauthorized(); } // 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); if ( to.code.length != 0 && ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") != ERC721TokenReceiver.onERC721Received.selector ) { revert UnsafeRecipient(); } } function safeTransferFrom( address from, address to, uint256 id, bytes calldata data ) public virtual { transferFrom(from, to, id); if ( to.code.length != 0 && ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) != ERC721TokenReceiver.onERC721Received.selector ) { revert UnsafeRecipient(); } } /*////////////////////////////////////////////////////////////// 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 { if (to == address(0)) { revert ZeroAddress(); } if (_ownerOf[id] != address(0)) { revert Unauthorized(); } // 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]; if (owner == address(0)) { revert Unauthorized(); } // 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); if ( to.code.length != 0 && ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") != ERC721TokenReceiver.onERC721Received.selector ) { revert UnsafeRecipient(); } } function _safeMint(address to, uint256 id, bytes memory data) internal virtual { _mint(to, id); if ( to.code.length != 0 && ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) != ERC721TokenReceiver.onERC721Received.selector ) { revert UnsafeRecipient(); } } } /// @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: GPL-3.0 pragma solidity 0.8.20; 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="M188 444.3h2.4l2.6 8.2 2.7-8.2h2.3l-3.7 10.7h-2.8l-3.5-10.7zm10.5 5.3c0-3.2 2.2-5.6 5.3-5.6 3.1 0 5.3 2.3 5.3 5.6 0 3.2-2.2 5.5-5.3 5.5-3.1.1-5.3-2.2-5.3-5.5zm5.3 3.5c1.8 0 3-1.3 3-3.4 0-2.1-1.1-3.5-3-3.5s-3 1.3-3 3.5c0 2.1 1.1 3.4 3 3.4zm8.7-6.7h-3.1v-2.1h8.4v2.1h-3.1v8.6h-2.2v-8.6zm6.9-2.1h2.2V455h-2.2v-10.7zm4.3 0h2.9l4 8.2v-8.2h2.1V455h-2.9l-4-8.2v8.2h-2.1v-10.7zm10.6 5.4c0-3.4 2.3-5.6 6-5.6 1.2 0 2.3.2 3.1.6v2.3c-.9-.6-1.9-.8-3.1-.8-2.4 0-3.8 1.3-3.8 3.5 0 2.1 1.3 3.4 3.5 3.4.5 0 .9-.1 1.3-.2v-2.2h-2.2v-1.9h4.3v5.6c-1 .5-2.2.8-3.4.8-3.5 0-5.7-2.2-5.7-5.5zm15.1-5.4h4.3c2.3 0 3.7 1.3 3.7 3.5s-1.4 3.5-3.7 3.5h-2.1v3.7h-2.2v-10.7zm4.1 5c1.1 0 1.6-.5 1.6-1.5s-.5-1.5-1.6-1.5h-1.9v2.9h1.9zm4.8.3c0-3.2 2.2-5.6 5.3-5.6 3.1 0 5.3 2.3 5.3 5.6 0 3.2-2.2 5.5-5.3 5.5-3.1.1-5.3-2.2-5.3-5.5zm5.3 3.5c1.8 0 3-1.3 3-3.4 0-2.1-1.1-3.5-3-3.5s-3 1.3-3 3.5c0 2.1 1.1 3.4 3 3.4zm5.8-8.8h2.3l1.7 7.8 1.9-7.8h2.4l1.8 7.8 1.8-7.8h2.3l-2.7 10.7h-2.5l-1.9-8.2-1.8 8.2h-2.5l-2.8-10.7zm15.4 0h6.9v2.1H287v2.2h4.5v2.1H287v2.3h4.9v2.1h-7v-10.8zm9 0h4.5c2 0 3.3 1.3 3.3 3.2 0 1.9-1.2 3.1-3 3.2l3.5 4.3h-2.7l-3.5-4.4v4.4h-2.1v-10.7zm4.1 4.8c1 0 1.5-.5 1.5-1.4 0-.9-.6-1.4-1.5-1.4h-2v2.9h2zM30 444.3h4.3c3 0 5.2 2.1 5.2 5.4s-2.1 5.4-5.2 5.4H30v-10.8zm4 8.6c2.1 0 3.2-1.2 3.2-3.2s-1.2-3.3-3.2-3.3h-1.8v6.5H34zm7.7-8.6h2.2V455h-2.2v-10.7zm4.8 10V452c1 .7 2.1 1.1 3.2 1.1s1.7-.5 1.7-1.2-.4-1-1.2-1.2l-1.2-.3c-1.8-.5-2.7-1.5-2.7-3.1 0-2 1.5-3.2 3.9-3.2 1 0 2.1.2 2.9.7v2.3c-.9-.6-1.9-.8-3-.8-.9 0-1.6.4-1.6 1.1 0 .6.4.9 1.2 1.1l1.3.4c1.8.5 2.6 1.4 2.6 3.1 0 2.1-1.5 3.4-3.8 3.4-1.1-.2-2.3-.5-3.3-1.1zm12-7.9h-3.1v-2.1h8.4v2.1h-3.1v8.6h-2.2v-8.6zm7.5-2.1h4.5c2 0 3.3 1.3 3.3 3.2 0 1.9-1.2 3.1-3 3.2l3.5 4.3h-2.7l-3.5-4.4v4.4H66v-10.7zm4.1 4.8c1 0 1.5-.5 1.5-1.4s-.6-1.4-1.5-1.4h-2v2.9h2zm6.1-4.8h2.2V455h-2.2v-10.7zm5 0h4.5c2 0 3.2 1.1 3.2 2.8 0 1.1-.5 1.9-1.4 2.3 1.1.3 1.8 1.3 1.8 2.5 0 1.9-1.3 3.1-3.5 3.1h-4.6v-10.7zm4.2 4.4c.9 0 1.4-.5 1.4-1.3s-.5-1.3-1.4-1.3h-2.1v2.5l2.1.1zm.3 4.4c.9 0 1.5-.5 1.5-1.3s-.6-1.3-1.5-1.3h-2.4v2.6h2.4zm5.7-2.5v-6.3h2.2v6.3c0 1.6.9 2.5 2.3 2.5s2.3-.9 2.3-2.5v-6.3h2.2v6.3c0 2.9-1.7 4.6-4.5 4.6s-4.6-1.7-4.5-4.6zm14.2-4.2h-3.1v-2.1h8.4v2.1h-3.1v8.6h-2.2v-8.6zm7.5-2.1h2.2V455h-2.2v-10.7zm4.5 5.3c0-3.2 2.2-5.6 5.3-5.6s5.3 2.3 5.3 5.6-2.2 5.5-5.3 5.5-5.3-2.2-5.3-5.5zm5.3 3.5c1.8 0 3-1.3 3-3.5s-1.2-3.5-3-3.5-3 1.3-3 3.5 1.1 3.5 3 3.5zm7.5-8.8h2.9l4 8.2v-8.2h2.1V455h-2.9l-4-8.2v8.2h-2.1v-10.7zm11.7 10V452c1 .7 2.1 1.1 3.2 1.1s1.7-.5 1.7-1.2-.4-1-1.2-1.2l-1.2-.3c-1.8-.5-2.6-1.5-2.6-3.1 0-2 1.5-3.2 3.9-3.2 1.1 0 2.1.2 2.9.7v2.3c-.9-.6-1.9-.8-3-.8-.9 0-1.6.4-1.6 1.1 0 .6.4.9 1.2 1.1l1.3.4c1.8.5 2.6 1.4 2.6 3.1 0 2.1-1.5 3.4-3.8 3.4a9.7 9.7 0 0 1-3.4-1.1zM30 259.3h4.3c2.2 0 3.7 1.3 3.7 3.5s-1.4 3.5-3.7 3.5h-2.1v3.7H30v-10.7zm4.1 5c1.1 0 1.6-.5 1.6-1.5s-.5-1.5-1.6-1.5h-1.9v2.9h1.9zm6.1-5h4.5c2 0 3.3 1.3 3.3 3.2 0 1.9-1.2 3.1-3 3.2l3.5 4.3h-2.7l-3.5-4.4v4.4h-2.1v-10.7zm4.1 4.8c1 0 1.5-.5 1.5-1.4s-.6-1.4-1.5-1.4h-2v2.9h2zm5.4.5c0-3.2 2.2-5.6 5.3-5.6s5.3 2.3 5.3 5.6-2.2 5.5-5.3 5.5-5.3-2.2-5.3-5.5zm5.3 3.5c1.8 0 3-1.3 3-3.5s-1.2-3.5-3-3.5-3 1.3-3 3.5 1.1 3.5 3 3.5zm7.6-8.8h4.3c2.2 0 3.7 1.3 3.7 3.5s-1.4 3.5-3.7 3.5h-2.1v3.7h-2.2v-10.7zm4.1 5c1.1 0 1.6-.5 1.6-1.5s-.6-1.5-1.6-1.5h-1.9v2.9h1.9zm5.4.4c0-3.2 2.2-5.6 5.3-5.6s5.3 2.3 5.3 5.6-2.2 5.5-5.3 5.5-5.3-2.3-5.3-5.5zm5.4 3.4c1.8 0 3-1.3 3-3.5s-1.2-3.5-3-3.5-3 1.3-3 3.5 1.1 3.5 3 3.5zm7.2 1.2V267c1 .7 2.1 1.1 3.2 1.1s1.7-.5 1.7-1.2-.4-1-1.2-1.2l-1.2-.3c-1.8-.5-2.7-1.5-2.7-3.1 0-2 1.5-3.2 3.9-3.2 1.1 0 2.1.2 2.9.7v2.3c-.9-.6-1.9-.8-3-.8-.9 0-1.6.4-1.6 1.1 0 .6.4.9 1.2 1.1l1.3.4c1.8.5 2.6 1.4 2.6 3.1 0 2.1-1.5 3.4-3.8 3.4-1.1-.2-2.3-.5-3.3-1.1zm12.2-10h2.8l3.7 10.7h-2.3l-.8-2.5h-4l-.8 2.5h-2.2l3.6-10.7zm2.8 6.3-1.4-4.2-1.4 4.2h2.8zm5.7-6.3h2.2v8.6h4.7v2.1h-6.9v-10.7zm9.1 10V267c1 .7 2.1 1.1 3.2 1.1s1.7-.5 1.7-1.2-.4-1-1.2-1.2l-1.2-.3c-1.8-.5-2.7-1.5-2.7-3.1 0-2 1.5-3.2 3.9-3.2 1.1 0 2.1.2 2.9.7v2.3c-.9-.6-1.9-.8-3-.8-.9 0-1.6.4-1.6 1.1 0 .6.4.9 1.2 1.1l1.3.4c1.8.5 2.6 1.4 2.6 3.1 0 2.1-1.5 3.4-3.8 3.4-1.1-.2-2.3-.5-3.3-1.1zm-84.5-70h2.9l4 8.2v-8.2H39V210h-2.9l-4-8.2v8.2H30v-10.7zm14.7 0h2.8l3.7 10.7h-2.3l-.8-2.6h-4l-.8 2.6H41l3.7-10.7zm2.8 6.2-1.4-4.2-1.4 4.2h2.8zm5.7-6.2h3.3l2.5 8.2 2.5-8.2h3.3V210h-2v-8.6L60 210h-2.1l-2.7-8.5v8.5h-2v-10.7zm14.4 0h6.9v2.1h-4.8v2.2h4.4v2.1h-4.4v2.3h4.9v2.1h-7v-10.8z" /><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: GPL-3.0 pragma solidity 0.8.20; import "../tokens/IERC20.sol"; import "../party/Party.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. Party 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; // Total shares at time distribution was created. uint96 totalShares; } event DistributionCreated(Party indexed party, DistributionInfo info); event DistributionFeeClaimed( Party indexed party, address indexed feeRecipient, TokenType tokenType, address token, uint256 amount ); event DistributionClaimedByPartyToken( Party 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( Party 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, Party 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 info Information on the distribution being claimed. /// @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( DistributionInfo calldata info, 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(Party 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( Party 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( Party party, uint256 distributionId ) external view returns (uint128); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.20; 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: 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; interface IERC721Receiver { function onERC721Received( address operator, address from, uint256 tokenId, bytes memory data ) external returns (bytes4); }
// SPDX-License-Identifier: AGPL-3.0-only // 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: GPL-3.0 pragma solidity 0.8.20; import "../tokens/IERC20.sol"; // Compatibility helpers for ERC20s. library LibERC20Compat { error NotATokenError(IERC20 token); error TokenTransferFailedError(IERC20 token, address to, uint256 amount); error TokenApprovalFailed(IERC20 token, address spender, 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); } // Perform an `IERC20.transferFrom()` handling non-compliant implementations. function compatTransferFrom(IERC20 token, address from, address to, uint256 amount) internal { (bool s, bytes memory r) = address(token).call( abi.encodeCall(IERC20.transferFrom, (from, 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); } function compatApprove(IERC20 token, address spender, uint256 amount) internal { (bool s, bytes memory r) = address(token).call( abi.encodeCall(IERC20.approve, (spender, 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 TokenApprovalFailed(token, spender, amount); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.20; 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: Apache-2.0 pragma solidity ^0.8; interface IERC4906 { event MetadataUpdate(uint256 _tokenId); event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.20; // Valid keys in `IGlobals`. Append-only. library LibGlobals { // The Globals commented out below were depreciated in 1.2; factories // can now choose the implementation address to deploy and no longer // deploy the latest implementation. They will no longer be updated // in future releases. // // See https://github.com/PartyDAO/party-migrations for // implementation addresses by release. 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; // uint256 internal constant GLOBAL_ROLLING_AUCTION_CF_IMPL = 24; // uint256 internal constant GLOBAL_COLLECTION_BATCH_BUY_CF_IMPL = 25; uint256 internal constant GLOBAL_METADATA_REGISTRY = 26; // uint256 internal constant GLOBAL_CROWDFUND_FACTORY = 27; // uint256 internal constant GLOBAL_INITIAL_ETH_CF_IMPL = 28; // uint256 internal constant GLOBAL_RERAISE_ETH_CF_IMPL = 29; uint256 internal constant GLOBAL_SEAPORT = 30; uint256 internal constant GLOBAL_CONDUIT_CONTROLLER = 31; uint256 internal constant GLOBAL_OFF_CHAIN_SIGNATURE_VALIDATOR = 32; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.20; 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 payable 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.20; import "../tokens/IERC721.sol"; library LibProposal { uint256 internal constant PROPOSAL_FLAG_UNANIMOUS = 0x1; uint256 internal constant PROPOSAL_FLAG_HOSTS_ACCEPT = 0x2; 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.20; 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; ProposalEngineOpts opts; GovernanceValues governanceValues; } /// @notice Governance values stored for a party struct GovernanceValues { uint40 voteDuration; uint40 executionDelay; uint16 passThresholdBps; uint96 totalVotingPower; } enum DistributionsConfig { AllowedWithoutVote, AllowedWithVote, NotAllowed } struct ProposalEngineOpts { // Whether the party can add new authorities with the add authority proposal. bool enableAddAuthorityProposal; // Whether the party can spend ETH from the party's balance with // arbitrary call proposals. bool allowArbCallsToSpendPartyEth; // Whether operators can be used. bool allowOperators; // Distributions config for the party. DistributionsConfig distributionsConfig; } uint256 internal constant PROPOSAL_FLAG_UNANIMOUS = 0x1; uint256 private constant SHARED_STORAGE_SLOT = uint256(keccak256("ProposalStorage.SharedProposalStorage")); 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() internal pure returns (SharedProposalStorage storage stor) { uint256 s = SHARED_STORAGE_SLOT; assembly { stor.slot := s } } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.20; // Base contract for all contracts intended to be delegatecalled into. abstract contract Implementation { event Initialized(); error AlreadyInitialized(); error OnlyDelegateCallError(); /// @notice The address of the implementation contract. address public immutable implementation; /// @notice Whether or not the implementation has been initialized. bool public initialized; constructor() { implementation = address(this); } // Reverts if the current function context is not inside of a delegatecall. modifier onlyDelegateCall() virtual { if (address(this) == implementation) { revert OnlyDelegateCallError(); } _; } modifier onlyInitialize() { if (initialized) revert AlreadyInitialized(); initialized = true; emit Initialized(); _; } /// @notice The address of the implementation contract. /// @dev This is an alias for `implementation` for backwards compatibility. function IMPL() external view returns (address) { return implementation; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.19; /** * @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: GPL-3.0 pragma solidity 0.8.20; 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 pure virtual returns (bool) { return interfaceId == this.supportsInterface.selector; } }
// 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. ); /// @solidity memory-safe-assembly 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) { /// @solidity memory-safe-assembly 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) } } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.20; 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: 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); }
{ "remappings": [ "forge-std/=lib/forge-std/src/", "openzeppelin/=lib/openzeppelin-contracts/", "solmate/=lib/solmate/src/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "party-addresses/=lib/party-addresses/" ], "optimizer": { "enabled": true, "runs": 50 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "shanghai", "libraries": {}, "viaIR": true }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IGlobals","name":"globals","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"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":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minAmount","type":"uint256"}],"name":"BelowMinWithdrawAmountError","type":"error"},{"inputs":[],"name":"CannotDisableRageQuitAfterInitializationError","type":"error"},{"inputs":[],"name":"CannotEnableRageQuitIfNotDistributionsRequireVoteError","type":"error"},{"inputs":[],"name":"CannotModifyTotalVotingPowerAndAcceptError","type":"error"},{"inputs":[{"internalType":"uint40","name":"rageQuitTimestamp","type":"uint40"}],"name":"CannotRageQuitError","type":"error"},{"inputs":[],"name":"DistributionsRequireVoteError","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bytes","name":"errData","type":"bytes"}],"name":"EthTransferFailed","type":"error"},{"inputs":[{"internalType":"uint40","name":"maxExecutableTime","type":"uint40"},{"internalType":"uint40","name":"timestamp","type":"uint40"}],"name":"ExecutionTimeExceededError","type":"error"},{"inputs":[{"internalType":"uint40","name":"rageQuitTimestamp","type":"uint40"}],"name":"FixedRageQuitTimestampError","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":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"InvalidGovernanceParameter","type":"error"},{"inputs":[],"name":"InvalidNewHostError","type":"error"},{"inputs":[],"name":"InvalidTokenOrderError","type":"error"},{"inputs":[],"name":"MismatchedPreciousListLengths","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"NotATokenError","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"NotMinted","type":"error"},{"inputs":[],"name":"NothingToBurnError","type":"error"},{"inputs":[],"name":"OnlyDelegateCallError","type":"error"},{"inputs":[],"name":"OnlyWhenEmergencyActionsAllowedError","type":"error"},{"inputs":[],"name":"OnlyWhenEnabledError","type":"error"},{"inputs":[],"name":"PartyNotStartedError","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":[],"name":"TooManyHosts","type":"error"},{"inputs":[{"internalType":"uint256","name":"v","type":"uint256"}],"name":"Uint256ToInt192CastOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"v","type":"uint256"}],"name":"Uint256ToUint96CastOutOfRange","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnsafeRecipient","type":"error"},{"inputs":[],"name":"ZeroAddress","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":true,"internalType":"address","name":"authority","type":"address"}],"name":"AuthorityAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"authority","type":"address"}],"name":"AuthorityRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_toTokenId","type":"uint256"}],"name":"BatchMetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"votingPower","type":"uint256"}],"name":"Burn","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":[],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"MetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"intrinsicVotingPower","type":"uint256"}],"name":"PartyCardIntrinsicVotingPowerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"delegate","type":"address"}],"name":"PartyDelegateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint40","name":"timestamp","type":"uint40"},{"indexed":false,"internalType":"uint96","name":"delegatedVotingPower","type":"uint96"},{"indexed":false,"internalType":"uint96","name":"intrinsicVotingPower","type":"uint96"},{"indexed":false,"internalType":"bool","name":"isDelegated","type":"bool"}],"name":"PartyVotingSnapshotCreated","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":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"indexed":false,"internalType":"contract IERC20[]","name":"withdrawTokens","type":"address[]"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"}],"name":"RageQuit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint40","name":"oldRageQuitTimestamp","type":"uint40"},{"indexed":false,"internalType":"uint40","name":"newRageQuitTimestamp","type":"uint40"}],"name":"RageQuitSet","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"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"IMPL","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION_ID","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"abdicateAuthority","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPartyHost","type":"address"}],"name":"abdicateHost","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":"authority","type":"address"}],"name":"addAuthority","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","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":"uint96","name":"votingPower","type":"uint96"}],"name":"decreaseTotalVotingPower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint96","name":"votingPower","type":"uint96"}],"name":"decreaseVotingPower","outputs":[],"stateMutability":"nonpayable","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":"uint256","name":"amount","type":"uint256"},{"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 Party","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":"uint96","name":"totalShares","type":"uint96"}],"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 ProposalStorage.GovernanceValues","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProposalEngineOpts","outputs":[{"components":[{"internalType":"bool","name":"enableAddAuthorityProposal","type":"bool"},{"internalType":"bool","name":"allowArbCallsToSpendPartyEth","type":"bool"},{"internalType":"bool","name":"allowOperators","type":"bool"},{"internalType":"enum ProposalStorage.DistributionsConfig","name":"distributionsConfig","type":"uint8"}],"internalType":"struct ProposalStorage.ProposalEngineOpts","name":"","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":"uint96","name":"totalVotingPower","type":"uint96"},{"internalType":"uint8","name":"numHosts","type":"uint8"},{"internalType":"uint8","name":"numHostsAccepted","type":"uint8"},{"internalType":"uint40","name":"voteDuration","type":"uint40"},{"internalType":"uint40","name":"executionDelay","type":"uint40"},{"internalType":"uint16","name":"passThresholdBps","type":"uint16"}],"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"},{"internalType":"uint256","name":"snapIndex","type":"uint256"}],"name":"getVotingPowerAt","outputs":[{"internalType":"uint96","name":"votingPower","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getVotingPowerShareOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint96","name":"votingPower","type":"uint96"}],"name":"increaseTotalVotingPower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint96","name":"votingPower","type":"uint96"}],"name":"increaseVotingPower","outputs":[],"stateMutability":"nonpayable","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"},{"components":[{"internalType":"bool","name":"enableAddAuthorityProposal","type":"bool"},{"internalType":"bool","name":"allowArbCallsToSpendPartyEth","type":"bool"},{"internalType":"bool","name":"allowOperators","type":"bool"},{"internalType":"enum ProposalStorage.DistributionsConfig","name":"distributionsConfig","type":"uint8"}],"internalType":"struct ProposalStorage.ProposalEngineOpts","name":"proposalEngine","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":"authorities","type":"address[]"},{"internalType":"uint40","name":"rageQuitTimestamp","type":"uint40"}],"internalType":"struct Party.PartyInitData","name":"initData","type":"tuple"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isAuthority","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":[],"name":"lastTotalVotingPowerChangeTimestamp","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"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":"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":[],"name":"numHosts","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"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":"tokenIds","type":"uint256[]"},{"internalType":"contract IERC20[]","name":"withdrawTokens","type":"address[]"},{"internalType":"uint256[]","name":"minWithdrawAmounts","type":"uint256[]"},{"internalType":"address","name":"receiver","type":"address"}],"name":"rageQuit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rageQuitTimestamp","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","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":"uint40","name":"newRageQuitTimestamp","type":"uint40"}],"name":"setRageQuit","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
60e0346200037557601f19906001600160401b03601f620063973881900382810186168501848111868210176200037957859282916040528339602094859181010312620003755751936001600160a01b03851685036200037557620000646200038d565b935f90818652620000746200038d565b92828452306080528760a05286518681116200036157600854976001988981811c9116801562000356575b858210146200034257908188849311620002ee575b5084908883116001146200028c57869262000280575b50505f19600383901b1c191690881b176008555b83519586116200026c576009548781811c9116801562000261575b838210146200024d5785811162000204575b50819486116001146200019d5750509183949184939462000191575b50501b915f199060031b1c1916176009555b60c052604051615fe99081620003ae82396080518161171f015260a051818181610fff0152818161135001528181612a7c015281816136f4015281816139730152615190015260c05181818161309201526159bb0152f35b015192505f8062000127565b600983528183209493928692918316915b88838310620001e95750505010620001d0575b505050811b0160095562000139565b01515f1960f88460031b161c191690555f8080620001c1565b858701518855909601959485019487935090810190620001ae565b600984528284208680890160051c820192858a1062000243575b0160051c019088905b828110620002375750506200010b565b85815501889062000227565b925081926200021e565b634e487b7160e01b84526022600452602484fd5b90607f1690620000f9565b634e487b7160e01b83526041600452602483fd5b015190505f80620000ca565b90848b9416916008885286882092885b88828210620002d75750508411620002be575b505050811b01600855620000de565b01515f1960f88460031b161c191690555f8080620002af565b8385015186558e979095019493840193016200029c565b909150600886528486208880850160051c82019287861062000338575b918c91869594930160051c01915b82811062000329575050620000b4565b8881558594508c910162000319565b925081926200030b565b634e487b7160e01b86526022600452602486fd5b90607f16906200009f565b634e487b7160e01b84526041600452602484fd5b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b60405190602082016001600160401b03811183821017620003795760405256fe60806040526004361015610021575b361561001f5734156131cf575b5f80fd5b005b5f3560e01c806301ffc9a71461042657806302403f711461042157806306fdde031461041c578063081812fc146104175780630935847914610412578063095ea7b31461040d5780630d4d151314610408578063158ef93e1461040357806316399ea2146103fe5780631d28dec7146103f95780632330f247146103f457806323b872dd146103ef57806324a9d853146103ea57806326defa73146103e557806327cb04b4146103e0578063287b4399146103db5780632a55205a146103d65780632fd75a27146103d1578063305a0721146103cc57806333b9d8c4146103c75780633846b6d2146103c25780633e4011b9146103bd5780634121c931146103b857806342842e0e146103b357806342966c68146103ae57806343bc8831146103a957806346904840146103a457806352a702b51461039f57806356973ee51461039a5780635c60da1b1461039a5780636210f6b2146103955780636352211e146103905780636fd44cfd1461038b57806370a082311461038657806374cb30411461038157806378cfabac14610340578063791fec561461037c5780638518a7451461037757806395d89b41146103725780639cd288941461036d5780639f181b5e14610368578063a22cb46514610363578063a25632fd1461035e578063b20240ee14610359578063b80f55c914610354578063b88d4fde1461034f578063c43683a11461034a578063c87b56dd14610345578063caf6aa4b14610340578063cc7b9d061461033b578063ccb3601114610336578063cd36324914610331578063cf67f3441461032c578063d1a35cba14610327578063d3c989af14610322578063d7faa2621461031d578063e6f26d9a14610318578063e7265a9514610313578063e8a3d4851461030e578063e985e9c514610309578063eb2931b714610304578063f0689b47146102ff578063f3ff955a146102fa578063fea44a56146102f55763fffc559d0361000e57612b2a565b612a46565b61291a565b612880565b612840565b6127e9565b6127d4565b6126a2565b61267e565b612661565b61259e565b612471565b612437565b6123ee565b61231c565b6120f6565b61183b565b6120e0565b612054565b611e72565b611e37565b611d26565b611b75565b611a82565b611a50565b611a2a565b611987565b61190d565b611865565b61181e565b6117ca565b61179e565b61176e565b61174e565b61170a565b6116cd565b6116a6565b61167f565b611622565b611544565b611282565b6111f2565b6110c6565b611078565b610fa0565b610f55565b610f3f565b610eea565b610e2a565b610dab565b610d88565b610d71565b610d05565b610ba0565b610aff565b610ade565b61096e565b61088b565b610851565b61081f565b610744565b61051d565b61043d565b6001600160e01b031981160361001b57565b3461001b57602036600319011261001b5761049960043561045d8161042b565b63ffffffff60e01b16630a85bd0160e11b81149081156104ee575b81156104ae575b811561049d575b5060405190151581529081906020820190565b0390f35b63152a902d60e11b1490505f610486565b90506301ffc9a760e01b811480156104de575b80156104ce575b9061047f565b50635b5e139f60e01b81146104c8565b506380ac58cd60e01b81146104c1565b630271189760e51b81149150610478565b6001600160601b0381160361001b57565b359061051b826104ff565b565b3461001b57604036600319011261001b5760043560243561053d816104ff565b6105456154da565b60018060601b039061058c6105618284600e5460601c166147a9565b600e8054600160601b600160c01b03191660609290921b600160601b600160c01b0316919091179055565b1690805f52600f60205260405f2090815491838303928311610603577ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7936105fe936105ee92556105e86105df84615cfa565b9160170b6154f1565b90614619565b6040519081529081906020820190565b0390a1005b61327c565b5f91031261001b57565b90600182811c92168015610640575b602083101461062c57565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610621565b634e487b7160e01b5f52604160045260245ffd5b608081019081106001600160401b0382111761067957604052565b61064a565b61016081019081106001600160401b0382111761067957604052565b6001600160401b03811161067957604052565b61010081019081106001600160401b0382111761067957604052565b90601f801991011681019081106001600160401b0382111761067957604052565b5f5b8381106106fb5750505f910152565b81810151838201526020016106ec565b90602091610724815180928185528580860191016106ea565b601f01601f1916010190565b90602061074192818152019061070b565b90565b3461001b575f8060031936011261081c576040518160085461076581610612565b808452906001908181169081156107f4575060011461079b575b6104998461078f818803826106c9565b60405191829182610730565b60088352602094507ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee35b8284106107e157505050816104999361078f928201019361077f565b80548585018701529285019281016107c5565b610499965061078f9450602092508593915060ff191682840152151560051b8201019361077f565b80fd5b3461001b57602036600319011261001b576004355f52600c602052602060018060a01b0360405f205416604051908152f35b3461001b57604036600319011261001b576020610872602435600435613d1d565b604051908152f35b6001600160a01b0381160361001b57565b3461001b57604036600319011261001b576004356108a88161087a565b6024355f818152600a602052604081205490926001600160a01b0391821691903383141580610945575b6109345761090b816108ec865f52600c60205260405f2090565b80546001600160a01b0319166001600160a01b03909216919091179055565b16907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258480a480f35b6040516282b42960e81b8152600490fd5b5061096961096561095e3361095987610c8c565b610cf0565b5460ff1690565b1590565b6108d2565b3461001b57606036600319011261001b576104995f80516020615ef48339815191526105ee610a786004356109a28161087a565b610aad6044356109b18161087a565b6109b96154da565b600e5460018060601b03808260601c1691815f80516020615f148339815191525460601c16926109ea602435615bce565b9380151580610ac7575b610aba575b5050600e80546001600160601b0319166001600160601b0392841660010184169283161790559788968792600e54610a479061056190879060601c6001600160601b0316613290565b613290565b84169384610a5d855f52600f60205260405f2090565b556040516001600160601b0390911681529081906020820190565b0390a2610a94610a8785610ca5565b546001600160a01b031690565b6001600160a01b038116610ab2575b5060170b836146ff565b615deb565b91505f610aa3565b03821692506001826109f9565b50610ad282826147a9565b848087169116106109f4565b3461001b575f36600319011261001b57602060ff5f54166040519015158152f35b3461001b57602036600319011261001b57610b81610b4a600435610b22816104ff565b610b2a6154da565b5f80516020615f148339815191525460601c6001600160601b03166147a9565b5f80516020615f148339815191528054600160601b600160c01b03191660609290921b600160601b600160c01b0316919091179055565b5f80516020615f34833981519152604080515f81525f196020820152a1005b3461001b57602036600319011261001b57600435610bbc61351d565b805f52600660205260405f20610bd9610bd4826132eb565b614be9565b610be281611f5c565b600181141580610c78575b80610c64575b610c43575080546001600160a01b03166001600160a01b03191790556040513381527fc2131db10d833d6b93ae553fa450ea0f6c0c2dfb0160cb3309468bf72718f3eb90602090a261001f614ddc565b604051630821641d60e21b8152908190610c609060048301613cbc565b0390fd5b50610c6e81611f5c565b6004811415610bf3565b50610c8281611f5c565b6003811415610bed565b6001600160a01b03165f908152600d6020526040902090565b6001600160a01b03165f90815260046020526040902090565b6001600160a01b03165f90815260036020526040902090565b6001600160a01b03165f908152600b6020526040902090565b9060018060a01b03165f5260205260405f2090565b3461001b57602036600319011261001b57600435610d228161087a565b60018060a01b03165f526010602052602060ff60405f2054166040519015158152f35b606090600319011261001b57600435610d5d8161087a565b90602435610d6a8161087a565b9060443590565b3461001b5761001f610d8236610d45565b91615855565b3461001b575f36600319011261001b57602061ffff5f5460101c16604051908152f35b3461001b57602036600319011261001b57600435610dc88161087a565b303303610e18576001600160a01b03165f818152601060205260408120805460ff19166001179055907f550a8ae64ec9d6640b6f168a26d3e6364b90defe8110c92135aa775b279e54ea8280a280f35b60405163ea8e4eb560e01b8152600490fd5b3461001b57602036600319011261001b57600435610e478161087a565b610e4f61351d565b6001600160a01b03811615610e705760405163640c1a3360e01b8152600490fd5b6005549060ff8216908115610603577fddffcdb3bb07c5efc18b0918cf4e3e88c7d42cc05156cdadb2ec12c3b5ff892f9260ff6105fe935f1901169060ff191617600555610eca610ec033610cbe565b805460ff19169055565b604080513381526001600160a01b03909216602083015290918291820190565b3461001b575f8060031936011261081c57610f036154da565b33808252601060205260408220805460ff191690557f272215cde179041f7a3e8da6f8aabc7c8fc1336ccd73aba698cb825a80d3be488280a280f35b3461001b576040366003190112156159a0575f80fd5b3461001b57602036600319011261001b576020610872600435615481565b9181601f8401121561001b578235916001600160401b03831161001b576020838186019501011161001b57565b606036600319011261001b57600435610fb88161087a565b6024356001600160401b03811161001b57610fd7903690600401610f73565b604051635c9fcd8560e11b8152600b60048201529192916001600160a01b03906020816024817f000000000000000000000000000000000000000000000000000000000000000086165afa908115611073575f91611045575b50163303610e185761001f926044359261414e565b611066915060203d811161106c575b61105e81836106c9565b81019061357c565b5f611030565b503d611054565b613591565b3461001b575f36600319011261001b575f80516020615f94833981519152546040516001600160a01b039091168152602090f35b64ffffffffff81160361001b57565b359061051b826110ac565b3461001b57604036600319011261001b5760206108726004356110e88161087a565b602435906110f5826110ac565b613490565b6040519061051b8261067e565b6040519060e082018281106001600160401b0382111761067957604052565b6040519060a082018281106001600160401b0382111761067957604052565b6040519061051b8261065e565b6001600160401b03811161067957601f01601f191660200190565b91909161117981611152565b61118660405191826106c9565b8093828252821161001b5781815f9384602080950137010152565b9291926111ad82611152565b916111bb60405193846106c9565b82948184528183011161001b578281602093845f960137010152565b9080601f8301121561001b57816020610741933591016111a1565b3461001b57604036600319011261001b5760043561120f8161087a565b6024356001600160401b03811161001b5761122e9036906004016111d7565b9030330361001b575f828192602082519201905af461127061127e61125161411f565b604051928391602083019515158652604080840152606083019061070b565b03601f1981018352826106c9565b5190fd5b3461001b576003196040368201811361001b576004803592602435906001600160401b03821161001b57606090823603011261001b576112c0613c84565b6112d2845f52600660205260405f2090565b6112eb60028201546112e636858701611b09565b614dfb565b6112f4816132eb565b916112fe83614be9565b61130781611f5c565b60058103611529575061131f60246113299201614106565b64ffffffffff1690565b8451631106aeeb60e21b808252600f8287019081526020966001600160a01b0396909492937f000000000000000000000000000000000000000000000000000000000000000088169289908290819083010381865afa9485156110735789915f9661150a575b508a51938491825281806113aa8a8201906017602083019252565b03915afa8015611073576113e7948a935f926114db575b50806114cb575b50806114b9575b5001516113e29064ffffffffff1661131f565b613421565b9081421061149357865f80888861142b8961140f42600160271b1764ffffffffff168b613a4a565b5f80516020615f9483398151915254166001600160a01b031690565b915163e0a8f6f560e01b9181019182526024810186905261144f8160448101611270565b51915af461145b61411f565b901561148e57507f416e669c63d9a3a5e36ee7cc7e2104b8db28ccd286aa18966e98fa230c73b08c5f80a261001f614ddc565b6141d4565b610c6086519283926303861c4b60e41b845264ffffffffff809216914216908401613fa9565b808410156113cf5792506113e26113cf565b808511156113c85793505f6113c8565b6114fc9192508a3d8c11611503575b6114f481836106c9565b810190614110565b905f6113c1565b503d6114ea565b611522919650823d8411611503576114f481836106c9565b945f61138f565b8551630821641d60e21b8152908190610c6090828801613cbc565b3461001b5761155236610d45565b919061155f838284615855565b803b15159283611585575b50505061157357005b604051633da6393160e01b8152600490fd5b604051630a85bd0160e11b8082523360048301526001600160a01b0394851660248301526044820192909252608060648201525f6084820181905291945092602092849260a4928492165af1908115611073575f916115f4575b506001600160e01b03191614155f808061156a565b611615915060203d811161161b575b61160d81836106c9565b810190615d2c565b5f6115df565b503d611603565b3461001b57602036600319011261001b57604051604081018181106001600160401b0382111761067957604052600181526020810190602036833780511561167a5761001f9160043590526116756154da565b615508565b61344c565b3461001b575f36600319011261001b57602064ffffffffff600e5460c01c16604051908152f35b3461001b575f36600319011261001b575f54604051602091821c6001600160a01b03168152f35b3461001b57602036600319011261001b5760206004356116ec8161087a565b60018060a01b038091165f526004825260405f205416604051908152f35b3461001b575f36600319011261001b576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461001b575f36600319011261001b57602060ff60055416604051908152f35b3461001b57602036600319011261001b57602061178c600435615cfa565b6040516001600160a01b039091168152f35b3461001b575f36600319011261001b57600e5460405160609190911c6001600160601b03168152602090f35b3461001b57602036600319011261001b576004356117e78161087a565b6001600160a01b0316801561180c575f52600b602052602060405f2054604051908152f35b60405163d92e233d60e01b8152600490fd5b3461001b575f36600319011261001b576020600254604051908152f35b3461001b57602036600319011261001b576004355f52600f602052602060405f2054604051908152f35b3461001b57602036600319011261001b57610b81610b4a600435611888816104ff565b6118906154da565b5f80516020615f148339815191525460601c6001600160601b0316613290565b634e487b7160e01b5f52602160045260245ffd5b600311156118ce57565b6118b0565b9190916060608082019380511515835260208101511515602084015260408101511515604084015201519060038210156118ce5760600152565b3461001b575f36600319011261001b57611925613258565b506040516119328161065e565b60ff5f80516020615f548339815191525481811615158352818160081c1615156020840152818160101c161515604084015260181c169060038210156118ce57610499916060820152604051918291826118d3565b3461001b575f8060031936011261081c57604051816009546119a881610612565b808452906001908181169081156107f457506001146119d1576104998461078f818803826106c9565b60098352602094507f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af5b828410611a1757505050816104999361078f928201019361077f565b80548585018701529285019281016119fb565b3461001b575f36600319011261001b57602064ffffffffff5f5460c01c16604051908152f35b3461001b575f36600319011261001b57600e546040516001600160601b039091168152602090f35b8015150361001b57565b3461001b57604036600319011261001b57600435611a9f8161087a565b60243590611aac82611a78565b335f52600d602052611ac18160405f20610cf0565b9115159160ff1981541660ff841617905560405191825260018060a01b0316907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b91909160608184031261001b57604051906001600160401b039060608301828111848210176106795760405282948135611b42816110ac565b84526020820135611b52816110ac565b6020850152604082013592831161001b57604092611b7092016111d7565b910152565b3461001b57604036600319011261001b576004356001600160401b03811161001b57611ba8610499913690600401611b09565b611bb0613c84565b7fea77d064c7d953e57748855e7b0751ea190d1df7505615a4e39336d4d548f688611d0e611bdf6002546139f2565b92611be984600255565b611d00611bf46133a6565b6060810151611cc9906001600160601b031691611cbd611c1660055460ff1690565b91611cae611c29825164ffffffffff1690565b611c99611c4d6040611c43602087015164ffffffffff1690565b95015161ffff1690565b95611c8f611c596110fa565b4264ffffffffff168152995f60208c0181905260408c0181905260608c0181905260808c01526001600160601b031660a08b0152565b60ff1660c0890152565b5f60e088015264ffffffffff16610100870152565b64ffffffffff16610120850152565b61ffff16610140830152565b611cd2836133fa565b611ce4875f52600660205260405f2090565b906002611cf9895f52600660205260405f2090565b0155613a6f565b604051918291338684613c39565b0390a1611d1d60243582613d1d565b506105ee614ddc565b3461001b575f36600319011261001b57611d3e613258565b506080604051611d4d8161065e565b5f80516020615f148339815191525464ffffffffff808216928381526020810191808460281c1683526040820190606061ffff93848760501c168452019360018060601b03809660601c168552604051968752511660208601525116604084015251166060820152f35b6001600160401b0381116106795760051b60200190565b9291611dd982611db7565b91611de760405193846106c9565b829481845260208094019160051b810192831161001b57905b828210611e0d5750505050565b81358152908301908301611e00565b9080601f8301121561001b5781602061074193359101611dce565b3461001b57602036600319011261001b576004356001600160401b03811161001b57611e6a61001f913690600401611e1c565b6116756154da565b3461001b57608036600319011261001b57600435611e8f8161087a565b602435611e9b8161087a565b604435916064356001600160401b03811161001b57611ebe903690600401610f73565b9092611ecb858285615855565b803b15159384611ee2575b50505050905061157357005b611f0c94505f6020949660405196879586948593630a85bd0160e11b9b8c86523360048701615d41565b03926001600160a01b03165af1908115611073575f91611f3e575b506001600160e01b0319161415805f808080611ed6565b611f56915060203d811161161b5761160d81836106c9565b5f611f27565b600811156118ce57565b9060088210156118ce5752565b61016061051b929493611f8b83610180810197611f66565b805164ffffffffff166020840152602081015164ffffffffff166040840152604081015164ffffffffff166060840152606081015164ffffffffff16608084015260808101516001600160601b031660a084015260a08101516001600160601b031660c084015260c081015160ff1660e084015260e0810151612016610100918286019060ff169052565b81015161202f610120918286019064ffffffffff169052565b81015190612049610140928386019064ffffffffff169052565b015161ffff16910152565b3461001b57602036600319011261001b576120c8604061014081516120788161067e565b5f91818380935282602082015282858201528260608201528260808201528260a08201528260c08201528260e08201528261010082015282610120820152015260043581526006602052206132eb565b6120d181614be9565b61049960405192839283611f73565b3461001b576020366003190112156159a0575f80fd5b3461001b575f36600319011261001b57602060405160028152f35b81601f8201121561001b5780359161212883611db7565b9261213660405194856106c9565b808452602092838086019260051b82010192831161001b578301905b828210612160575050505090565b838091833561216e8161087a565b815201910190612152565b359061ffff8216820361001b57565b359061051b8261087a565b91909160e08184031261001b576121a8611107565b928135916001600160401b03831161001b576121cb60c092612228948301612111565b85526121d9602082016110bb565b60208601526121ea604082016110bb565b60408601526121fb60608201612179565b606086015261220c60808201610510565b608086015261221d60a08201612179565b60a086015201612188565b60c0830152565b919082608091031261001b576040516122478161065e565b60608193803561225681611a78565b8352602081013561226681611a78565b6020840152604081013561227981611a78565b6040840152013590600382101561001b5760600152565b91906101008382031261001b576122a5611126565b926001600160401b03813581811161001b57836122c3918401612193565b85526122d2836020840161222f565b602086015260a082013581811161001b57836122ef9184016111d7565b604086015260c082013590811161001b5760e09261230e9183016111d7565b606085015201356080830152565b3461001b5760031960203682011261001b576004908135916001600160401b039182841161001b5760a090843603011261001b57612358611126565b918382013581811161001b5761237390833691870101612290565b8352602484013581811161001b5761239090833691870101612111565b6020840152604484013581811161001b576123b090833691870101611e1c565b6040840152606484013590811161001b5761001f936123d96084926123e4943691840101612111565b6060850152016110bb565b6080820152612fc2565b3461001b57606036600319011261001b5760206124256004356124108161087a565b60243561241c816110ac565b604435916132a9565b6040516001600160601b039091168152f35b3461001b57602036600319011261001b576004356001600160401b03811161001b5761087261246c6020923690600401611b09565b6133fa565b3461001b57602036600319011261001b5760043561248e816110ac565b61249661351d565b64ffffffffff9064ab2cb21860828216811461256b5760ff5f80516020615f548339815191525460181c166124ca816118c4565b1561255957600e5460c01c64ffffffffff1692831690646b5b567bfe821491821561254f575b5050612530577f33d3074d42e98b5940d3d8364ba0f3421c4fde9db929c3d1c2899a36c5b216f29161252182615094565b6105fe60405192839283613fa9565b60405163066a813560e51b815264ffffffffff83166004820152602490fd5b1490505f806124f0565b60405163064023b360e51b8152600490fd5b604051635f07128f60e01b8152600490fd5b6002111561001b57565b600211156118ce57565b9060028210156118ce5752565b3461001b57608036600319011261001b576101006125d96024356125c18161257d565b6044356125cd8161087a565b60643591600435613694565b61265f60e0604051926125ed848251612591565b6020810151602085015260018060a01b03806040830151166040860152806060830151166060860152608082015116608085015261263a60a082015160a086019060018060801b03169052565b60c0818101516001600160801b03169085015201516001600160601b031660e0830152565bf35b3461001b575f36600319011261001b576020600154604051908152f35b3461001b575f36600319011261001b57602060ff5f5460081c166040519015158152f35b3461001b57604036600319011261001b577ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce76105fe6004356105ee6024356126e9816104ff565b82816126f36154da565b600e5460601c6001600160601b03165f80516020615f14833981519152546001600160601b039260609190911c83169081151590816127bb575b506127ac575b506127725f80516020615ef4833981519152926127566105618761279695613290565b612768855f52600f60205260405f2090565b5495168095613421565b80612785855f52600f60205260405f2090565b556040519081529081906020820190565b0390a26127a283615cfa565b9060170b90614619565b81900382169350612772612733565b905083806127c985856147a9565b92169116105f61272d565b3461001b575f366003190112156159a0575f80fd5b3461001b57604036600319011261001b57602060ff61283460043561280d8161087a565b6024359061281a8261087a565b6001600160a01b03165f908152600d855260409020610cf0565b54166040519015158152f35b3461001b57602036600319011261001b5760043561285d8161087a565b60018060a01b03165f526003602052602060ff60405f2054166040519015158152f35b60c036600319011261001b576001600160401b0360243581811161001b576128ad60049136908301611b09565b9060443583811161001b576128c59036908301612111565b60643584811161001b576128dc9036908401611e1c565b9060843585811161001b576128f49036908501610f73565b92909160a43596871161001b5761291161001f9736908701610f73565b96909535613fc1565b3461001b57602036600319011261001b5761001f60043561293a8161087a565b61294333614b30565b61294f610a8733610ca5565b6001600160a01b039290838116612a40575033905b808416612a3a5750805b60208301516001600160601b0316936129ef6129b56129b06129ab61299c604089015160018060601b031690565b6001600160601b031660170b90565b6145d4565b615bfa565b918416916129df6129c4611145565b4264ffffffffff168152976001600160601b03166020890152565b6001600160601b03166040870152565b338114156060860152612a028533614a01565b612a0f836108ec33610ca5565b337fad2543a59f1b8c397ab540030b195cbeea5fadc4d5560e9fdf1ca5f750b725065f80a3336147c2565b9061296e565b90612964565b3461001b575f8060031936011261081c57604051635c9fcd8560e11b8152600b60048201526001600160a01b03906020816024817f000000000000000000000000000000000000000000000000000000000000000086165afa908115611073578391612adc575b501633141580612ac7575b610e1857612ac461420e565b80f35b50612ad761096561095e33610cbe565b612ab8565b612af4915060203d811161106c5761105e81836106c9565b5f612aad565b9181601f8401121561001b578235916001600160401b03831161001b576020808501948460051b01011161001b57565b3461001b57608036600319011261001b5760046001600160401b03813581811161001b57612b5b9036908401612afa565b9160243581811161001b57612b739036908601612afa565b9160443590811161001b57612b8b9036908701612afa565b9560643596612b998861087a565b8615612fb257335f908152601060205260409020612bb69061095e565b92612bcb600e5464ffffffffff9060c01c1690565b93159081612f4a575b600e805464ffffffffff60c01b19166405596590c360c51b1790555f805464ffffffffff60c01b19164260c01b64ffffffffff60c01b16179055612c1787615765565b91888a5f805b8b8210612de8575050612c4192612c3c610b4a93610b2a933691611dce565b61564b565b5f5460101c61ffff1661ffff165f5b888110612c96577f1d1937c6b6f4541f415f6e3e99b2b7a960dcedc201d01deada3d90b8cf77f9578b8b6105fe8f8d8d612c898e615094565b60405195869533876157b1565b612ca9612ca4828b8b615797565b6157a7565b612cb382866150bb565b51612cc9612cc18583613d0a565b612710900490565b80612d6b575b50612cdb838887615797565b35808210612d46575090818e612cf99493612cfe575b5050506139f2565b612c50565b6001600160a01b039280841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee03612d375750612d2f9216615a8a565b5f808e612cf1565b612d419350615ae5565b612d2f565b60408051632d9eac9360e01b8152808b01938452602084019290925290918291010390fd5b9081612d7691613483565b906001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee03612db9575f54612db3919060201c6001600160a01b0316615a8a565b5f612ccf565b5f54612de39190612ddd9060201c6001600160a01b03165b6001600160a01b031690565b84615ae5565b612db3565b91509150612dfd612dd1612ca4848d8d615797565b6001600160a01b039091161015612f3957879073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee612e43612dd180612ca4858f612e3d8383838c615797565b98615797565b14818b8b5f935f14612ed05750505050475b5f5b8d8d818310612e765750505050612e6d906139f2565b8b908b92612c1d565b612eab612e9d612e97612e9186612ecb9796612ebb96615797565b35615481565b86613d0a565b670de0b6b3a7640000900490565b612eb5868b6150bb565b51613421565b612ec5858a6150bb565b526139f2565b612e57565b612ee192612dd192612ca492615797565b6040516370a0823160e01b815230818b0190815290916020918291849182908190850103915afa9283156110735792612f1c575b5050612e55565b612f329250803d10611503576114f481836106c9565b5f80612f15565b604051633a67cf6d60e01b81528690fd5b64ffffffffff8516646b5b567bfe8103612f65575b50612bd4565b64ab2cb218608114908115612fa8575b50612f80575f612f5f565b505060405163a16caf5360e01b815264ffffffffff9093169183019182525081906020010390fd5b905042115f612f75565b50604051630c48157760e11b8152fd5b5f90815460ff81166131be5760ff1916600190811783557f5daa87a0e9463431830481fd4b6e3403442dfb9a12b9c07597e9f61d50b633c88380a18082519260408401519360608101519461305160808301519661304c602085519501519361304760208801516040890151908764ffffffffff608060608d01519c015116996150cf565b614ed4565b614fb4565b8161318f575b505084915b613131575b5050508061306d575050565b604051635c9fcd8560e11b8152601660048201526001600160a01b03906020816024817f000000000000000000000000000000000000000000000000000000000000000086165afa908115611073578491613113575b501690813b1561310f5760405163fc9968df60e01b8152600481019190915291908290602490829084905af18015611073576130fc5750565b8061310961051b9261069a565b80610608565b8280fd5b61312b915060203d811161106c5761105e81836106c9565b5f6130c3565b805182101561318a57828261318361317661315d6131508597876150bb565b516001600160a01b031690565b6001600160a01b03165f90815260106020526040902090565b805460ff19166001179055565b019161305c565b613061565b6060919350015161319f816118c4565b6131a8816118c4565b15612559576131b78392615094565b5f80613057565b60405162dc149f60e41b8152600490fd5b3660041161001b575f356001600160e01b03191663bc197c8160e01b81148015613248575b8015613238575b613227575f80516020615f94833981519152546001600160a01b0316613221368061116d565b90615c41565b602090604051908152818101604052f35b50630a85bd0160e11b81146131fb565b5063f23a6e6160e01b81146131f4565b604051906132658261065e565b5f6060838281528260208201528260408201520152565b634e487b7160e01b5f52601160045260245ffd5b6001600160601b03918216908216019190821161060357565b916132b791610741936144e6565b6060810151156132d7575f905b602001516001600160601b031690613290565b60408101516001600160601b0316906132c4565b9061051b61ffff6132fa6110fa565b845464ffffffffff8082168352602882901c81166020840152605082901c81166040840152607882901c8116606084015260a09190911c6080830152909461339490600101546001600160601b03811660a088015291606083901c60ff1660c0880152606883901c60ff1660e088015264ffffffffff607084901c8216166101008801528260981c1661012087019064ffffffffff169052565b60c01c1661014084019061ffff169052565b604051906133b38261065e565b5f80516020615f148339815191525464ffffffffff8082168452602882901c166020840152605081901c61ffff166040840152606090811c6001600160601b031690830152565b9060408201916060835191825160208401208552209252565b906001820180921161060357565b9190820180921161060357565b8115613438570490565b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b805482101561167a575f5260205f2001905f90565b5f1981019190821161060357565b9190820391821161060357565b6001600160a01b03165f9081526007602052604081208054925b8383106134c857505050806134bf57505f1990565b61074190613475565b9091928084018085116106035760011c906134f26134e68386613460565b505464ffffffffff1690565b64ffffffffff8481169116111561350d5750925b91906134aa565b935061351890613413565b613506565b335f52600360205260ff60405f20541615610e1857565b60405190613541826106ad565b8160e05f918281528260208201528260408201528260608201528260808201528260a08201528260c08201520152565b519061051b8261087a565b9081602091031261001b57516107418161087a565b6040513d5f823e3d90fd5b6040919493926135b0826060810197612591565b6001600160a01b031660208201520152565b51906001600160801b038216820361001b57565b519061051b826104ff565b908161010091031261001b5761367160e0604051926135ff846106ad565b805161360a8161257d565b84526020810151602085015261362260408201613571565b604085015261363360608201613571565b606085015261364460808201613571565b608085015261365560a082016135c2565b60a085015261366660c082016135c2565b60c0850152016135d6565b60e082015290565b1561368057565b634e487b7160e01b5f52600160045260245ffd5b909261369e613534565b506136a7613957565b3033036138b1575b5f80516020615f148339815191525460601c6001600160601b03161561389f57604051635c9fcd8560e11b8152600c60048201526001600160a01b03906020816024817f000000000000000000000000000000000000000000000000000000000000000086165afa8015611073578261375c917fdda962f630bf2f85c8412f305206a4f363688481dd632689f88ad7022e4cc233935f91613881575b501693604051918291888a8461359c565b0390a1613767614ddc565b5f549361ffff828660201c169560101c169561378281612587565b801561383b576137ff93925f9697926137a96001846137a36137b296612587565b14613679565b16948386615ae5565b60405163eedaf00d60e01b81526001600160a01b03948516600482015230602482015295909316604486015261ffff90921660648501526101009392849284929091839182906084820190565b03925af1918215611073575f9261381557505090565b6107419250803d10613834575b61382c81836106c9565b8101906135e1565b503d613822565b5050604051631d1972a760e11b81523060048201526001600160a01b0390941660248501525061ffff9093166044830152610100928391839190829081606481016137ff565b613899915060203d811161106c5761105e81836106c9565b5f61374b565b6040516311bf009f60e21b8152600490fd5b60ff5f80516020615f548339815191525460181c166138cf816118c4565b613930576138dc33614b30565b60408101516001600160601b031615908161390a575b50156136af5760405163ea8e4eb560e01b8152600490fd5b6020015161392991506001600160601b03165b6001600160601b031690565b155f6138f2565b604051632e31362d60e01b8152600490fd5b9081602091031261001b575161074181611a78565b6040516331a1aa3360e11b8152601560048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115611073575f916139c4575b506139b257565b604051632fb3e88560e01b8152600490fd5b6139e5915060203d81116139eb575b6139dd81836106c9565b810190613942565b5f6139ab565b503d6139d3565b5f1981146106035760010190565b805464ffffffffff60281b191660289290921b64ffffffffff60281b16919091179055565b805464ffffffffff60501b191660509290921b64ffffffffff60501b16919091179055565b805464ffffffffff60781b191660789290921b64ffffffffff60781b16919091179055565b90613c1d610140600161051b94613aa6613a8e865164ffffffffff1690565b825464ffffffffff191664ffffffffff909116178255565b613ac1613abb602087015164ffffffffff1690565b82613a00565b613adc613ad6604087015164ffffffffff1690565b82613a25565b613af7613af1606087015164ffffffffff1690565b82613a4a565b6080850151613b29906001600160601b031682546001600160a01b031660a09190911b6001600160a01b031916178255565b60a0850151910180546001600160601b0319166001600160601b0390921691909117815592613b79613b5f60c083015160ff1690565b855460ff60601b191660609190911b60ff60601b16178555565b613ba4613b8a60e083015160ff1690565b855460ff60681b191660689190911b60ff60681b16178555565b613bdc613bba61010083015164ffffffffff1690565b855464ffffffffff60701b191660709190911b64ffffffffff60701b16178555565b613c14613bf261012083015164ffffffffff1690565b855464ffffffffff60981b191660989190911b64ffffffffff60981b16178555565b015161ffff1690565b815461ffff60c01b191660c09190911b61ffff60c01b16179055565b916107419360409160c093855260018060a01b0316602085015260608285015264ffffffffff8082511660608601526020820151166080850152015191606060a0820152019061070b565b613c8d33614b30565b60408101516001600160601b03908116159182613cad575b5050610e1857565b60200151161590505f80613ca5565b60208101929161051b9190611f66565b64ffffffffff9081165f19019190821161060357565b60ff1660ff81146106035760010190565b906127109182810292818404149015171561060357565b8181029291811591840414171561060357565b90613d30825f52600660205260405f2090565b91613d3a836132eb565b90613d4482614be9565b613d4d81611f5c565b600181141580613f95575b80613f81575b610c4357505f5460c01c64ffffffffff1664ffffffffff9081164214613f6c576003850194613d9061095e3388610cf0565b613f5457613dc961391d95613dac613176610741993390610cf0565b613dc3613dbe875164ffffffffff1690565b613ccc565b336132a9565b937fea45672a2d92b09ff2dd48aa67615f8b5c79d7808b7282fc026a24e00283f78d613e586080830196613e17613e0a82610a428b5160018060601b031690565b6001600160601b03168952565b613e2361095e33610cbe565b613f2e575b613e328486613a6f565b604080518881523360208201526001600160601b03909216908201529081906060820190565b0390a182613e6e602083015164ffffffffff1690565b16159081613ecf575b50613e8f575b505090516001600160601b0316919050565b613e9b91421690613a00565b7fe36f8b7448daff4a52e2945db0d1d7a436279cc1d527a45c27835dcbd27f336d5f80a2613ec7614ddc565b5f8080613e7d565b9050613f26613f1f610140613f15613ef8613ef361391d8b5160018060601b031690565b613cf3565b60a0860151613f0f906001600160601b031661391d565b9061342e565b93015161ffff1690565b61ffff1690565b11155f613e77565b613f4f60e08501613f48613f43825160ff1690565b613ce2565b60ff169052565b613e28565b604051630b517d8f60e41b8152336004820152602490fd5b6040516001621af97960e21b03198152600490fd5b50613f8b81611f5c565b6004811415613d5e565b50613f9f81611f5c565b6003811415613d58565b64ffffffffff91821681529116602082015260400190565b93949196929096613fd0613957565b613fd8613c84565b613fea855f52600660205260405f2090565b97613ff960028a015482614dfb565b614002896132eb565b9661400c88614be9565b61401581611f5c565b60048114908115806140f2575b610c435761402f90611f5c565b6140ae575b6140416109658585614dab565b61409c576140849861407661407e9261406e6109659b6140698f64ffffffffff421690613a4a565b614b79565b9736916111a1565b9636916111a1565b956143c2565b61408b5750565b805464ffffffffff60781b19169055565b604051633b43666f60e01b8152600490fd5b815164ffffffffff9081164281106140d257506140cd9042168b613a25565b614034565b604051632f7e600560e21b8152918291610c609142169060048401613fa9565b506140fc81611f5c565b6005811415614022565b35610741816110ac565b9081602091031261001b575190565b3d15614149573d9061413082611152565b9161413e60405193846106c9565b82523d5f602084013e565b606090565b90939260ff5f5460081c166141dc575f806040518588823780868101838152039084865af161417b61411f565b90156141d457506141c97f66cf5924183d7d44caa75d9268a169d7c1422fef43848743d5e1ba32d5833acf949560405194859460018060a01b031685526060602086015260608501916141ee565b9060408301520390a1565b602081519101fd5b6040516304e71fd360e31b8152600490fd5b908060209392818452848401375f828201840152601f01601f1916010190565b61010061ff00195f5416175f557f447e75484d6bdb571b4a92ae14018db7b6dd41f3f02360690c554e1d48f46f875f80a1565b9081518082526020808093019301915f5b828110614260575050505090565b835185529381019392810192600101614252565b919060209283815281518482015261429b8483015160e0604084015261010083019061070b565b906142cf6142bb604085015193601f19948585830301606086015261070b565b60608501518484830301608085015261070b565b92608081015160a083015260a081015193838382030160c08401528680865192838152019501905f5b81811061431c5750505061074194955060c060e09101519282850301910152614241565b82516001600160a01b0316875295880195918801916001016142f8565b81601f8201121561001b57805161434f81611152565b9261435d60405194856106c9565b8184526020828401011161001b5761074191602080850191016106ea565b9060208282031261001b5781516001600160401b03811161001b576107419201614339565b6001600160a01b0390911681526040602082018190526107419291019061070b565b95935f9593929194604087960151946143d9611107565b898152602081019690965260408601526060850152608084015260a083015260c08201525f80516020615f94833981519152546001600160a01b03169060405161443881611270602082019463a7c8a3f960e01b865260248301614274565b51915af461444461411f565b901561148e578060208061445d9351830101910161437b565b907fc98fbf8f20b11b050a9541d12aee1c11fcd31e8e42975cc885fb3d33a6accc826040518061448e8533836143a0565b0390a2614499614ddc565b511590565b906040516144ab8161065e565b915464ffffffffff81168352602881901c6001600160601b039081166020850152608882901c16604084015260e81c60ff1615156060830152565b91906144f0613258565b6001600160a01b0384165f9081526007602052604090209093909283548061451b575b505050505090565b80821090816145b2575b81614572575b5061456157509061453b91613490565b906001820161454c57808080614513565b61074192509061455b91613460565b5061449e565b915050610741925061455b91613460565b61457c9150613475565b8114801561458b575b5f61452b565b506145a16134e661459b83613413565b86613460565b64ffffffffff808516911611614585565b90506145c16134e68387613460565b64ffffffffff8086169116111590614525565b60170b906001600160bf1b0382136001600160bf1b031983121761060357565b601791820b910b01906001600160bf1b031982126001600160bf1b0383131761060357565b9061051b9161462781614b30565b906001600160a01b038061463a83610ca5565b5416806146f757508182915b602085015160408601516001600160601b039182169761466d926129b0921660170b6145f4565b906146ae8184169185169261469e614683611145565b4264ffffffffff168152996001600160601b031660208b0152565b6001600160601b03166040890152565b8181141560608801526146c18784614a01565b6146ce846108ec85610ca5565b7fad2543a59f1b8c397ab540030b195cbeea5fadc4d5560e9fdf1ca5f750b725065f80a36147c2565b918291614646565b9161051b9261470d81614b30565b9161471a610a8783610ca5565b6001600160a01b0392908381166147a3575080915b80841661479d575081925b602085015160408601516001600160601b0391821697614767926129b092614762911661299c565b6145f4565b9061477d8184169186169261469e614683611145565b8181141560608801526147908784614a01565b6146ce856108ec85610ca5565b9261473a565b9161472f565b6001600160601b03918216908216039190821161060357565b90936001600160a01b038381169491928515801561494e575b61493c578116908616958187141580614932575b6148d7575b508403614803575b5050505050565b6148a79461483361481385614b30565b602081015160409095015190946001600160601b03908116911690613290565b94146148b1575b5060408101516148a2919061489990614862906060906001600160601b03165b930151151590565b9161488961486e611145565b4264ffffffffff168152966001600160601b03166020880152565b6001600160601b03166040860152565b15156060840152565b614a01565b5f808080806147fc565b6040015190926148a2916148d091906001600160601b03165b906147a9565b929061483a565b806148e461492c92614b30565b60208101519091906148a290614910906001600160601b031660408801516001600160601b03166148ca565b92614899614862606061485a604085015160018060601b031690565b5f6147f4565b50858714156147ef565b60405163e5ec2d2560e01b8152600490fd5b50818716156147db565b91906149c557805182546020830151604084015160609094015164ffffffffff9093166001600160f01b03199092169190911760289190911b600160281b600160881b03161760889290921b600160881b600160e81b03169190911790151560e81b60ff60e81b16179055565b634e487b7160e01b5f525f60045260245ffd5b80549190600160401b83101561067957826149fb91600161051b95018155613460565b90614958565b81516020830151604084015164ffffffffff9493614ac2939092908616917f59c8109016c9c9310894a72309b48d2a442208dacb537923fca808618ce57102916001600160601b03908116911690614aa6614a5f6060890151151590565b6040805164ffffffffff90971687526001600160601b039384166020880152929093169185019190915290151560608401526001600160a01b038416929081906080820190565b0390a26001600160a01b03165f90815260076020526040902090565b9182549081614ad7575b505061051b916149d8565b614afa614aef61455b614ae985613475565b87613460565b5164ffffffffff1690565b90614b0d61131f855164ffffffffff1690565b911614614b1a5780614acc565b61051b92614b2a6149fb92613475565b90613460565b90614b39613258565b6001600160a01b039092165f90815260076020526040902080549081614b5d575050565b9192505f19810191908211610603576107419161455b91613460565b608081015160a08201515f9291614b9c916001600160601b039081169116614d5d565b614bc7575b8060ff60e08160c0614bba950151169201511690614d91565b614bc15790565b60021790565b60019150614ba1565b91909164ffffffffff8080941691160191821161060357565b64ffffffffff80614bff835164ffffffffff1690565b1615614d5757614c1a61131f604084015164ffffffffff1690565b614d25576080820180519092906001600160601b0390811614614d1d5781421692614c4d602083015164ffffffffff1690565b838116614c9357505080614c7c610100614c6f614c82945164ffffffffff1690565b92015164ffffffffff1690565b90614bd0565b161115614c8e57600190565b600290565b614caf90614c7c610120859795969496015164ffffffffff1690565b161115614d165751614cd8906001600160601b031660a08301516001600160601b031690614d5d565b614d105780614cfc60e0614cf360c0614d0295015160ff1690565b92015160ff1690565b90614d91565b614d0b57600390565b600490565b50600490565b5050600490565b505050600290565b60609091015164ffffffffff1690811615614d5157600160271b80911614614d4c57600690565b600790565b50600590565b50505f90565b6001600160601b0391906127109083168181029181159183041417156106035761270f92614d8c92169061342e565b101590565b60ff168015159182614da257505090565b60ff1614919050565b60015491614db891614dbc565b1490565b6020815160051b9101205f526020815160051b91012060205260405f2090565b5f80516020615f34833981519152604080515f81525f196020820152a1565b614e04906133fa565b90818103614e10575050565b6044925060405191630267877160e11b835260048301526024820152fd5b601f8111614e3a575050565b5f906008825260208220906020601f850160051c83019410614e77575b601f0160051c01915b828110614e6c57505050565b818155600101614e60565b9092508290614e57565b601f8111614e8d575050565b5f906009825260208220906020601f850160051c83019410614eca575b601f0160051c01915b828110614ebf57505050565b818155600101614eb3565b9092508290614eaa565b9081516001600160401b03811161067957614ef981614ef4600854610612565b614e2e565b602080601f8311600114614f3357508192935f92614f28575b50508160011b915f199060031b1c191617600855565b015190505f80614f12565b60085f52601f198316949091907ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee3925f905b878210614f9c575050836001959610614f84575b505050811b01600855565b01515f1960f88460031b161c191690555f8080614f79565b80600185968294968601518155019501930190614f65565b9081516001600160401b03811161067957614fd981614fd4600954610612565b614e81565b602080601f831160011461501357508192935f92615008575b50508160011b915f199060031b1c191617600955565b015190505f80614ff2565b60095f52601f198316949091907f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af925f905b87821061507c575050836001959610615064575b505050811b01600955565b01515f1960f88460031b161c191690555f8080615059565b80600185968294968601518155019501930190615045565b600e805464ffffffffff60c01b191660c09290921b64ffffffffff60c01b16919091179055565b805182101561167a5760209160051b010190565b9260a08401926150e1845161ffff1690565b9361271061ffff95818782161161540e575060209182880192615109845164ffffffffff1690565b9764ffffffffff98610e108a821610615436575060608a019361512e855161ffff1690565b91821690811591821561542c575b505061540e5750604097888a0190615159825164ffffffffff1690565b9081168015908115615401575b506153e157508851635c9fcd8560e11b815260026004820152916001600160a01b039080846024817f000000000000000000000000000000000000000000000000000000000000000086165afa8015611073578c61526661530a9861523f8f6153669f61522761521b6153239f614aef615230946152e39f9d6080976152809f9d8f6152709f5f926153bc575b5061520761521592935195869283016118d3565b03601f1981018552846106c9565b16615a1c565b9a5164ffffffffff1690565b935161ffff1690565b9401516001600160601b031690565b9461525861524b611145565b64ffffffffff9099168952565b87019064ffffffffff169052565b61ffff16848d0152565b6001600160601b03166060830152565b64ffffffffff8151165f80516020615f148339815191529182549164ffffffffff60281b602083015160281b169061ffff60501b604084015160501b169260606001811b600160c01b0391015160601b169360018060c01b031916171717179055565b6153026152f289515160ff1690565b60ff1660ff196005541617600555565b5161ffff1690565b63ffff00005f549160101b169063ffff00001916175f55565b60c0850151615361906001600160a01b03165f8054640100000000600160c01b03191660209290921b640100000000600160c01b0316919091179055565b615457565b60ff825151116153a957505f5b81519081518110156153a45761539a6131766153956131508461539f966150bb565b610cbe565b6139f2565b615373565b505050565b5160016211dcdd60e31b03198152600490fd5b61521592506153da61520791833d851161106c5761105e81836106c9565b92506151f3565b8951636dfaf3cd60e01b815264ffffffffff919091166004820152602490fd5b62278d009150115f615166565b6040516323dd0d6d60e11b815261ffff919091166004820152602490fd5b1190505f8061513c565b604051636dfaf3cd60e01b815264ffffffffff919091166004820152602490fd5b90815181510361546f5761546a91614dbc565b600155565b6040516357cc2fc760e01b8152600490fd5b5f80516020615f148339815191525460601c6001600160601b0316905f826154aa575050505f90565b6040918152600f602052205490670de0b6b3a764000091828102928184041490151715610603576107419161342e565b335f52601060205260ff60405f20541615610e1857565b60170b6001600160bf1b03198114610603575f0390565b905f8092815b815181101561560957807f49995e5dd6158cf69ad3e9777c46755a1a826a446c6416992167462dad033b2a61554661560493856150bb565b519661555188615cfa565b976155fc61557a61557361556d845f52600f60205260405f2090565b54615bce565b8094613290565b998861558e845f52600f60205260405f2090565b556155cd604091845f80516020615ef48339815191528451806155b581905f602083019252565b0390a26105e86001600160601b03871660170b6154f1565b6155d683615d72565b5133815260208101929092526001600160601b0390921660408201529081906060820190565b0390a16139f2565b61550e565b5050600e5461562a915061056190849060601c6001600160601b03166147a9565b604080515f81525f1960208201525f80516020615f348339815191529190a1565b91905f9283845b8251811015615741579081615669849386956150bb565b5161567381615cfa565b956156d7575b6156ce92816155fc6156ba61557361556d7f49995e5dd6158cf69ad3e9777c46755a1a826a446c6416992167462dad033b2a965f52600f60205260405f2090565b988b61558e845f52600f60205260405f2090565b92909192615652565b336001600160a01b038716141580615720575b80615707575b156156795760405163ea8e4eb560e01b8152600490fd5b5061571b61096561095e336109598a610c8c565b6156f0565b503361573a612dd1610a87845f52600c60205260405f2090565b14156156ea565b50600e5490945061562a92506105619150849060601c6001600160601b03166147a9565b9061576f82611db7565b61577c60405191826106c9565b828152809261578d601f1991611db7565b0190602036910137565b919081101561167a5760051b0190565b356107418161087a565b6001600160a01b03918216815260806020808301829052908201859052909796959390926001600160fb1b03821161001b5760c0916005959493951b809160a08b013788018360a0820160a08b84030160408c0152520193925f905b83821061582f57505050505090606061051b9294019060018060a01b03169052565b909192939483806001928489356158458161087a565b168152019601949392019061580d565b5f838152600f60205260409020546001600160bf1b03811161598857615899906001600160c01b031660170b61589361588d826154f1565b84614619565b83614619565b6158b1612dd1610a87855f52600a60205260405f2090565b6001600160a01b038083169291830361093457831692831561180c57823314158061596f575b8061594e575b610934576158ed61591692610cd7565b80545f190190556158fd81610cd7565b805460010190556108ec855f52600a60205260405f2090565b61593b61592b845f52600c60205260405f2090565b80546001600160a01b0319169055565b5f80516020615f748339815191525f80a4565b50615967612dd1610a87875f52600c60205260405f2090565b3314156158dd565b5061598361096561095e3361095986610c8c565b6158d7565b6024906040519063e9a5989b60e01b82526004820152fd5b604051635c9fcd8560e11b81526004808201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115611073575f916159fe575b50613221363661116d565b615a16915060203d811161106c5761105e81836106c9565b5f6159f3565b5f80516020615f9483398151915280546001600160a01b039283166001600160a01b03198216811790925560405163347d5e2560e21b602082019081525f9586959193615a7592849261127092909116602484016143a0565b51915af4615a8161411f565b90156141d45750565b8115615ae1576001600160a01b0316905f90819081908190855af190615aae61411f565b9115615ab8575050565b610c6060405192839263354db69760e01b8452600484015260406024840152604483019061070b565b5050565b60405163a9059cbb60e01b602082019081526001600160a01b03841660248301526044820185905292949193925f91829190615b248160648101611270565b5190826001600160a01b0388165af1615b3b61411f565b90615b73575b5050604051631702a98760e11b81526001600160a01b0392831660048201529290911660248301526044820152606490fd5b805115615b9d5780602080615b8d93518301019101613942565b615b975780615b41565b92505050565b50925050803b15615bab5750565b604051639fe23a3960e01b81526001600160a01b03919091166004820152602490fd5b6001600160601b0390818111615be2571690565b60249060405190636f55e21560e11b82526004820152fd5b8060170b5f81128015615c31575b615c1957506001600160601b031690565b602490604051906394e08f6160e01b82526004820152fd5b506001600160601b038113615c08565b303b1561001b5760405190633e4011b960e01b82528180615c685f958694600484016143a0565b0381305afa9081615ce3575b50615ccf57615c8161411f565b805181019160408284031261081c57602082015192615c9f84611a78565b6040830151916001600160401b03831161081c5750615cc5926020918201920101614339565b90615cf2576141d4565b634e487b7160e01b81526001600452602490fd5b615cec9061069a565b5f615c74565b602081519101f35b5f908152600a60205260409020546001600160a01b0316908115615d1a57565b604051634d5e5fb360e01b8152600490fd5b9081602091031261001b57516107418161042b565b6001600160a01b039182168152911660208201526040810191909152608060608201819052610741939101916141ee565b5f818152600a60205260408120546001600160a01b0316801561093457808252600b602052604082205f198154019055615db4835f52600a60205260405f2090565b80546001600160a01b03199081169091555f848152600c602052604090209081541690555f80516020615f748339815191528280a4565b90615df68183615e94565b813b15159182615e09575b505061157357565b604051630a85bd0160e11b8082523360048301525f6024830181905260448301949094526080606483015260848201849052935091602091839160a4918391906001600160a01b03165af1908115611073575f91615e76575b506001600160e01b03191614155f80615e01565b615e8e915060203d811161161b5761160d81836106c9565b5f615e62565b6001600160a01b038181169190821561180c57835f52600a60205260405f2054166109345780615ec6615edf92610cd7565b600181540190556108ec845f52600a60205260405f2090565b5f5f80516020615f748339815191528180a456fe84a9a38a0d320e93bcc5ebdabf23f355777c9b2251f0a2eceb54e0bddcf6f728eb054550c406db3b89dc7016369a66aff0ce40188133281942b92e6188c6b1f16bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661ceb054550c406db3b89dc7016369a66aff0ce40188133281942b92e6188c6b1f0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efeb054550c406db3b89dc7016369a66aff0ce40188133281942b92e6188c6b1efa264697066735822122045bd91fe3d3d061af7cc89368f87f03aa3210c97ebe816f8783a32e9e8294eef64736f6c634300081400330000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade
Deployed Bytecode
0x60806040526004361015610021575b361561001f5734156131cf575b5f80fd5b005b5f3560e01c806301ffc9a71461042657806302403f711461042157806306fdde031461041c578063081812fc146104175780630935847914610412578063095ea7b31461040d5780630d4d151314610408578063158ef93e1461040357806316399ea2146103fe5780631d28dec7146103f95780632330f247146103f457806323b872dd146103ef57806324a9d853146103ea57806326defa73146103e557806327cb04b4146103e0578063287b4399146103db5780632a55205a146103d65780632fd75a27146103d1578063305a0721146103cc57806333b9d8c4146103c75780633846b6d2146103c25780633e4011b9146103bd5780634121c931146103b857806342842e0e146103b357806342966c68146103ae57806343bc8831146103a957806346904840146103a457806352a702b51461039f57806356973ee51461039a5780635c60da1b1461039a5780636210f6b2146103955780636352211e146103905780636fd44cfd1461038b57806370a082311461038657806374cb30411461038157806378cfabac14610340578063791fec561461037c5780638518a7451461037757806395d89b41146103725780639cd288941461036d5780639f181b5e14610368578063a22cb46514610363578063a25632fd1461035e578063b20240ee14610359578063b80f55c914610354578063b88d4fde1461034f578063c43683a11461034a578063c87b56dd14610345578063caf6aa4b14610340578063cc7b9d061461033b578063ccb3601114610336578063cd36324914610331578063cf67f3441461032c578063d1a35cba14610327578063d3c989af14610322578063d7faa2621461031d578063e6f26d9a14610318578063e7265a9514610313578063e8a3d4851461030e578063e985e9c514610309578063eb2931b714610304578063f0689b47146102ff578063f3ff955a146102fa578063fea44a56146102f55763fffc559d0361000e57612b2a565b612a46565b61291a565b612880565b612840565b6127e9565b6127d4565b6126a2565b61267e565b612661565b61259e565b612471565b612437565b6123ee565b61231c565b6120f6565b61183b565b6120e0565b612054565b611e72565b611e37565b611d26565b611b75565b611a82565b611a50565b611a2a565b611987565b61190d565b611865565b61181e565b6117ca565b61179e565b61176e565b61174e565b61170a565b6116cd565b6116a6565b61167f565b611622565b611544565b611282565b6111f2565b6110c6565b611078565b610fa0565b610f55565b610f3f565b610eea565b610e2a565b610dab565b610d88565b610d71565b610d05565b610ba0565b610aff565b610ade565b61096e565b61088b565b610851565b61081f565b610744565b61051d565b61043d565b6001600160e01b031981160361001b57565b3461001b57602036600319011261001b5761049960043561045d8161042b565b63ffffffff60e01b16630a85bd0160e11b81149081156104ee575b81156104ae575b811561049d575b5060405190151581529081906020820190565b0390f35b63152a902d60e11b1490505f610486565b90506301ffc9a760e01b811480156104de575b80156104ce575b9061047f565b50635b5e139f60e01b81146104c8565b506380ac58cd60e01b81146104c1565b630271189760e51b81149150610478565b6001600160601b0381160361001b57565b359061051b826104ff565b565b3461001b57604036600319011261001b5760043560243561053d816104ff565b6105456154da565b60018060601b039061058c6105618284600e5460601c166147a9565b600e8054600160601b600160c01b03191660609290921b600160601b600160c01b0316919091179055565b1690805f52600f60205260405f2090815491838303928311610603577ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7936105fe936105ee92556105e86105df84615cfa565b9160170b6154f1565b90614619565b6040519081529081906020820190565b0390a1005b61327c565b5f91031261001b57565b90600182811c92168015610640575b602083101461062c57565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610621565b634e487b7160e01b5f52604160045260245ffd5b608081019081106001600160401b0382111761067957604052565b61064a565b61016081019081106001600160401b0382111761067957604052565b6001600160401b03811161067957604052565b61010081019081106001600160401b0382111761067957604052565b90601f801991011681019081106001600160401b0382111761067957604052565b5f5b8381106106fb5750505f910152565b81810151838201526020016106ec565b90602091610724815180928185528580860191016106ea565b601f01601f1916010190565b90602061074192818152019061070b565b90565b3461001b575f8060031936011261081c576040518160085461076581610612565b808452906001908181169081156107f4575060011461079b575b6104998461078f818803826106c9565b60405191829182610730565b60088352602094507ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee35b8284106107e157505050816104999361078f928201019361077f565b80548585018701529285019281016107c5565b610499965061078f9450602092508593915060ff191682840152151560051b8201019361077f565b80fd5b3461001b57602036600319011261001b576004355f52600c602052602060018060a01b0360405f205416604051908152f35b3461001b57604036600319011261001b576020610872602435600435613d1d565b604051908152f35b6001600160a01b0381160361001b57565b3461001b57604036600319011261001b576004356108a88161087a565b6024355f818152600a602052604081205490926001600160a01b0391821691903383141580610945575b6109345761090b816108ec865f52600c60205260405f2090565b80546001600160a01b0319166001600160a01b03909216919091179055565b16907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258480a480f35b6040516282b42960e81b8152600490fd5b5061096961096561095e3361095987610c8c565b610cf0565b5460ff1690565b1590565b6108d2565b3461001b57606036600319011261001b576104995f80516020615ef48339815191526105ee610a786004356109a28161087a565b610aad6044356109b18161087a565b6109b96154da565b600e5460018060601b03808260601c1691815f80516020615f148339815191525460601c16926109ea602435615bce565b9380151580610ac7575b610aba575b5050600e80546001600160601b0319166001600160601b0392841660010184169283161790559788968792600e54610a479061056190879060601c6001600160601b0316613290565b613290565b84169384610a5d855f52600f60205260405f2090565b556040516001600160601b0390911681529081906020820190565b0390a2610a94610a8785610ca5565b546001600160a01b031690565b6001600160a01b038116610ab2575b5060170b836146ff565b615deb565b91505f610aa3565b03821692506001826109f9565b50610ad282826147a9565b848087169116106109f4565b3461001b575f36600319011261001b57602060ff5f54166040519015158152f35b3461001b57602036600319011261001b57610b81610b4a600435610b22816104ff565b610b2a6154da565b5f80516020615f148339815191525460601c6001600160601b03166147a9565b5f80516020615f148339815191528054600160601b600160c01b03191660609290921b600160601b600160c01b0316919091179055565b5f80516020615f34833981519152604080515f81525f196020820152a1005b3461001b57602036600319011261001b57600435610bbc61351d565b805f52600660205260405f20610bd9610bd4826132eb565b614be9565b610be281611f5c565b600181141580610c78575b80610c64575b610c43575080546001600160a01b03166001600160a01b03191790556040513381527fc2131db10d833d6b93ae553fa450ea0f6c0c2dfb0160cb3309468bf72718f3eb90602090a261001f614ddc565b604051630821641d60e21b8152908190610c609060048301613cbc565b0390fd5b50610c6e81611f5c565b6004811415610bf3565b50610c8281611f5c565b6003811415610bed565b6001600160a01b03165f908152600d6020526040902090565b6001600160a01b03165f90815260046020526040902090565b6001600160a01b03165f90815260036020526040902090565b6001600160a01b03165f908152600b6020526040902090565b9060018060a01b03165f5260205260405f2090565b3461001b57602036600319011261001b57600435610d228161087a565b60018060a01b03165f526010602052602060ff60405f2054166040519015158152f35b606090600319011261001b57600435610d5d8161087a565b90602435610d6a8161087a565b9060443590565b3461001b5761001f610d8236610d45565b91615855565b3461001b575f36600319011261001b57602061ffff5f5460101c16604051908152f35b3461001b57602036600319011261001b57600435610dc88161087a565b303303610e18576001600160a01b03165f818152601060205260408120805460ff19166001179055907f550a8ae64ec9d6640b6f168a26d3e6364b90defe8110c92135aa775b279e54ea8280a280f35b60405163ea8e4eb560e01b8152600490fd5b3461001b57602036600319011261001b57600435610e478161087a565b610e4f61351d565b6001600160a01b03811615610e705760405163640c1a3360e01b8152600490fd5b6005549060ff8216908115610603577fddffcdb3bb07c5efc18b0918cf4e3e88c7d42cc05156cdadb2ec12c3b5ff892f9260ff6105fe935f1901169060ff191617600555610eca610ec033610cbe565b805460ff19169055565b604080513381526001600160a01b03909216602083015290918291820190565b3461001b575f8060031936011261081c57610f036154da565b33808252601060205260408220805460ff191690557f272215cde179041f7a3e8da6f8aabc7c8fc1336ccd73aba698cb825a80d3be488280a280f35b3461001b576040366003190112156159a0575f80fd5b3461001b57602036600319011261001b576020610872600435615481565b9181601f8401121561001b578235916001600160401b03831161001b576020838186019501011161001b57565b606036600319011261001b57600435610fb88161087a565b6024356001600160401b03811161001b57610fd7903690600401610f73565b604051635c9fcd8560e11b8152600b60048201529192916001600160a01b03906020816024817f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade86165afa908115611073575f91611045575b50163303610e185761001f926044359261414e565b611066915060203d811161106c575b61105e81836106c9565b81019061357c565b5f611030565b503d611054565b613591565b3461001b575f36600319011261001b575f80516020615f94833981519152546040516001600160a01b039091168152602090f35b64ffffffffff81160361001b57565b359061051b826110ac565b3461001b57604036600319011261001b5760206108726004356110e88161087a565b602435906110f5826110ac565b613490565b6040519061051b8261067e565b6040519060e082018281106001600160401b0382111761067957604052565b6040519060a082018281106001600160401b0382111761067957604052565b6040519061051b8261065e565b6001600160401b03811161067957601f01601f191660200190565b91909161117981611152565b61118660405191826106c9565b8093828252821161001b5781815f9384602080950137010152565b9291926111ad82611152565b916111bb60405193846106c9565b82948184528183011161001b578281602093845f960137010152565b9080601f8301121561001b57816020610741933591016111a1565b3461001b57604036600319011261001b5760043561120f8161087a565b6024356001600160401b03811161001b5761122e9036906004016111d7565b9030330361001b575f828192602082519201905af461127061127e61125161411f565b604051928391602083019515158652604080840152606083019061070b565b03601f1981018352826106c9565b5190fd5b3461001b576003196040368201811361001b576004803592602435906001600160401b03821161001b57606090823603011261001b576112c0613c84565b6112d2845f52600660205260405f2090565b6112eb60028201546112e636858701611b09565b614dfb565b6112f4816132eb565b916112fe83614be9565b61130781611f5c565b60058103611529575061131f60246113299201614106565b64ffffffffff1690565b8451631106aeeb60e21b808252600f8287019081526020966001600160a01b0396909492937f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade88169289908290819083010381865afa9485156110735789915f9661150a575b508a51938491825281806113aa8a8201906017602083019252565b03915afa8015611073576113e7948a935f926114db575b50806114cb575b50806114b9575b5001516113e29064ffffffffff1661131f565b613421565b9081421061149357865f80888861142b8961140f42600160271b1764ffffffffff168b613a4a565b5f80516020615f9483398151915254166001600160a01b031690565b915163e0a8f6f560e01b9181019182526024810186905261144f8160448101611270565b51915af461145b61411f565b901561148e57507f416e669c63d9a3a5e36ee7cc7e2104b8db28ccd286aa18966e98fa230c73b08c5f80a261001f614ddc565b6141d4565b610c6086519283926303861c4b60e41b845264ffffffffff809216914216908401613fa9565b808410156113cf5792506113e26113cf565b808511156113c85793505f6113c8565b6114fc9192508a3d8c11611503575b6114f481836106c9565b810190614110565b905f6113c1565b503d6114ea565b611522919650823d8411611503576114f481836106c9565b945f61138f565b8551630821641d60e21b8152908190610c6090828801613cbc565b3461001b5761155236610d45565b919061155f838284615855565b803b15159283611585575b50505061157357005b604051633da6393160e01b8152600490fd5b604051630a85bd0160e11b8082523360048301526001600160a01b0394851660248301526044820192909252608060648201525f6084820181905291945092602092849260a4928492165af1908115611073575f916115f4575b506001600160e01b03191614155f808061156a565b611615915060203d811161161b575b61160d81836106c9565b810190615d2c565b5f6115df565b503d611603565b3461001b57602036600319011261001b57604051604081018181106001600160401b0382111761067957604052600181526020810190602036833780511561167a5761001f9160043590526116756154da565b615508565b61344c565b3461001b575f36600319011261001b57602064ffffffffff600e5460c01c16604051908152f35b3461001b575f36600319011261001b575f54604051602091821c6001600160a01b03168152f35b3461001b57602036600319011261001b5760206004356116ec8161087a565b60018060a01b038091165f526004825260405f205416604051908152f35b3461001b575f36600319011261001b576040517f0000000000000000000000006c7d98079023f05c2b57dfc933fa0903a2c954116001600160a01b03168152602090f35b3461001b575f36600319011261001b57602060ff60055416604051908152f35b3461001b57602036600319011261001b57602061178c600435615cfa565b6040516001600160a01b039091168152f35b3461001b575f36600319011261001b57600e5460405160609190911c6001600160601b03168152602090f35b3461001b57602036600319011261001b576004356117e78161087a565b6001600160a01b0316801561180c575f52600b602052602060405f2054604051908152f35b60405163d92e233d60e01b8152600490fd5b3461001b575f36600319011261001b576020600254604051908152f35b3461001b57602036600319011261001b576004355f52600f602052602060405f2054604051908152f35b3461001b57602036600319011261001b57610b81610b4a600435611888816104ff565b6118906154da565b5f80516020615f148339815191525460601c6001600160601b0316613290565b634e487b7160e01b5f52602160045260245ffd5b600311156118ce57565b6118b0565b9190916060608082019380511515835260208101511515602084015260408101511515604084015201519060038210156118ce5760600152565b3461001b575f36600319011261001b57611925613258565b506040516119328161065e565b60ff5f80516020615f548339815191525481811615158352818160081c1615156020840152818160101c161515604084015260181c169060038210156118ce57610499916060820152604051918291826118d3565b3461001b575f8060031936011261081c57604051816009546119a881610612565b808452906001908181169081156107f457506001146119d1576104998461078f818803826106c9565b60098352602094507f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af5b828410611a1757505050816104999361078f928201019361077f565b80548585018701529285019281016119fb565b3461001b575f36600319011261001b57602064ffffffffff5f5460c01c16604051908152f35b3461001b575f36600319011261001b57600e546040516001600160601b039091168152602090f35b8015150361001b57565b3461001b57604036600319011261001b57600435611a9f8161087a565b60243590611aac82611a78565b335f52600d602052611ac18160405f20610cf0565b9115159160ff1981541660ff841617905560405191825260018060a01b0316907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b91909160608184031261001b57604051906001600160401b039060608301828111848210176106795760405282948135611b42816110ac565b84526020820135611b52816110ac565b6020850152604082013592831161001b57604092611b7092016111d7565b910152565b3461001b57604036600319011261001b576004356001600160401b03811161001b57611ba8610499913690600401611b09565b611bb0613c84565b7fea77d064c7d953e57748855e7b0751ea190d1df7505615a4e39336d4d548f688611d0e611bdf6002546139f2565b92611be984600255565b611d00611bf46133a6565b6060810151611cc9906001600160601b031691611cbd611c1660055460ff1690565b91611cae611c29825164ffffffffff1690565b611c99611c4d6040611c43602087015164ffffffffff1690565b95015161ffff1690565b95611c8f611c596110fa565b4264ffffffffff168152995f60208c0181905260408c0181905260608c0181905260808c01526001600160601b031660a08b0152565b60ff1660c0890152565b5f60e088015264ffffffffff16610100870152565b64ffffffffff16610120850152565b61ffff16610140830152565b611cd2836133fa565b611ce4875f52600660205260405f2090565b906002611cf9895f52600660205260405f2090565b0155613a6f565b604051918291338684613c39565b0390a1611d1d60243582613d1d565b506105ee614ddc565b3461001b575f36600319011261001b57611d3e613258565b506080604051611d4d8161065e565b5f80516020615f148339815191525464ffffffffff808216928381526020810191808460281c1683526040820190606061ffff93848760501c168452019360018060601b03809660601c168552604051968752511660208601525116604084015251166060820152f35b6001600160401b0381116106795760051b60200190565b9291611dd982611db7565b91611de760405193846106c9565b829481845260208094019160051b810192831161001b57905b828210611e0d5750505050565b81358152908301908301611e00565b9080601f8301121561001b5781602061074193359101611dce565b3461001b57602036600319011261001b576004356001600160401b03811161001b57611e6a61001f913690600401611e1c565b6116756154da565b3461001b57608036600319011261001b57600435611e8f8161087a565b602435611e9b8161087a565b604435916064356001600160401b03811161001b57611ebe903690600401610f73565b9092611ecb858285615855565b803b15159384611ee2575b50505050905061157357005b611f0c94505f6020949660405196879586948593630a85bd0160e11b9b8c86523360048701615d41565b03926001600160a01b03165af1908115611073575f91611f3e575b506001600160e01b0319161415805f808080611ed6565b611f56915060203d811161161b5761160d81836106c9565b5f611f27565b600811156118ce57565b9060088210156118ce5752565b61016061051b929493611f8b83610180810197611f66565b805164ffffffffff166020840152602081015164ffffffffff166040840152604081015164ffffffffff166060840152606081015164ffffffffff16608084015260808101516001600160601b031660a084015260a08101516001600160601b031660c084015260c081015160ff1660e084015260e0810151612016610100918286019060ff169052565b81015161202f610120918286019064ffffffffff169052565b81015190612049610140928386019064ffffffffff169052565b015161ffff16910152565b3461001b57602036600319011261001b576120c8604061014081516120788161067e565b5f91818380935282602082015282858201528260608201528260808201528260a08201528260c08201528260e08201528261010082015282610120820152015260043581526006602052206132eb565b6120d181614be9565b61049960405192839283611f73565b3461001b576020366003190112156159a0575f80fd5b3461001b575f36600319011261001b57602060405160028152f35b81601f8201121561001b5780359161212883611db7565b9261213660405194856106c9565b808452602092838086019260051b82010192831161001b578301905b828210612160575050505090565b838091833561216e8161087a565b815201910190612152565b359061ffff8216820361001b57565b359061051b8261087a565b91909160e08184031261001b576121a8611107565b928135916001600160401b03831161001b576121cb60c092612228948301612111565b85526121d9602082016110bb565b60208601526121ea604082016110bb565b60408601526121fb60608201612179565b606086015261220c60808201610510565b608086015261221d60a08201612179565b60a086015201612188565b60c0830152565b919082608091031261001b576040516122478161065e565b60608193803561225681611a78565b8352602081013561226681611a78565b6020840152604081013561227981611a78565b6040840152013590600382101561001b5760600152565b91906101008382031261001b576122a5611126565b926001600160401b03813581811161001b57836122c3918401612193565b85526122d2836020840161222f565b602086015260a082013581811161001b57836122ef9184016111d7565b604086015260c082013590811161001b5760e09261230e9183016111d7565b606085015201356080830152565b3461001b5760031960203682011261001b576004908135916001600160401b039182841161001b5760a090843603011261001b57612358611126565b918382013581811161001b5761237390833691870101612290565b8352602484013581811161001b5761239090833691870101612111565b6020840152604484013581811161001b576123b090833691870101611e1c565b6040840152606484013590811161001b5761001f936123d96084926123e4943691840101612111565b6060850152016110bb565b6080820152612fc2565b3461001b57606036600319011261001b5760206124256004356124108161087a565b60243561241c816110ac565b604435916132a9565b6040516001600160601b039091168152f35b3461001b57602036600319011261001b576004356001600160401b03811161001b5761087261246c6020923690600401611b09565b6133fa565b3461001b57602036600319011261001b5760043561248e816110ac565b61249661351d565b64ffffffffff9064ab2cb21860828216811461256b5760ff5f80516020615f548339815191525460181c166124ca816118c4565b1561255957600e5460c01c64ffffffffff1692831690646b5b567bfe821491821561254f575b5050612530577f33d3074d42e98b5940d3d8364ba0f3421c4fde9db929c3d1c2899a36c5b216f29161252182615094565b6105fe60405192839283613fa9565b60405163066a813560e51b815264ffffffffff83166004820152602490fd5b1490505f806124f0565b60405163064023b360e51b8152600490fd5b604051635f07128f60e01b8152600490fd5b6002111561001b57565b600211156118ce57565b9060028210156118ce5752565b3461001b57608036600319011261001b576101006125d96024356125c18161257d565b6044356125cd8161087a565b60643591600435613694565b61265f60e0604051926125ed848251612591565b6020810151602085015260018060a01b03806040830151166040860152806060830151166060860152608082015116608085015261263a60a082015160a086019060018060801b03169052565b60c0818101516001600160801b03169085015201516001600160601b031660e0830152565bf35b3461001b575f36600319011261001b576020600154604051908152f35b3461001b575f36600319011261001b57602060ff5f5460081c166040519015158152f35b3461001b57604036600319011261001b577ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce76105fe6004356105ee6024356126e9816104ff565b82816126f36154da565b600e5460601c6001600160601b03165f80516020615f14833981519152546001600160601b039260609190911c83169081151590816127bb575b506127ac575b506127725f80516020615ef4833981519152926127566105618761279695613290565b612768855f52600f60205260405f2090565b5495168095613421565b80612785855f52600f60205260405f2090565b556040519081529081906020820190565b0390a26127a283615cfa565b9060170b90614619565b81900382169350612772612733565b905083806127c985856147a9565b92169116105f61272d565b3461001b575f366003190112156159a0575f80fd5b3461001b57604036600319011261001b57602060ff61283460043561280d8161087a565b6024359061281a8261087a565b6001600160a01b03165f908152600d855260409020610cf0565b54166040519015158152f35b3461001b57602036600319011261001b5760043561285d8161087a565b60018060a01b03165f526003602052602060ff60405f2054166040519015158152f35b60c036600319011261001b576001600160401b0360243581811161001b576128ad60049136908301611b09565b9060443583811161001b576128c59036908301612111565b60643584811161001b576128dc9036908401611e1c565b9060843585811161001b576128f49036908501610f73565b92909160a43596871161001b5761291161001f9736908701610f73565b96909535613fc1565b3461001b57602036600319011261001b5761001f60043561293a8161087a565b61294333614b30565b61294f610a8733610ca5565b6001600160a01b039290838116612a40575033905b808416612a3a5750805b60208301516001600160601b0316936129ef6129b56129b06129ab61299c604089015160018060601b031690565b6001600160601b031660170b90565b6145d4565b615bfa565b918416916129df6129c4611145565b4264ffffffffff168152976001600160601b03166020890152565b6001600160601b03166040870152565b338114156060860152612a028533614a01565b612a0f836108ec33610ca5565b337fad2543a59f1b8c397ab540030b195cbeea5fadc4d5560e9fdf1ca5f750b725065f80a3336147c2565b9061296e565b90612964565b3461001b575f8060031936011261081c57604051635c9fcd8560e11b8152600b60048201526001600160a01b03906020816024817f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade86165afa908115611073578391612adc575b501633141580612ac7575b610e1857612ac461420e565b80f35b50612ad761096561095e33610cbe565b612ab8565b612af4915060203d811161106c5761105e81836106c9565b5f612aad565b9181601f8401121561001b578235916001600160401b03831161001b576020808501948460051b01011161001b57565b3461001b57608036600319011261001b5760046001600160401b03813581811161001b57612b5b9036908401612afa565b9160243581811161001b57612b739036908601612afa565b9160443590811161001b57612b8b9036908701612afa565b9560643596612b998861087a565b8615612fb257335f908152601060205260409020612bb69061095e565b92612bcb600e5464ffffffffff9060c01c1690565b93159081612f4a575b600e805464ffffffffff60c01b19166405596590c360c51b1790555f805464ffffffffff60c01b19164260c01b64ffffffffff60c01b16179055612c1787615765565b91888a5f805b8b8210612de8575050612c4192612c3c610b4a93610b2a933691611dce565b61564b565b5f5460101c61ffff1661ffff165f5b888110612c96577f1d1937c6b6f4541f415f6e3e99b2b7a960dcedc201d01deada3d90b8cf77f9578b8b6105fe8f8d8d612c898e615094565b60405195869533876157b1565b612ca9612ca4828b8b615797565b6157a7565b612cb382866150bb565b51612cc9612cc18583613d0a565b612710900490565b80612d6b575b50612cdb838887615797565b35808210612d46575090818e612cf99493612cfe575b5050506139f2565b612c50565b6001600160a01b039280841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee03612d375750612d2f9216615a8a565b5f808e612cf1565b612d419350615ae5565b612d2f565b60408051632d9eac9360e01b8152808b01938452602084019290925290918291010390fd5b9081612d7691613483565b906001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee03612db9575f54612db3919060201c6001600160a01b0316615a8a565b5f612ccf565b5f54612de39190612ddd9060201c6001600160a01b03165b6001600160a01b031690565b84615ae5565b612db3565b91509150612dfd612dd1612ca4848d8d615797565b6001600160a01b039091161015612f3957879073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee612e43612dd180612ca4858f612e3d8383838c615797565b98615797565b14818b8b5f935f14612ed05750505050475b5f5b8d8d818310612e765750505050612e6d906139f2565b8b908b92612c1d565b612eab612e9d612e97612e9186612ecb9796612ebb96615797565b35615481565b86613d0a565b670de0b6b3a7640000900490565b612eb5868b6150bb565b51613421565b612ec5858a6150bb565b526139f2565b612e57565b612ee192612dd192612ca492615797565b6040516370a0823160e01b815230818b0190815290916020918291849182908190850103915afa9283156110735792612f1c575b5050612e55565b612f329250803d10611503576114f481836106c9565b5f80612f15565b604051633a67cf6d60e01b81528690fd5b64ffffffffff8516646b5b567bfe8103612f65575b50612bd4565b64ab2cb218608114908115612fa8575b50612f80575f612f5f565b505060405163a16caf5360e01b815264ffffffffff9093169183019182525081906020010390fd5b905042115f612f75565b50604051630c48157760e11b8152fd5b5f90815460ff81166131be5760ff1916600190811783557f5daa87a0e9463431830481fd4b6e3403442dfb9a12b9c07597e9f61d50b633c88380a18082519260408401519360608101519461305160808301519661304c602085519501519361304760208801516040890151908764ffffffffff608060608d01519c015116996150cf565b614ed4565b614fb4565b8161318f575b505084915b613131575b5050508061306d575050565b604051635c9fcd8560e11b8152601660048201526001600160a01b03906020816024817f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade86165afa908115611073578491613113575b501690813b1561310f5760405163fc9968df60e01b8152600481019190915291908290602490829084905af18015611073576130fc5750565b8061310961051b9261069a565b80610608565b8280fd5b61312b915060203d811161106c5761105e81836106c9565b5f6130c3565b805182101561318a57828261318361317661315d6131508597876150bb565b516001600160a01b031690565b6001600160a01b03165f90815260106020526040902090565b805460ff19166001179055565b019161305c565b613061565b6060919350015161319f816118c4565b6131a8816118c4565b15612559576131b78392615094565b5f80613057565b60405162dc149f60e41b8152600490fd5b3660041161001b575f356001600160e01b03191663bc197c8160e01b81148015613248575b8015613238575b613227575f80516020615f94833981519152546001600160a01b0316613221368061116d565b90615c41565b602090604051908152818101604052f35b50630a85bd0160e11b81146131fb565b5063f23a6e6160e01b81146131f4565b604051906132658261065e565b5f6060838281528260208201528260408201520152565b634e487b7160e01b5f52601160045260245ffd5b6001600160601b03918216908216019190821161060357565b916132b791610741936144e6565b6060810151156132d7575f905b602001516001600160601b031690613290565b60408101516001600160601b0316906132c4565b9061051b61ffff6132fa6110fa565b845464ffffffffff8082168352602882901c81166020840152605082901c81166040840152607882901c8116606084015260a09190911c6080830152909461339490600101546001600160601b03811660a088015291606083901c60ff1660c0880152606883901c60ff1660e088015264ffffffffff607084901c8216166101008801528260981c1661012087019064ffffffffff169052565b60c01c1661014084019061ffff169052565b604051906133b38261065e565b5f80516020615f148339815191525464ffffffffff8082168452602882901c166020840152605081901c61ffff166040840152606090811c6001600160601b031690830152565b9060408201916060835191825160208401208552209252565b906001820180921161060357565b9190820180921161060357565b8115613438570490565b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b805482101561167a575f5260205f2001905f90565b5f1981019190821161060357565b9190820391821161060357565b6001600160a01b03165f9081526007602052604081208054925b8383106134c857505050806134bf57505f1990565b61074190613475565b9091928084018085116106035760011c906134f26134e68386613460565b505464ffffffffff1690565b64ffffffffff8481169116111561350d5750925b91906134aa565b935061351890613413565b613506565b335f52600360205260ff60405f20541615610e1857565b60405190613541826106ad565b8160e05f918281528260208201528260408201528260608201528260808201528260a08201528260c08201520152565b519061051b8261087a565b9081602091031261001b57516107418161087a565b6040513d5f823e3d90fd5b6040919493926135b0826060810197612591565b6001600160a01b031660208201520152565b51906001600160801b038216820361001b57565b519061051b826104ff565b908161010091031261001b5761367160e0604051926135ff846106ad565b805161360a8161257d565b84526020810151602085015261362260408201613571565b604085015261363360608201613571565b606085015261364460808201613571565b608085015261365560a082016135c2565b60a085015261366660c082016135c2565b60c0850152016135d6565b60e082015290565b1561368057565b634e487b7160e01b5f52600160045260245ffd5b909261369e613534565b506136a7613957565b3033036138b1575b5f80516020615f148339815191525460601c6001600160601b03161561389f57604051635c9fcd8560e11b8152600c60048201526001600160a01b03906020816024817f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade86165afa8015611073578261375c917fdda962f630bf2f85c8412f305206a4f363688481dd632689f88ad7022e4cc233935f91613881575b501693604051918291888a8461359c565b0390a1613767614ddc565b5f549361ffff828660201c169560101c169561378281612587565b801561383b576137ff93925f9697926137a96001846137a36137b296612587565b14613679565b16948386615ae5565b60405163eedaf00d60e01b81526001600160a01b03948516600482015230602482015295909316604486015261ffff90921660648501526101009392849284929091839182906084820190565b03925af1918215611073575f9261381557505090565b6107419250803d10613834575b61382c81836106c9565b8101906135e1565b503d613822565b5050604051631d1972a760e11b81523060048201526001600160a01b0390941660248501525061ffff9093166044830152610100928391839190829081606481016137ff565b613899915060203d811161106c5761105e81836106c9565b5f61374b565b6040516311bf009f60e21b8152600490fd5b60ff5f80516020615f548339815191525460181c166138cf816118c4565b613930576138dc33614b30565b60408101516001600160601b031615908161390a575b50156136af5760405163ea8e4eb560e01b8152600490fd5b6020015161392991506001600160601b03165b6001600160601b031690565b155f6138f2565b604051632e31362d60e01b8152600490fd5b9081602091031261001b575161074181611a78565b6040516331a1aa3360e11b8152601560048201526020816024817f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade6001600160a01b03165afa908115611073575f916139c4575b506139b257565b604051632fb3e88560e01b8152600490fd5b6139e5915060203d81116139eb575b6139dd81836106c9565b810190613942565b5f6139ab565b503d6139d3565b5f1981146106035760010190565b805464ffffffffff60281b191660289290921b64ffffffffff60281b16919091179055565b805464ffffffffff60501b191660509290921b64ffffffffff60501b16919091179055565b805464ffffffffff60781b191660789290921b64ffffffffff60781b16919091179055565b90613c1d610140600161051b94613aa6613a8e865164ffffffffff1690565b825464ffffffffff191664ffffffffff909116178255565b613ac1613abb602087015164ffffffffff1690565b82613a00565b613adc613ad6604087015164ffffffffff1690565b82613a25565b613af7613af1606087015164ffffffffff1690565b82613a4a565b6080850151613b29906001600160601b031682546001600160a01b031660a09190911b6001600160a01b031916178255565b60a0850151910180546001600160601b0319166001600160601b0390921691909117815592613b79613b5f60c083015160ff1690565b855460ff60601b191660609190911b60ff60601b16178555565b613ba4613b8a60e083015160ff1690565b855460ff60681b191660689190911b60ff60681b16178555565b613bdc613bba61010083015164ffffffffff1690565b855464ffffffffff60701b191660709190911b64ffffffffff60701b16178555565b613c14613bf261012083015164ffffffffff1690565b855464ffffffffff60981b191660989190911b64ffffffffff60981b16178555565b015161ffff1690565b815461ffff60c01b191660c09190911b61ffff60c01b16179055565b916107419360409160c093855260018060a01b0316602085015260608285015264ffffffffff8082511660608601526020820151166080850152015191606060a0820152019061070b565b613c8d33614b30565b60408101516001600160601b03908116159182613cad575b5050610e1857565b60200151161590505f80613ca5565b60208101929161051b9190611f66565b64ffffffffff9081165f19019190821161060357565b60ff1660ff81146106035760010190565b906127109182810292818404149015171561060357565b8181029291811591840414171561060357565b90613d30825f52600660205260405f2090565b91613d3a836132eb565b90613d4482614be9565b613d4d81611f5c565b600181141580613f95575b80613f81575b610c4357505f5460c01c64ffffffffff1664ffffffffff9081164214613f6c576003850194613d9061095e3388610cf0565b613f5457613dc961391d95613dac613176610741993390610cf0565b613dc3613dbe875164ffffffffff1690565b613ccc565b336132a9565b937fea45672a2d92b09ff2dd48aa67615f8b5c79d7808b7282fc026a24e00283f78d613e586080830196613e17613e0a82610a428b5160018060601b031690565b6001600160601b03168952565b613e2361095e33610cbe565b613f2e575b613e328486613a6f565b604080518881523360208201526001600160601b03909216908201529081906060820190565b0390a182613e6e602083015164ffffffffff1690565b16159081613ecf575b50613e8f575b505090516001600160601b0316919050565b613e9b91421690613a00565b7fe36f8b7448daff4a52e2945db0d1d7a436279cc1d527a45c27835dcbd27f336d5f80a2613ec7614ddc565b5f8080613e7d565b9050613f26613f1f610140613f15613ef8613ef361391d8b5160018060601b031690565b613cf3565b60a0860151613f0f906001600160601b031661391d565b9061342e565b93015161ffff1690565b61ffff1690565b11155f613e77565b613f4f60e08501613f48613f43825160ff1690565b613ce2565b60ff169052565b613e28565b604051630b517d8f60e41b8152336004820152602490fd5b6040516001621af97960e21b03198152600490fd5b50613f8b81611f5c565b6004811415613d5e565b50613f9f81611f5c565b6003811415613d58565b64ffffffffff91821681529116602082015260400190565b93949196929096613fd0613957565b613fd8613c84565b613fea855f52600660205260405f2090565b97613ff960028a015482614dfb565b614002896132eb565b9661400c88614be9565b61401581611f5c565b60048114908115806140f2575b610c435761402f90611f5c565b6140ae575b6140416109658585614dab565b61409c576140849861407661407e9261406e6109659b6140698f64ffffffffff421690613a4a565b614b79565b9736916111a1565b9636916111a1565b956143c2565b61408b5750565b805464ffffffffff60781b19169055565b604051633b43666f60e01b8152600490fd5b815164ffffffffff9081164281106140d257506140cd9042168b613a25565b614034565b604051632f7e600560e21b8152918291610c609142169060048401613fa9565b506140fc81611f5c565b6005811415614022565b35610741816110ac565b9081602091031261001b575190565b3d15614149573d9061413082611152565b9161413e60405193846106c9565b82523d5f602084013e565b606090565b90939260ff5f5460081c166141dc575f806040518588823780868101838152039084865af161417b61411f565b90156141d457506141c97f66cf5924183d7d44caa75d9268a169d7c1422fef43848743d5e1ba32d5833acf949560405194859460018060a01b031685526060602086015260608501916141ee565b9060408301520390a1565b602081519101fd5b6040516304e71fd360e31b8152600490fd5b908060209392818452848401375f828201840152601f01601f1916010190565b61010061ff00195f5416175f557f447e75484d6bdb571b4a92ae14018db7b6dd41f3f02360690c554e1d48f46f875f80a1565b9081518082526020808093019301915f5b828110614260575050505090565b835185529381019392810192600101614252565b919060209283815281518482015261429b8483015160e0604084015261010083019061070b565b906142cf6142bb604085015193601f19948585830301606086015261070b565b60608501518484830301608085015261070b565b92608081015160a083015260a081015193838382030160c08401528680865192838152019501905f5b81811061431c5750505061074194955060c060e09101519282850301910152614241565b82516001600160a01b0316875295880195918801916001016142f8565b81601f8201121561001b57805161434f81611152565b9261435d60405194856106c9565b8184526020828401011161001b5761074191602080850191016106ea565b9060208282031261001b5781516001600160401b03811161001b576107419201614339565b6001600160a01b0390911681526040602082018190526107419291019061070b565b95935f9593929194604087960151946143d9611107565b898152602081019690965260408601526060850152608084015260a083015260c08201525f80516020615f94833981519152546001600160a01b03169060405161443881611270602082019463a7c8a3f960e01b865260248301614274565b51915af461444461411f565b901561148e578060208061445d9351830101910161437b565b907fc98fbf8f20b11b050a9541d12aee1c11fcd31e8e42975cc885fb3d33a6accc826040518061448e8533836143a0565b0390a2614499614ddc565b511590565b906040516144ab8161065e565b915464ffffffffff81168352602881901c6001600160601b039081166020850152608882901c16604084015260e81c60ff1615156060830152565b91906144f0613258565b6001600160a01b0384165f9081526007602052604090209093909283548061451b575b505050505090565b80821090816145b2575b81614572575b5061456157509061453b91613490565b906001820161454c57808080614513565b61074192509061455b91613460565b5061449e565b915050610741925061455b91613460565b61457c9150613475565b8114801561458b575b5f61452b565b506145a16134e661459b83613413565b86613460565b64ffffffffff808516911611614585565b90506145c16134e68387613460565b64ffffffffff8086169116111590614525565b60170b906001600160bf1b0382136001600160bf1b031983121761060357565b601791820b910b01906001600160bf1b031982126001600160bf1b0383131761060357565b9061051b9161462781614b30565b906001600160a01b038061463a83610ca5565b5416806146f757508182915b602085015160408601516001600160601b039182169761466d926129b0921660170b6145f4565b906146ae8184169185169261469e614683611145565b4264ffffffffff168152996001600160601b031660208b0152565b6001600160601b03166040890152565b8181141560608801526146c18784614a01565b6146ce846108ec85610ca5565b7fad2543a59f1b8c397ab540030b195cbeea5fadc4d5560e9fdf1ca5f750b725065f80a36147c2565b918291614646565b9161051b9261470d81614b30565b9161471a610a8783610ca5565b6001600160a01b0392908381166147a3575080915b80841661479d575081925b602085015160408601516001600160601b0391821697614767926129b092614762911661299c565b6145f4565b9061477d8184169186169261469e614683611145565b8181141560608801526147908784614a01565b6146ce856108ec85610ca5565b9261473a565b9161472f565b6001600160601b03918216908216039190821161060357565b90936001600160a01b038381169491928515801561494e575b61493c578116908616958187141580614932575b6148d7575b508403614803575b5050505050565b6148a79461483361481385614b30565b602081015160409095015190946001600160601b03908116911690613290565b94146148b1575b5060408101516148a2919061489990614862906060906001600160601b03165b930151151590565b9161488961486e611145565b4264ffffffffff168152966001600160601b03166020880152565b6001600160601b03166040860152565b15156060840152565b614a01565b5f808080806147fc565b6040015190926148a2916148d091906001600160601b03165b906147a9565b929061483a565b806148e461492c92614b30565b60208101519091906148a290614910906001600160601b031660408801516001600160601b03166148ca565b92614899614862606061485a604085015160018060601b031690565b5f6147f4565b50858714156147ef565b60405163e5ec2d2560e01b8152600490fd5b50818716156147db565b91906149c557805182546020830151604084015160609094015164ffffffffff9093166001600160f01b03199092169190911760289190911b600160281b600160881b03161760889290921b600160881b600160e81b03169190911790151560e81b60ff60e81b16179055565b634e487b7160e01b5f525f60045260245ffd5b80549190600160401b83101561067957826149fb91600161051b95018155613460565b90614958565b81516020830151604084015164ffffffffff9493614ac2939092908616917f59c8109016c9c9310894a72309b48d2a442208dacb537923fca808618ce57102916001600160601b03908116911690614aa6614a5f6060890151151590565b6040805164ffffffffff90971687526001600160601b039384166020880152929093169185019190915290151560608401526001600160a01b038416929081906080820190565b0390a26001600160a01b03165f90815260076020526040902090565b9182549081614ad7575b505061051b916149d8565b614afa614aef61455b614ae985613475565b87613460565b5164ffffffffff1690565b90614b0d61131f855164ffffffffff1690565b911614614b1a5780614acc565b61051b92614b2a6149fb92613475565b90613460565b90614b39613258565b6001600160a01b039092165f90815260076020526040902080549081614b5d575050565b9192505f19810191908211610603576107419161455b91613460565b608081015160a08201515f9291614b9c916001600160601b039081169116614d5d565b614bc7575b8060ff60e08160c0614bba950151169201511690614d91565b614bc15790565b60021790565b60019150614ba1565b91909164ffffffffff8080941691160191821161060357565b64ffffffffff80614bff835164ffffffffff1690565b1615614d5757614c1a61131f604084015164ffffffffff1690565b614d25576080820180519092906001600160601b0390811614614d1d5781421692614c4d602083015164ffffffffff1690565b838116614c9357505080614c7c610100614c6f614c82945164ffffffffff1690565b92015164ffffffffff1690565b90614bd0565b161115614c8e57600190565b600290565b614caf90614c7c610120859795969496015164ffffffffff1690565b161115614d165751614cd8906001600160601b031660a08301516001600160601b031690614d5d565b614d105780614cfc60e0614cf360c0614d0295015160ff1690565b92015160ff1690565b90614d91565b614d0b57600390565b600490565b50600490565b5050600490565b505050600290565b60609091015164ffffffffff1690811615614d5157600160271b80911614614d4c57600690565b600790565b50600590565b50505f90565b6001600160601b0391906127109083168181029181159183041417156106035761270f92614d8c92169061342e565b101590565b60ff168015159182614da257505090565b60ff1614919050565b60015491614db891614dbc565b1490565b6020815160051b9101205f526020815160051b91012060205260405f2090565b5f80516020615f34833981519152604080515f81525f196020820152a1565b614e04906133fa565b90818103614e10575050565b6044925060405191630267877160e11b835260048301526024820152fd5b601f8111614e3a575050565b5f906008825260208220906020601f850160051c83019410614e77575b601f0160051c01915b828110614e6c57505050565b818155600101614e60565b9092508290614e57565b601f8111614e8d575050565b5f906009825260208220906020601f850160051c83019410614eca575b601f0160051c01915b828110614ebf57505050565b818155600101614eb3565b9092508290614eaa565b9081516001600160401b03811161067957614ef981614ef4600854610612565b614e2e565b602080601f8311600114614f3357508192935f92614f28575b50508160011b915f199060031b1c191617600855565b015190505f80614f12565b60085f52601f198316949091907ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee3925f905b878210614f9c575050836001959610614f84575b505050811b01600855565b01515f1960f88460031b161c191690555f8080614f79565b80600185968294968601518155019501930190614f65565b9081516001600160401b03811161067957614fd981614fd4600954610612565b614e81565b602080601f831160011461501357508192935f92615008575b50508160011b915f199060031b1c191617600955565b015190505f80614ff2565b60095f52601f198316949091907f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af925f905b87821061507c575050836001959610615064575b505050811b01600955565b01515f1960f88460031b161c191690555f8080615059565b80600185968294968601518155019501930190615045565b600e805464ffffffffff60c01b191660c09290921b64ffffffffff60c01b16919091179055565b805182101561167a5760209160051b010190565b9260a08401926150e1845161ffff1690565b9361271061ffff95818782161161540e575060209182880192615109845164ffffffffff1690565b9764ffffffffff98610e108a821610615436575060608a019361512e855161ffff1690565b91821690811591821561542c575b505061540e5750604097888a0190615159825164ffffffffff1690565b9081168015908115615401575b506153e157508851635c9fcd8560e11b815260026004820152916001600160a01b039080846024817f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade86165afa8015611073578c61526661530a9861523f8f6153669f61522761521b6153239f614aef615230946152e39f9d6080976152809f9d8f6152709f5f926153bc575b5061520761521592935195869283016118d3565b03601f1981018552846106c9565b16615a1c565b9a5164ffffffffff1690565b935161ffff1690565b9401516001600160601b031690565b9461525861524b611145565b64ffffffffff9099168952565b87019064ffffffffff169052565b61ffff16848d0152565b6001600160601b03166060830152565b64ffffffffff8151165f80516020615f148339815191529182549164ffffffffff60281b602083015160281b169061ffff60501b604084015160501b169260606001811b600160c01b0391015160601b169360018060c01b031916171717179055565b6153026152f289515160ff1690565b60ff1660ff196005541617600555565b5161ffff1690565b63ffff00005f549160101b169063ffff00001916175f55565b60c0850151615361906001600160a01b03165f8054640100000000600160c01b03191660209290921b640100000000600160c01b0316919091179055565b615457565b60ff825151116153a957505f5b81519081518110156153a45761539a6131766153956131508461539f966150bb565b610cbe565b6139f2565b615373565b505050565b5160016211dcdd60e31b03198152600490fd5b61521592506153da61520791833d851161106c5761105e81836106c9565b92506151f3565b8951636dfaf3cd60e01b815264ffffffffff919091166004820152602490fd5b62278d009150115f615166565b6040516323dd0d6d60e11b815261ffff919091166004820152602490fd5b1190505f8061513c565b604051636dfaf3cd60e01b815264ffffffffff919091166004820152602490fd5b90815181510361546f5761546a91614dbc565b600155565b6040516357cc2fc760e01b8152600490fd5b5f80516020615f148339815191525460601c6001600160601b0316905f826154aa575050505f90565b6040918152600f602052205490670de0b6b3a764000091828102928184041490151715610603576107419161342e565b335f52601060205260ff60405f20541615610e1857565b60170b6001600160bf1b03198114610603575f0390565b905f8092815b815181101561560957807f49995e5dd6158cf69ad3e9777c46755a1a826a446c6416992167462dad033b2a61554661560493856150bb565b519661555188615cfa565b976155fc61557a61557361556d845f52600f60205260405f2090565b54615bce565b8094613290565b998861558e845f52600f60205260405f2090565b556155cd604091845f80516020615ef48339815191528451806155b581905f602083019252565b0390a26105e86001600160601b03871660170b6154f1565b6155d683615d72565b5133815260208101929092526001600160601b0390921660408201529081906060820190565b0390a16139f2565b61550e565b5050600e5461562a915061056190849060601c6001600160601b03166147a9565b604080515f81525f1960208201525f80516020615f348339815191529190a1565b91905f9283845b8251811015615741579081615669849386956150bb565b5161567381615cfa565b956156d7575b6156ce92816155fc6156ba61557361556d7f49995e5dd6158cf69ad3e9777c46755a1a826a446c6416992167462dad033b2a965f52600f60205260405f2090565b988b61558e845f52600f60205260405f2090565b92909192615652565b336001600160a01b038716141580615720575b80615707575b156156795760405163ea8e4eb560e01b8152600490fd5b5061571b61096561095e336109598a610c8c565b6156f0565b503361573a612dd1610a87845f52600c60205260405f2090565b14156156ea565b50600e5490945061562a92506105619150849060601c6001600160601b03166147a9565b9061576f82611db7565b61577c60405191826106c9565b828152809261578d601f1991611db7565b0190602036910137565b919081101561167a5760051b0190565b356107418161087a565b6001600160a01b03918216815260806020808301829052908201859052909796959390926001600160fb1b03821161001b5760c0916005959493951b809160a08b013788018360a0820160a08b84030160408c0152520193925f905b83821061582f57505050505090606061051b9294019060018060a01b03169052565b909192939483806001928489356158458161087a565b168152019601949392019061580d565b5f838152600f60205260409020546001600160bf1b03811161598857615899906001600160c01b031660170b61589361588d826154f1565b84614619565b83614619565b6158b1612dd1610a87855f52600a60205260405f2090565b6001600160a01b038083169291830361093457831692831561180c57823314158061596f575b8061594e575b610934576158ed61591692610cd7565b80545f190190556158fd81610cd7565b805460010190556108ec855f52600a60205260405f2090565b61593b61592b845f52600c60205260405f2090565b80546001600160a01b0319169055565b5f80516020615f748339815191525f80a4565b50615967612dd1610a87875f52600c60205260405f2090565b3314156158dd565b5061598361096561095e3361095986610c8c565b6158d7565b6024906040519063e9a5989b60e01b82526004820152fd5b604051635c9fcd8560e11b81526004808201526020816024817f0000000000000000000000001ca20040ce6ad406bc2a6c89976388829e7fbade6001600160a01b03165afa908115611073575f916159fe575b50613221363661116d565b615a16915060203d811161106c5761105e81836106c9565b5f6159f3565b5f80516020615f9483398151915280546001600160a01b039283166001600160a01b03198216811790925560405163347d5e2560e21b602082019081525f9586959193615a7592849261127092909116602484016143a0565b51915af4615a8161411f565b90156141d45750565b8115615ae1576001600160a01b0316905f90819081908190855af190615aae61411f565b9115615ab8575050565b610c6060405192839263354db69760e01b8452600484015260406024840152604483019061070b565b5050565b60405163a9059cbb60e01b602082019081526001600160a01b03841660248301526044820185905292949193925f91829190615b248160648101611270565b5190826001600160a01b0388165af1615b3b61411f565b90615b73575b5050604051631702a98760e11b81526001600160a01b0392831660048201529290911660248301526044820152606490fd5b805115615b9d5780602080615b8d93518301019101613942565b615b975780615b41565b92505050565b50925050803b15615bab5750565b604051639fe23a3960e01b81526001600160a01b03919091166004820152602490fd5b6001600160601b0390818111615be2571690565b60249060405190636f55e21560e11b82526004820152fd5b8060170b5f81128015615c31575b615c1957506001600160601b031690565b602490604051906394e08f6160e01b82526004820152fd5b506001600160601b038113615c08565b303b1561001b5760405190633e4011b960e01b82528180615c685f958694600484016143a0565b0381305afa9081615ce3575b50615ccf57615c8161411f565b805181019160408284031261081c57602082015192615c9f84611a78565b6040830151916001600160401b03831161081c5750615cc5926020918201920101614339565b90615cf2576141d4565b634e487b7160e01b81526001600452602490fd5b615cec9061069a565b5f615c74565b602081519101f35b5f908152600a60205260409020546001600160a01b0316908115615d1a57565b604051634d5e5fb360e01b8152600490fd5b9081602091031261001b57516107418161042b565b6001600160a01b039182168152911660208201526040810191909152608060608201819052610741939101916141ee565b5f818152600a60205260408120546001600160a01b0316801561093457808252600b602052604082205f198154019055615db4835f52600a60205260405f2090565b80546001600160a01b03199081169091555f848152600c602052604090209081541690555f80516020615f748339815191528280a4565b90615df68183615e94565b813b15159182615e09575b505061157357565b604051630a85bd0160e11b8082523360048301525f6024830181905260448301949094526080606483015260848201849052935091602091839160a4918391906001600160a01b03165af1908115611073575f91615e76575b506001600160e01b03191614155f80615e01565b615e8e915060203d811161161b5761160d81836106c9565b5f615e62565b6001600160a01b038181169190821561180c57835f52600a60205260405f2054166109345780615ec6615edf92610cd7565b600181540190556108ec845f52600a60205260405f2090565b5f5f80516020615f748339815191528180a456fe84a9a38a0d320e93bcc5ebdabf23f355777c9b2251f0a2eceb54e0bddcf6f728eb054550c406db3b89dc7016369a66aff0ce40188133281942b92e6188c6b1f16bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661ceb054550c406db3b89dc7016369a66aff0ce40188133281942b92e6188c6b1f0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efeb054550c406db3b89dc7016369a66aff0ce40188133281942b92e6188c6b1efa264697066735822122045bd91fe3d3d061af7cc89368f87f03aa3210c97ebe816f8783a32e9e8294eef64736f6c63430008140033
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
[ Download: CSV Export ]
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.