Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
TimedRound
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 10000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { AssetRound } from './base/AssetRound.sol'; import { Asset, PackedAsset } from '../lib/types/Common.sol'; import { ITimedRound } from '../interfaces/ITimedRound.sol'; import { AssetHelper } from '../lib/utils/AssetHelper.sol'; import { MerkleProof } from '../lib/utils/MerkleProof.sol'; import { Selector, RoundType } from '../Constants.sol'; import { Uint256 } from '../lib/utils/Uint256.sol'; contract TimedRound is ITimedRound, AssetRound { using { Uint256.mask250 } for bytes32; using { AssetHelper.pack } for Asset; using { AssetHelper.packMany } for Asset[]; /// @notice The amount of time before an asset provider can reclaim unclaimed assets uint256 public constant RECLAIM_UNCLAIMED_ASSETS_AFTER = 4 weeks; /// @notice The amount of time before the security council can emergency withdraw assets uint256 public constant EMERGENCY_WITHDRAW_ASSETS_AFTER = 8 weeks; /// @notice Maximum winner count for this strategy uint256 public constant MAX_WINNER_COUNT = 25; /// @notice The minimum proposal submission period duration uint256 public constant MIN_PROPOSAL_PERIOD_DURATION = 60 minutes; /// @notice The minimum vote period duration uint256 public constant MIN_VOTE_PERIOD_DURATION = 60 minutes; /// @notice The current state of the timed round. `Active` upon deployment. RoundState public state; /// @notice The timestamp at which the round was finalized. `0` if not finalized. uint40 public finalizedAt; /// @notice The timestamp at which the proposal period starts. `0` if not registered. uint40 public proposalPeriodStartTimestamp; /// @notice The proposal period duration in seconds. `0` if not registered. uint40 public proposalPeriodDuration; /// @notice The vote period duration in seconds. `0` if not registered. uint40 public votePeriodDuration; /// @notice The number of possible winners. `0` if not registered. uint16 public winnerCount; constructor( uint256 _classHash, address _propHouse, address _starknet, address _messenger, uint256 _roundFactory, uint256 _executionRelayer, address _manager ) AssetRound( RoundType.TIMED, _classHash, _propHouse, _starknet, _messenger, _roundFactory, _executionRelayer, _manager ) {} /// @notice Initialize the round by defining the round's configuration /// and registering it on L2. /// @dev This function is only callable by the prop house contract function initialize(bytes calldata data) external payable onlyPropHouse { _register(abi.decode(data, (RoundConfig))); } /// @notice Checks if the `user` is a winner in the round when no assets were offered /// @param user The Ethereum address of the user /// @param proposalId The winning proposal ID /// @param position The rank or order of a winner in the round /// @param proof The Merkle proof verifying the user's inclusion at the specified position in the round's winner list function isWinner( address user, uint256 proposalId, uint256 position, bytes32[] calldata proof ) external view returns (bool) { return MerkleProof.verify(proof, winnerMerkleRoot, keccak256(abi.encode(user, proposalId, position))); } /// @notice Checks if the `user` is a winner in the round when assets were offered /// @param user The Ethereum address of the user /// @param proposalId The winning proposal ID /// @param position The rank or order of a winner in the round /// @param asset The asset that was won by the user /// @param proof The Merkle proof verifying the user's inclusion in the round's winner list function isAssetWinner( address user, uint256 proposalId, uint256 position, Asset calldata asset, bytes32[] calldata proof ) public view returns (bool) { return MerkleProof.verify( proof, winnerMerkleRoot, _computeClaimLeaf(proposalId, position, user, asset.pack()) ); } /// @notice Cancel the timed round /// @dev This function is only callable by the round manager function cancel() external payable onlyRoundManager { _cancel(); emit RoundCancelled(); } /// @notice Cancel the timed round in the event of an emergency /// @dev This function is only callable by the owner of the security council function emergencyCancel() external payable onlySecurityCouncil { _cancel(); emit RoundEmergencyCancelled(); } /// @notice Finalize the round by consuming the merkle root from Starknet. /// @param merkleRootLow The lower half of the split merkle root /// @param merkleRootHigh The higher half of the split merkle root function finalize(uint256 merkleRootLow, uint256 merkleRootHigh) external { if (state != RoundState.Active) { revert FINALIZATION_NOT_AVAILABLE(); } uint256[] memory payload = new uint256[](2); payload[0] = merkleRootLow; payload[1] = merkleRootHigh; // This function will revert if the message does not exist starknet.consumeMessageFromL2(executionRelayer, payload); // Reconstruct the merkle root, store it, and move the round to the finalized state winnerMerkleRoot = bytes32((merkleRootHigh << 128) + merkleRootLow); finalizedAt = uint40(block.timestamp); state = RoundState.Finalized; emit RoundFinalized(); } /// @notice Claim a round award asset to a custom recipient /// @param recipient The asset recipient /// @param proposalId The winning proposal ID /// @param position The rank or order of the winner in the round /// @param asset The asset to claim /// @param proof The merkle proof used to verify the validity of the asset payout function claimTo( address recipient, uint256 proposalId, uint256 position, Asset calldata asset, bytes32[] calldata proof ) external { _claimTo(recipient, proposalId, position, asset, proof); } /// @notice Claim a round award asset to the caller /// @param proposalId The winning proposal ID /// @param position The rank or order of the winner in the round /// @param asset The asset to claim /// @param proof The merkle proof used to verify the validity of the asset payout function claim(uint256 proposalId, uint256 position, Asset calldata asset, bytes32[] calldata proof) external { _claimTo(msg.sender, proposalId, position, asset, proof); } /// @notice Reclaim assets to a custom recipient /// @param recipient The asset recipient /// @param assets The assets to reclaim function reclaimTo(address recipient, Asset[] calldata assets) public { // prettier-ignore // Reclamation is only available when the round has been cancelled OR // the round has been finalized and is in the reclamation period if (state == RoundState.Active || (state == RoundState.Finalized && block.timestamp - finalizedAt < RECLAIM_UNCLAIMED_ASSETS_AFTER)) { revert RECLAMATION_NOT_AVAILABLE(); } _reclaimTo(recipient, assets); } /// @notice Reclaim assets to the caller /// @param assets The assets to reclaim function reclaim(Asset[] calldata assets) external { reclaimTo(msg.sender, assets); } /// @notice Emergency withdraw assets to a custom recipient /// @param recipient The asset recipient /// @param assets The assets to withdraw /// @dev This function is only callable by the security council once enough time has passed /// since the round was scheduled to end. function emergencyWithdrawTo(address recipient, Asset[] calldata assets) external onlySecurityCouncil { uint256 scheduledEnd = proposalPeriodStartTimestamp + proposalPeriodDuration + votePeriodDuration; if (block.timestamp < scheduledEnd || block.timestamp - scheduledEnd < EMERGENCY_WITHDRAW_ASSETS_AFTER) { revert EMERGENCY_WITHDRAWAL_NOT_AVAILABLE(); } for (uint256 i = 0; i < assets.length; ++i) { _transfer(assets[i], address(this), payable(recipient)); } } // prettier-ignore /// @notice Generate the payload required to register the round on L2 /// @param config The round configuration function getRegistrationPayload(RoundConfig memory config) public view returns (uint256[] memory payload) { uint256 vsCount = config.votingStrategies.length; uint256 vsParamFlatCount = config.votingStrategyParamsFlat.length; uint256 psCount = config.proposingStrategies.length; uint256 psParamsFlatCount = config.proposingStrategyParamsFlat.length; uint256 strategyParamsCount = vsCount + vsParamFlatCount + psCount + psParamsFlatCount; payload = new uint256[](14 + strategyParamsCount); // `payload[0]` is reserved for the round address, which is // set in the messenger contract for security purposes. payload[1] = classHash; // L2 strategy params payload[2] = 11 + strategyParamsCount; payload[3] = 10 + strategyParamsCount; payload[4] = _computeAwardHash(config.awards); payload[5] = config.proposalPeriodStartTimestamp; payload[6] = config.proposalPeriodDuration; payload[7] = config.votePeriodDuration; payload[8] = config.winnerCount; payload[9] = config.proposalThreshold; uint256 offset = 10; (payload, offset) = _addStrategies(payload, offset, config.proposingStrategies, config.proposingStrategyParamsFlat); (payload, ) = _addStrategies(payload, ++offset, config.votingStrategies, config.votingStrategyParamsFlat); return payload; } /// @notice Define the configuration and register the round on L2. /// Duplicate voting strategies are handled on L2. /// @param config The round configuration function _register(RoundConfig memory config) internal { _validate(config); // Set the proposal period start timestamp to the current block timestamp if it is in the past. config.proposalPeriodStartTimestamp = _max(config.proposalPeriodStartTimestamp, uint40(block.timestamp)); // Write round metadata to storage. This will be consumed by the token URI later. proposalPeriodStartTimestamp = config.proposalPeriodStartTimestamp; proposalPeriodDuration = config.proposalPeriodDuration; votePeriodDuration = config.votePeriodDuration; winnerCount = config.winnerCount; // Forward ETH to the meta-transaction relayer, if set. uint256 etherRemaining = msg.value; if (config.metaTx.deposit > 0) { if (config.metaTx.relayer == address(0)) revert NO_META_TX_RELAYER_PROVIDED(); if (config.metaTx.deposit > etherRemaining) revert INSUFFICIENT_ETHER_SUPPLIED(); _transferETH(payable(config.metaTx.relayer), config.metaTx.deposit); etherRemaining -= config.metaTx.deposit; } // Register the round on L2 messenger.sendMessageToL2{ value: etherRemaining }(roundFactory, Selector.REGISTER_ROUND, getRegistrationPayload(config)); emit RoundRegistered( config.awards, config.metaTx, config.proposalThreshold, config.proposingStrategies, config.proposingStrategyParamsFlat, config.votingStrategies, config.votingStrategyParamsFlat, config.proposalPeriodStartTimestamp, config.proposalPeriodDuration, config.votePeriodDuration, config.winnerCount ); } // prettier-ignore /// @notice Revert if the round configuration is invalid /// @param config The round configuration function _validate(RoundConfig memory config) internal pure { if (config.proposalPeriodDuration < MIN_PROPOSAL_PERIOD_DURATION) { revert PROPOSAL_PERIOD_DURATION_TOO_SHORT(); } if (config.votePeriodDuration < MIN_VOTE_PERIOD_DURATION) { revert VOTE_PERIOD_DURATION_TOO_SHORT(); } if (config.winnerCount == 0 || config.winnerCount > MAX_WINNER_COUNT) { revert WINNER_COUNT_OUT_OF_RANGE(); } if (config.proposalThreshold != 0 && config.proposingStrategies.length == 0) { revert NO_PROPOSING_STRATEGIES_PROVIDED(); } if (config.votingStrategies.length == 0) { revert NO_VOTING_STRATEGIES_PROVIDED(); } if (config.awards.length != 0 && config.awards.length != config.winnerCount) { if (config.awards.length != 1) { revert AWARD_LENGTH_MISMATCH(); } if (config.awards[0].amount % config.winnerCount != 0) { revert AWARD_AMOUNT_NOT_MULTIPLE_OF_WINNER_COUNT(); } } } /// @notice Cancel the timed round function _cancel() internal { if (state != RoundState.Active) { revert CANCELLATION_NOT_AVAILABLE(); } state = RoundState.Cancelled; // Notify Starknet of the cancellation _notifyRoundCancelled(); } /// @notice Claim a round award asset to a custom recipient /// @param recipient The asset recipient /// @param proposalId The winning proposal ID /// @param position The position or rank of the proposal in the winners list /// @param asset The asset to claim /// @param proof The merkle proof used to verify the validity of the asset payout function _claimTo( address recipient, uint256 proposalId, uint256 position, Asset calldata asset, bytes32[] calldata proof ) internal { if (isClaimed(proposalId)) { revert ALREADY_CLAIMED(); } PackedAsset memory packed = asset.pack(); if (!MerkleProof.verify(proof, winnerMerkleRoot, _computeClaimLeaf(proposalId, position, msg.sender, packed))) { revert INVALID_MERKLE_PROOF(); } _setClaimed(proposalId); _transfer(asset, address(this), payable(recipient)); emit AssetClaimed(proposalId, msg.sender, recipient, packed); } /// @dev Computes a leaf in the winner merkle tree used to release assets to winners. /// @param proposalId The winning proposal ID /// @param position The position or rank of the proposal in the winners list /// @param user The user claiming the assets /// @param packed The packed asset that's being claimed function _computeClaimLeaf(uint256 proposalId, uint256 position, address user, PackedAsset memory packed) internal pure returns (bytes32) { return keccak256(abi.encode(proposalId, position, user, packed)); } /// @notice Compute the award hash for the round, returning `0` if /// there are no awards. /// @param awards The round awards function _computeAwardHash(Asset[] memory awards) internal pure returns (uint256) { if (awards.length == 0) { return 0; } return keccak256(abi.encode(awards.packMany())).mask250(); } /// @dev Returns the largest of two numbers. /// @param a The first number /// @param b The second number function _max(uint40 a, uint40 b) internal pure returns (uint40) { return a > b ? a : b; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { Round } from './Round.sol'; import { IERC165 } from '../../interfaces/IERC165.sol'; import { AssetHelper } from '../../lib/utils/AssetHelper.sol'; import { IAssetRound } from '../../interfaces/IAssetRound.sol'; import { AssetController } from '../../lib/utils/AssetController.sol'; import { DepositReceiver } from '../../lib/utils/DepositReceiver.sol'; import { TokenHolder } from '../../lib/utils/TokenHolder.sol'; import { IManager } from '../../interfaces/IManager.sol'; import { ERC1155 } from '../../lib/token/ERC1155.sol'; import { Asset } from '../../lib/types/Common.sol'; abstract contract AssetRound is IAssetRound, Round, AssetController, TokenHolder, ERC1155, DepositReceiver { using { AssetHelper.toID } for Asset; /// @notice The Prop House manager contract IManager public immutable manager; /// @notice Determine if a winner has claimed their award asset /// @dev Proposal IDs map to bits in the uint256 mapping mapping(uint256 => uint256) private _assetClaimStatus; /// @notice The round implementation contract address address private immutable _implementation; constructor( bytes32 _kind, uint256 _classHash, address _propHouse, address _starknet, address _messenger, uint256 _roundFactory, uint256 _executionRelayer, address _manager ) Round(_kind, _classHash, _propHouse, _starknet, _messenger, _roundFactory, _executionRelayer) { manager = IManager(_manager); _implementation = address(this); } /// @notice Require that the caller is the prop house contract modifier onlySecurityCouncil() { if (msg.sender != manager.getSecurityCouncil()) { revert ONLY_SECURITY_COUNCIL(); } _; } /// @notice Returns the deposit token URI for the provided token ID /// @param tokenId The deposit token ID function uri(uint256 tokenId) external view override returns (string memory) { return manager.getMetadataRenderer(_implementation).tokenURI(tokenId); } // prettier-ignore /// @notice If the contract implements an interface /// @param interfaceId The interface id function supportsInterface(bytes4 interfaceId) public view virtual override(DepositReceiver, TokenHolder, ERC1155, IERC165) returns (bool) { return DepositReceiver.supportsInterface(interfaceId) || TokenHolder.supportsInterface(interfaceId) || ERC1155.supportsInterface(interfaceId); } /// @notice Issue a deposit receipt /// @param depositor The depositor address /// @param id The token identifier /// @param amount The token amount /// @dev This function is only callable by the prop house contract function onDepositReceived(address depositor, uint256 id, uint256 amount) external onlyPropHouse { _mint(depositor, id, amount, new bytes(0)); } /// @notice Issue deposit receipts /// @param depositor The depositor address /// @param ids The token identifiers /// @param amounts The token amounts /// @dev This function is only callable by the prop house contract function onDepositsReceived( address depositor, uint256[] calldata ids, uint256[] calldata amounts ) external onlyPropHouse { _batchMint(depositor, ids, amounts, new bytes(0)); } /// @notice Determine whether an asset has been claimed for a specific proposal ID /// @param proposalId The proposal ID function isClaimed(uint256 proposalId) public view returns (bool claimed) { uint256 isBitSet = (_assetClaimStatus[proposalId >> 8] >> (proposalId & 0xff)) & 1; assembly { claimed := isBitSet } } /// @notice Reclaim assets to a custom recipient /// @param recipient The asset recipient /// @param assets The assets to reclaim function _reclaimTo(address recipient, Asset[] calldata assets) internal { uint256 assetCount = assets.length; address caller = msg.sender; for (uint256 i = 0; i < assetCount; ) { uint256 assetId = assets[i].toID(); // Burn deposit credits. This will revert if the caller does not have enough credits. _burn(caller, assetId, assets[i].amount); // Transfer the asset to the recipient _transfer(assets[i], address(this), payable(recipient)); unchecked { ++i; } } } /// @notice Mark an asset as 'claimed' for the provided proposal ID /// @param proposalId The winning proposal ID function _setClaimed(uint256 proposalId) internal { _assetClaimStatus[proposalId >> 8] |= (1 << (proposalId & 0xff)); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; /// @notice Supported asset types enum AssetType { Native, ERC20, ERC721, ERC1155 } /// @notice Common struct for all supported asset types struct Asset { AssetType assetType; address token; uint256 identifier; uint256 amount; } /// @notice Packed asset information, which consists of an asset ID and amount struct PackedAsset { uint256 assetId; uint256 amount; } /// @notice Merkle proof information for an incremental tree struct IncrementalTreeProof { bytes32[] siblings; uint8[] pathIndices; } /// @notice A meta-transaction relayer address and deposit amount struct MetaTransaction { address relayer; uint256 deposit; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { Asset, MetaTransaction } from '../lib/types/Common.sol'; /// @notice Interface implemented by the timed round interface ITimedRound { /// @notice All possible round states enum RoundState { Active, Cancelled, Finalized } /// @notice The timed round configuration struct RoundConfig { Asset[] awards; MetaTransaction metaTx; uint248 proposalThreshold; uint256[] proposingStrategies; uint256[] proposingStrategyParamsFlat; uint256[] votingStrategies; uint256[] votingStrategyParamsFlat; uint40 proposalPeriodStartTimestamp; uint40 proposalPeriodDuration; uint40 votePeriodDuration; uint16 winnerCount; } /// @notice Thrown when cancellation is attempted and the round is not active error CANCELLATION_NOT_AVAILABLE(); /// @notice Thrown when finalization is attempted and the round is not active error FINALIZATION_NOT_AVAILABLE(); /// @notice Thrown when asset reclamation is not available error RECLAMATION_NOT_AVAILABLE(); /// @notice Thrown when emergency withdrawal is not available error EMERGENCY_WITHDRAWAL_NOT_AVAILABLE(); /// @notice Thrown when the proposal period duration is too short error PROPOSAL_PERIOD_DURATION_TOO_SHORT(); /// @notice Thrown when the vote period duration is too short error VOTE_PERIOD_DURATION_TOO_SHORT(); /// @notice Thrown when the award length is greater than one and does not match the winner count error AWARD_LENGTH_MISMATCH(); /// @notice Thrown when one award is split between winners and the amount is not a multiple of the winner count error AWARD_AMOUNT_NOT_MULTIPLE_OF_WINNER_COUNT(); /// @notice Thrown when the winner count is zero or greater than the maximum allowable error WINNER_COUNT_OUT_OF_RANGE(); /// @notice Thrown when the proposal threshold is non-zero and no proposing strategies are provided error NO_PROPOSING_STRATEGIES_PROVIDED(); /// @notice Thrown when no voting strategies are provided error NO_VOTING_STRATEGIES_PROVIDED(); /// @notice Thrown when the meta-transaction deposit amount is non-zero, but no relayer address is provided. error NO_META_TX_RELAYER_PROVIDED(); /// @notice Thrown when an insufficient amount of ether is provided to `msg.value` error INSUFFICIENT_ETHER_SUPPLIED(); /// @notice Emitted when the round is registered on L2 /// @param awards The awards offered to round winners /// @param metaTx The meta-transaction relayer and deposit amount /// @param proposalThreshold The proposal threshold /// @param proposingStrategies The proposing strategy addresses /// @param proposingStrategyParamsFlat The flattened proposing strategy params /// @param votingStrategies The voting strategy addresses /// @param votingStrategyParamsFlat The flattened voting strategy params /// @param proposalPeriodStartTimestamp The timestamp at which the proposal period starts /// @param proposalPeriodDuration The proposal period duration in seconds /// @param votePeriodDuration The vote period duration in seconds /// @param winnerCount The number of possible winners event RoundRegistered( Asset[] awards, MetaTransaction metaTx, uint248 proposalThreshold, uint256[] proposingStrategies, uint256[] proposingStrategyParamsFlat, uint256[] votingStrategies, uint256[] votingStrategyParamsFlat, uint40 proposalPeriodStartTimestamp, uint40 proposalPeriodDuration, uint40 votePeriodDuration, uint16 winnerCount ); /// @notice Emitted when the round is finalized event RoundFinalized(); /// @notice Emitted when a round is cancelled by the round manager event RoundCancelled(); /// @notice Emitted when a round is cancelled by the security council in an emergency event RoundEmergencyCancelled(); /// @notice The current state of the timed round function state() external view returns (RoundState); /// @notice The timestamp at which the round was finalized. `0` if not finalized. function finalizedAt() external view returns (uint40); /// @notice The timestamp at which the proposal period starts. `0` when in pending state. function proposalPeriodStartTimestamp() external view returns (uint40); /// @notice The proposal period duration in seconds. `0` when in pending state. function proposalPeriodDuration() external view returns (uint40); /// @notice The vote period duration in seconds. `0` when in pending state. function votePeriodDuration() external view returns (uint40); /// @notice The number of possible winners. `0` when in pending state. function winnerCount() external view returns (uint16); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { Asset, AssetType, PackedAsset } from '../types/Common.sol'; library AssetHelper { /// @notice Returns the packed asset information for a single asset /// @param asset The asset information function pack(Asset memory asset) internal pure returns (PackedAsset memory packed) { unchecked { packed = PackedAsset({ assetId: toID(asset), amount: asset.amount }); } } /// @notice Returns the packed asset information for the provided assets /// @param assets The asset information function packMany(Asset[] memory assets) internal pure returns (PackedAsset[] memory packed) { unchecked { uint256 assetCount = assets.length; packed = new PackedAsset[](assetCount); for (uint256 i = 0; i < assetCount; ++i) { packed[i] = pack(assets[i]); } } } /// @notice Calculates the asset IDs for the provided assets /// @param assets The asset information function toIDs(Asset[] memory assets) internal pure returns (uint256[] memory ids) { unchecked { uint256 assetCount = assets.length; ids = new uint256[](assetCount); for (uint256 i = 0; i < assetCount; ++i) { ids[i] = toID(assets[i]); } } } /// @dev Calculates the asset ID for the provided asset /// @param asset The asset information function toID(Asset memory asset) internal pure returns (uint256) { if (asset.assetType == AssetType.Native) { return uint256(asset.assetType); } if (asset.assetType == AssetType.ERC20) { return uint256(bytes32(abi.encodePacked(asset.assetType, asset.token))); } // prettier-ignore return uint256( bytes32(abi.encodePacked(asset.assetType, keccak256(abi.encodePacked(asset.token, asset.identifier)))) ); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; /// @notice Gas optimized merkle proof verification library library MerkleProof { function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool isValid) { /// @solidity memory-safe-assembly assembly { if mload(proof) { // Initialize `offset` to the offset of `proof` elements in memory. let offset := add(proof, 0x20) // Left shift by 5 is equivalent to multiplying by 0x20. let end := add(offset, shl(5, mload(proof))) // Iterate over proof elements to compute root hash. for {} 1 {} { // Slot of `leaf` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(leaf, mload(offset))) // Store elements to hash contiguously in scratch space. // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. mstore(scratch, leaf) mstore(xor(scratch, 0x20), mload(offset)) // Reuse `leaf` to store the hash to reduce stack operations. leaf := keccak256(0x00, 0x40) offset := add(offset, 0x20) if iszero(lt(offset, end)) { break } } } isValid := eq(leaf, root) } } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; // ETH pseudo-token address address constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; // The maximum value that can be represented as an unsigned 250-bit integer uint256 constant MAX_250_BIT_UNSIGNED = 0x03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; /// @notice Starknet function selector constants library Selector { // print(get_selector_from_name("register_round")) uint256 constant REGISTER_ROUND = 0x26490f901ea8ad5a245d987479919f1d20fbb0c164367e33ef09a9ea4ba8d04; // print(get_selector_from_name("cancel_round")) uint256 constant CANCEL_ROUND = 0x8af3ea41808c9515720e56add54a2d8008458a8bc5e347b791c6d75cd0e407; // print(get_selector_from_name("finalize_round")) uint256 constant FINALIZE_ROUND = 0x2445872c1b7a1219e1e75f2a60719ce0a68a8442fee1bdbee6c3c649340e6f3; // print(get_selector_from_name("route_call_to_round")) uint256 constant ROUTE_CALL_TO_ROUND = 0x24931ca109ce0ffa87913d91f12d6ac327550c015a573c7b17a187c29ed8c1a; } /// @notice Prop House metadata constants library PHMetadata { // The Prop House NFT name string constant NAME = 'Prop House'; // The Prop House entrypoint NFT symbol string constant SYMBOL = 'PROP'; // The Prop House entrypoint NFT contract URI string constant URI = 'ipfs://bafkreiagexn2wbv5t63y2xbf6mmcx3rktrqxrsyzf5gl5l7c2lm3bkqjc4'; } /// @notice Community house metadata constants library CHMetadata { // The Community House type bytes32 constant TYPE = 'COMMUNITY'; // The Community House NFT name string constant NAME = 'Community House'; // The Community House NFT symbol string constant SYMBOL = 'COMM'; } /// @notice Round type constants library RoundType { // The Timed Round type bytes32 constant TIMED = 'TIMED'; // The Infinite Round type bytes32 constant INFINITE = 'INFINITE'; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { MAX_250_BIT_UNSIGNED } from '../../Constants.sol'; library Uint256 { /// @notice Split a uint256 into a high and low value /// @param value The uint256 value to split /// @dev This is useful for passing uint256 values to Starknet, whose felt /// type only supports 251 bits. function split(uint256 value) internal pure returns (uint256, uint256) { uint256 low = value & ((1 << 128) - 1); uint256 high = value >> 128; return (low, high); } /// Mask the passed `value` to 250 bits /// @param value The value to mask function mask250(bytes32 value) internal pure returns (uint256) { return uint256(value) & MAX_250_BIT_UNSIGNED; } /// @notice Convert an address to a uint256 /// @param addr The address to convert function toUint256(address addr) internal pure returns (uint256) { return uint256(uint160(addr)); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { Clone } from 'solady/src/utils/Clone.sol'; import { IHouse } from '../../interfaces/IHouse.sol'; import { IRound } from '../../interfaces/IRound.sol'; import { IPropHouse } from '../../interfaces/IPropHouse.sol'; import { IStarknetCore } from '../../interfaces/IStarknetCore.sol'; import { IMessenger } from '../../interfaces/IMessenger.sol'; import { Uint256 } from '../../lib/utils/Uint256.sol'; import { Selector } from '../../Constants.sol'; abstract contract Round is IRound, Clone { using { Uint256.toUint256 } for address; /// @notice The round type bytes32 public immutable kind; /// @notice The hash of the Starknet round contract uint256 public immutable classHash; /// @notice The entrypoint for all house and round creation IPropHouse public immutable propHouse; /// @notice The Starknet Core contract IStarknetCore public immutable starknet; /// @notice The Starknet Messenger contract IMessenger public immutable messenger; /// @notice The Round Factory contract address on Starknet uint256 internal immutable roundFactory; /// @notice The execution relayer contract on Starknet uint256 public immutable executionRelayer; /// @notice The merkle root that contains winner information. `bytes32(0)` if not finalized. bytes32 public winnerMerkleRoot; /// @notice Get the address of the house on which this strategy belongs /// @dev Value is read using clone-with-immutable-args from contract's code region. function house() public pure returns (address) { return _getArgAddress(0); } /// @notice Get the round title /// @dev Value is read using clone-with-immutable-args from contract's code region. function title() public pure returns (string memory) { return string(_getArgBytes(21, _getArgUint8(20))); } /// @notice Get the round ID function id() public view returns (uint256) { return address(this).toUint256(); } /// @param _kind The round type /// @param _classHash The hash of the Starknet round contract /// @param _propHouse The entrypoint for all house and round creation /// @param _starknet The Starknet Core contract /// @param _messenger The Starknet Messenger contract /// @param _roundFactory The Round Factory contract address on Starknet /// @param _executionRelayer The execution relayer contract on Starknet constructor( bytes32 _kind, uint256 _classHash, address _propHouse, address _starknet, address _messenger, uint256 _roundFactory, uint256 _executionRelayer ) { kind = _kind; classHash = _classHash; propHouse = IPropHouse(_propHouse); starknet = IStarknetCore(_starknet); messenger = IMessenger(_messenger); roundFactory = _roundFactory; executionRelayer = _executionRelayer; } /// @notice Require that the caller is the prop house contract modifier onlyPropHouse() { if (msg.sender != address(propHouse)) { revert ONLY_PROP_HOUSE(); } _; } /// @notice Require that the caller is the round manager modifier onlyRoundManager() { if (msg.sender != IHouse(house()).ownerOf(id())) { revert ONLY_ROUND_MANAGER(); } _; } /// @dev Route a call to the round contract on Starknet /// @param payload The payload to send to the round contract on Starknet function _callStarknetRound(uint256[] memory payload) internal { messenger.sendMessageToL2{ value: msg.value }(roundFactory, Selector.ROUTE_CALL_TO_ROUND, payload); } /// @dev Route a round cancellation call to the round contract on Starknet /// `payload[0]` - Round address /// `payload[2]` - Empty calldata array length function _notifyRoundCancelled() internal { uint256[] memory payload = new uint256[](3); payload[1] = Selector.CANCEL_ROUND; _callStarknetRound(payload); } /// @dev Add strategies and parameters to the payload /// @param payload The payload to add to /// @param offset The starting offset index /// @param strategies The strategy addresses to add /// @param params The flattened parameters to add function _addStrategies( uint256[] memory payload, uint256 offset, uint256[] memory strategies, uint256[] memory params ) internal pure returns (uint256[] memory, uint256) { unchecked { uint256 strategyCount = strategies.length; uint256 paramCount = params.length; // Add strategy count payload[offset] = strategyCount; // Add strategies for (uint256 i = 0; i < strategyCount; ++i) { uint256 strategy = strategies[i]; if (strategy == 0) { revert INVALID_STRATEGY(strategy); } payload[++offset] = strategy; } // Add parameter count payload[++offset] = paramCount; // Add parameters for (uint256 i = 0; i < paramCount; ++i) { payload[++offset] = params[i]; } return (payload, offset); } } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; /// @title IERC165 /// @notice Interface of the ERC165 standard, as defined in the https://eips.ethereum.org/EIPS/eip-165[EIP]. 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 30000 gas. function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { IRound } from './IRound.sol'; import { PackedAsset } from '../lib/types/Common.sol'; interface IAssetRound is IRound { /// @notice Thrown when an asset has already been claimed error ALREADY_CLAIMED(); /// @notice Thrown when the provided merkle proof is invalid error INVALID_MERKLE_PROOF(); /// @notice Thrown when the caller of a guarded function is not the security council error ONLY_SECURITY_COUNCIL(); /// @notice Emitted when an asset is claimed by a winner /// @param proposalId The ID of the winning proposal /// @param claimer The address of the claimer (winner) /// @param recipient The recipient of the asset /// @param asset The ID and amount of the asset being claimed event AssetClaimed(uint256 proposalId, address claimer, address recipient, PackedAsset asset); /// @notice Emitted when an asset is claimed by a winner /// @param proposalId The ID of the winning proposal /// @param claimer The address of the claimer (winner) /// @param recipient The recipient of the asset /// @param assets The ID and amount of the assets being claimed event AssetsClaimed(uint256 proposalId, address claimer, address recipient, PackedAsset[] assets); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import { IERC721 } from '@openzeppelin/contracts/token/ERC721/IERC721.sol'; import { IERC1155 } from '@openzeppelin/contracts/token/ERC1155/IERC1155.sol'; import { SafeERC20 } from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; import { AssetType, Asset } from '../types/Common.sol'; abstract contract AssetController { using SafeERC20 for IERC20; /// @notice Thrown when unused asset parameters are populated error UNUSED_ASSET_PARAMETERS(); /// @notice Thrown when an ether transfer does not succeed error ETHER_TRANSFER_FAILED(); /// @notice Thrown when the ERC721 transfer amount is not equal to one error INVALID_ERC721_TRANSFER_AMOUNT(); /// @notice Thrown when an unknown asset type is provided error INVALID_ASSET_TYPE(); /// @notice Thrown when no asset amount is provided error MISSING_ASSET_AMOUNT(); /// @dev Returns the balance of `asset` for `account` /// @param asset The asset to fetch the balance of /// @param account The account to fetch the balance for function _balanceOf(Asset memory asset, address account) internal view returns (uint256) { if (asset.assetType == AssetType.Native) { return account.balance; } if (asset.assetType == AssetType.ERC20) { return IERC20(asset.token).balanceOf(account); } if (asset.assetType == AssetType.ERC721) { return IERC721(asset.token).ownerOf(asset.identifier) == account ? 1 : 0; } if (asset.assetType == AssetType.ERC1155) { return IERC1155(asset.token).balanceOf(account, asset.identifier); } revert INVALID_ASSET_TYPE(); } /// @dev Transfer a given asset from the provided `from` address to the `to` address /// @param asset The asset to transfer, including the asset amount /// @param source The account supplying the asset /// @param recipient The asset recipient function _transfer(Asset memory asset, address source, address payable recipient) internal { if (asset.assetType == AssetType.Native) { // Ensure neither the token nor the identifier parameters are set if ((uint160(asset.token) | asset.identifier) != 0) { revert UNUSED_ASSET_PARAMETERS(); } _transferETH(recipient, asset.amount); } else if (asset.assetType == AssetType.ERC20) { // Ensure that no identifier is supplied if (asset.identifier != 0) { revert UNUSED_ASSET_PARAMETERS(); } _transferERC20(asset.token, source, recipient, asset.amount); } else if (asset.assetType == AssetType.ERC721) { _transferERC721(asset.token, asset.identifier, source, recipient, asset.amount); } else if (asset.assetType == AssetType.ERC1155) { _transferERC1155(asset.token, asset.identifier, source, recipient, asset.amount); } else { revert INVALID_ASSET_TYPE(); } } /// @notice Transfers one or more assets from the provided `from` address to the `to` address /// @param assets The assets to transfer, including the asset amounts /// @param source The account supplying the assets /// @param recipient The asset recipient function _transferMany(Asset[] memory assets, address source, address payable recipient) internal { uint256 assetCount = assets.length; for (uint256 i = 0; i < assetCount; ) { _transfer(assets[i], source, recipient); unchecked { ++i; } } } /// @notice Transfers ETH to a recipient address /// @param recipient The transfer recipient /// @param amount The amount of ETH to transfer function _transferETH(address payable recipient, uint256 amount) internal { _assertNonZeroAmount(amount); bool success; assembly { success := call(10000, recipient, amount, 0, 0, 0, 0) } if (!success) { revert ETHER_TRANSFER_FAILED(); } } /// @notice Transfers ERC20 tokens from a provided account to a recipient address /// @param token The token to transfer /// @param source The transfer source /// @param recipient The transfer recipient /// @param amount The amount to transfer function _transferERC20(address token, address source, address recipient, uint256 amount) internal { _assertNonZeroAmount(amount); // Use `transfer` if the source is this contract if (source == address(this)) { IERC20(token).safeTransfer(recipient, amount); } else { IERC20(token).safeTransferFrom(source, recipient, amount); } } /// @notice Transfers an ERC721 token to a recipient address /// @param token The token to transfer /// @param identifier The ID of the token to transfer /// @param source The transfer source /// @param recipient The transfer recipient /// @param amount The token amount (Must be 1) function _transferERC721( address token, uint256 identifier, address source, address recipient, uint256 amount ) internal { if (amount != 1) { revert INVALID_ERC721_TRANSFER_AMOUNT(); } IERC721(token).transferFrom(source, recipient, identifier); } /// @notice Transfers ERC1155 tokens to a recipient address /// @param token The token to transfer /// @param identifier The ID of the token to transfer /// @param source The transfer source /// @param recipient The transfer recipient /// @param amount The amount to transfer function _transferERC1155( address token, uint256 identifier, address source, address recipient, uint256 amount ) internal { _assertNonZeroAmount(amount); IERC1155(token).safeTransferFrom(source, recipient, identifier, amount, new bytes(0)); } /// @dev Ensure that a given asset amount is not zero /// @param amount The amount to check function _assertNonZeroAmount(uint256 amount) internal pure { // Revert if the supplied amount is equal to zero if (amount == 0) { revert MISSING_ASSET_AMOUNT(); } } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { IDepositReceiver } from '../../interfaces/IDepositReceiver.sol'; abstract contract DepositReceiver is IDepositReceiver { function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IDepositReceiver).interfaceId; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { ERC165 } from './ERC165.sol'; import { IERC165 } from '../../interfaces/IERC165.sol'; import { ERC721TokenReceiver, ERC1155TokenReceiver } from './TokenReceiver.sol'; /// @notice A contract which properly accepts and holds ERC721 & ERC1155 tokens. abstract contract TokenHolder is ERC721TokenReceiver, ERC1155TokenReceiver, ERC165 { /// @notice If the contract implements an interface /// @param interfaceId The interface id function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(ERC721TokenReceiver).interfaceId || interfaceId == type(ERC1155TokenReceiver).interfaceId || super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { ITokenMetadataRenderer } from './ITokenMetadataRenderer.sol'; /// @notice Interface for the Manager contract interface IManager { /// @notice Emitted when a house implementation is registered /// @param houseImpl The house implementation address /// @param houseType The house implementation type event HouseRegistered(address houseImpl, bytes32 houseType); /// @notice Emitted when a house implementation is unregistered /// @param houseImpl The house implementation address event HouseUnregistered(address houseImpl); /// @notice Emitted when a round implementation is registered on a house /// @param houseImpl The house implementation address /// @param roundImpl The round implementation address /// @param roundType The round implementation type event RoundRegistered(address houseImpl, address roundImpl, bytes32 roundType); /// @notice Emitted when a round implementation is unregistered on a house /// @param houseImpl The house implementation address /// @param roundImpl The round implementation address event RoundUnregistered(address houseImpl, address roundImpl); /// @notice Emitted when a metadata renderer is set for a contract /// @param addr The contract address /// @param renderer The renderer address event MetadataRendererSet(address addr, address renderer); /// @notice Emitted when the security council address is set /// @param securityCouncil The security council address event SecurityCouncilSet(address securityCouncil); /// @notice Determine if a house implementation is registered /// @param houseImpl The house implementation address function isHouseRegistered(address houseImpl) external view returns (bool); /// @notice Determine if a round implementation is registered on the provided house /// @param houseImpl The house implementation address /// @param roundImpl The round implementation address function isRoundRegistered(address houseImpl, address roundImpl) external view returns (bool); /// @notice Get the metadata renderer for a contract /// @param contract_ The contract address function getMetadataRenderer(address contract_) external view returns (ITokenMetadataRenderer); /// @notice Get the security council address function getSecurityCouncil() external view returns (address); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.17; import { ERC1155TokenReceiver } from '../utils/TokenReceiver.sol'; import { IERC1155 } from '../../interfaces/IERC1155.sol'; /// @notice Minimalist and gas efficient standard ERC1155 implementation. /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) /// - Uses custom errors /// - Does not revert on `_mint` & `_batchMint` if the receiver is a contract and does NOT implement the ERC1155TokenReceiver rules abstract contract ERC1155 is IERC1155 { mapping(address => mapping(uint256 => uint256)) public balanceOf; mapping(address => mapping(address => bool)) public isApprovedForAll; function uri(uint256 id) external view virtual returns (string memory); 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 { if (msg.sender != from && !isApprovedForAll[from][msg.sender]) { revert NOT_AUTHORIZED(); } uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(msg.sender, from, to, ids, amounts, data); balanceOf[from][id] -= amount; balanceOf[to][id] += amount; emit TransferSingle(msg.sender, from, to, id, amount); // prettier-ignore if (to.code.length == 0 ? to == address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) != ERC1155TokenReceiver.onERC1155Received.selector) { revert UNSAFE_RECIPIENT(); } } function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) public virtual { if (ids.length != amounts.length) { revert LENGTH_MISMATCH(); } if (msg.sender != from && !isApprovedForAll[from][msg.sender]) { revert NOT_AUTHORIZED(); } _beforeTokenTransfer(msg.sender, from, to, ids, amounts, data); // Storing these outside the loop saves ~15 gas per iteration. uint256 id; uint256 amount; for (uint256 i = 0; 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); // prettier-ignore if (to.code.length == 0 ? to == address(0) : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) != ERC1155TokenReceiver.onERC1155BatchReceived.selector) { revert UNSAFE_RECIPIENT(); } } function balanceOfBatch( address[] calldata owners, uint256[] calldata ids ) public view virtual returns (uint256[] memory balances) { if (owners.length != ids.length) { revert 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 = 0; i < owners.length; ++i) { balances[i] = balanceOf[owners[i]][ids[i]]; } } } 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 } function _mint(address to, uint256 id, uint256 amount, bytes memory data) internal virtual { uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(msg.sender, address(0), to, ids, amounts, data); balanceOf[to][id] += amount; emit TransferSingle(msg.sender, address(0), to, id, amount); if (to.code.length == 0) { if (to == address(0)) { revert UNSAFE_RECIPIENT(); } } else { // prettier-ignore try ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) returns (bytes4 response) { // `to` supports `ERC1155TokenReceiver`. Revert if an unexpected response is received. if (response != ERC1155TokenReceiver.onERC1155Received.selector) { revert UNSAFE_RECIPIENT(); } } catch { // We MUST check if `to` supports `ERC1155TokenReceiver`. If not, we take a less restrictive approach than // most implementations and do NOT revert. According to the spec, this is valid behavior. try ERC1155TokenReceiver(to).supportsInterface(0x4e2312e0 /* `ERC1155TokenReceiver` support */) returns (bool supported) { if (supported) { revert UNSAFE_RECIPIENT(); } } catch {} } } } function _batchMint( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. if (idsLength != amounts.length) { revert LENGTH_MISMATCH(); } _beforeTokenTransfer(msg.sender, address(0), to, ids, amounts, data); for (uint256 i = 0; 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); if (to.code.length == 0) { if (to == address(0)) { revert UNSAFE_RECIPIENT(); } } else { // prettier-ignore try ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) returns (bytes4 response) { // `to` supports `ERC1155TokenReceiver`. Revert if an unexpected response is received. if (response != ERC1155TokenReceiver.onERC1155BatchReceived.selector) { revert UNSAFE_RECIPIENT(); } } catch { // We MUST check if `to` supports `ERC1155TokenReceiver`. If not, we take a less restrictive approach than // most implementations and do NOT revert. According to the spec, this is valid behavior. try ERC1155TokenReceiver(to).supportsInterface(0x4e2312e0 /* `ERC1155TokenReceiver` support */) returns (bool supported) { if (supported) { revert UNSAFE_RECIPIENT(); } } catch {} } } } function _batchBurn(address from, uint256[] memory ids, uint256[] memory amounts) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. if (idsLength != amounts.length) { revert LENGTH_MISMATCH(); } _beforeTokenTransfer(msg.sender, from, address(0), ids, amounts, ''); for (uint256 i = 0; 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 { uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(msg.sender, from, address(0), ids, amounts, ''); balanceOf[from][id] -= amount; emit TransferSingle(msg.sender, from, address(0), id, amount); } function _asSingletonArray(uint256 element) private pure returns (uint256[] memory array) { array = new uint256[](1); array[0] = element; } function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Class with helper read functions for clone with immutable args. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Clone.sol) /// @author Adapted from clones with immutable args by zefram.eth, Saw-mon & Natalie /// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args) abstract contract Clone { /// @dev Reads an immutable arg with type bytes. function _getArgBytes(uint256 argOffset, uint256 length) internal pure returns (bytes memory arg) { uint256 offset = _getImmutableArgsOffset(); /// @solidity memory-safe-assembly assembly { // Grab the free memory pointer. arg := mload(0x40) // Store the array length. mstore(arg, length) // Copy the array. calldatacopy(add(arg, 0x20), add(offset, argOffset), length) // Allocate the memory, rounded up to the next 32 byte boudnary. mstore(0x40, and(add(add(arg, 0x3f), length), not(0x1f))) } } /// @dev Reads an immutable arg with type address. function _getArgAddress(uint256 argOffset) internal pure returns (address arg) { uint256 offset = _getImmutableArgsOffset(); /// @solidity memory-safe-assembly assembly { arg := shr(0x60, calldataload(add(offset, argOffset))) } } /// @dev Reads an immutable arg with type uint256 function _getArgUint256(uint256 argOffset) internal pure returns (uint256 arg) { uint256 offset = _getImmutableArgsOffset(); /// @solidity memory-safe-assembly assembly { arg := calldataload(add(offset, argOffset)) } } /// @dev Reads a uint256 array stored in the immutable args. function _getArgUint256Array(uint256 argOffset, uint256 length) internal pure returns (uint256[] memory arg) { uint256 offset = _getImmutableArgsOffset(); /// @solidity memory-safe-assembly assembly { // Grab the free memory pointer. arg := mload(0x40) // Store the array length. mstore(arg, length) // Copy the array. calldatacopy(add(arg, 0x20), add(offset, argOffset), shl(5, length)) // Allocate the memory. mstore(0x40, add(add(arg, 0x20), shl(5, length))) } } /// @dev Reads an immutable arg with type uint64. function _getArgUint64(uint256 argOffset) internal pure returns (uint64 arg) { uint256 offset = _getImmutableArgsOffset(); /// @solidity memory-safe-assembly assembly { arg := shr(0xc0, calldataload(add(offset, argOffset))) } } /// @dev Reads an immutable arg with type uint8. function _getArgUint8(uint256 argOffset) internal pure returns (uint8 arg) { uint256 offset = _getImmutableArgsOffset(); /// @solidity memory-safe-assembly assembly { arg := shr(0xf8, calldataload(add(offset, argOffset))) } } /// @return offset The offset of the packed immutable args in calldata. function _getImmutableArgsOffset() internal pure returns (uint256 offset) { /// @solidity memory-safe-assembly assembly { offset := sub(calldatasize(), shr(0xf0, calldataload(sub(calldatasize(), 2)))) } } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { IERC721 } from './IERC721.sol'; /// @notice Common House interface interface IHouse is IERC721 { /// @notice Thrown when the caller is not the prop house contract error ONLY_PROP_HOUSE(); /// @notice Thrown when the caller does not hold the house ownership token error ONLY_HOUSE_OWNER(); /// @notice Thrown when the provided value does not fit into 8 bits error VALUE_DOES_NOT_FIT_IN_8_BITS(); /// @notice The house type function kind() external view returns (bytes32); /// @notice Initialize the house /// @param data Initialization data function initialize(bytes calldata data) external; /// @notice Returns `true` if the provided address is a valid round on the house /// @param round The round to validate function isRound(address round) external view returns (bool); /// @notice Create a new round /// @param impl The round implementation contract /// @param title The round title /// @param creator The round creator address function createRound(address impl, string calldata title, address creator) external returns (address); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { IERC165 } from './IERC165.sol'; /// @notice Interface that must be implemented by all round types interface IRound is IERC165 { /// @notice Thrown when the caller of a guarded function is not the prop house contract error ONLY_PROP_HOUSE(); /// @notice Thrown when the caller of a guarded function is not the round manager error ONLY_ROUND_MANAGER(); /// @notice Thrown when the address of a provided strategy is zero /// @param strategy The address of the strategy error INVALID_STRATEGY(uint256 strategy); /// @notice The round type function kind() external view returns (bytes32); /// @notice Get the round title function title() external pure returns (string memory); /// @notice Initialize the round /// @param data The optional round data. If empty, round registration is deferred. function initialize(bytes calldata data) external payable; /// @notice The house that the round belongs to function house() external view returns (address); /// @notice The round ID function id() external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { Asset } from '../lib/types/Common.sol'; import { IERC721 } from './IERC721.sol'; /// @notice Interface implemented by the Prop House entry contract interface IPropHouse is IERC721 { /// @notice House creation data, including the implementation contract and config struct House { address impl; bytes config; } /// @notice Round creation data, including the implementation contract, config, and other metadata struct Round { address impl; bytes config; string title; string description; } /// @notice Thrown when an insufficient amount of ether is provided to `msg.value` error INSUFFICIENT_ETHER_SUPPLIED(); /// @notice Thrown when a provided house is invalid error INVALID_HOUSE(); /// @notice Thrown when a provided round is invalid error INVALID_ROUND(); /// @notice Thrown when a provided house implementation is invalid error INVALID_HOUSE_IMPL(); /// @notice Thrown when a round implementation contract is invalid for a house error INVALID_ROUND_IMPL_FOR_HOUSE(); /// @notice Thrown when a house attempts to pull tokens from a user who has not approved it error HOUSE_NOT_APPROVED_BY_USER(); /// @notice Emitted when a house is created /// @param creator The house creator /// @param house The house contract address /// @param kind The house contract type event HouseCreated(address indexed creator, address indexed house, bytes32 kind); /// @notice Emitted when a round is created /// @param creator The round creator /// @param house The house that the round was created on /// @param round The round contract address /// @param kind The round contract type /// @param title The round title /// @param description The round description event RoundCreated( address indexed creator, address indexed house, address indexed round, bytes32 kind, string title, string description ); /// @notice Emitted when an asset is deposited to a round /// @param from The user who deposited the asset /// @param round The round that received the asset /// @param asset The asset information event DepositToRound(address from, address round, Asset asset); /// @notice Emitted when one or more assets are deposited to a round /// @param from The user who deposited the asset(s) /// @param round The round that received the asset(s) /// @param assets The asset information event BatchDepositToRound(address from, address round, Asset[] assets); /// @notice Returns `true` if the passed `house` address is valid /// @param house The house address function isHouse(address house) external view returns (bool); /// @notice Returns `true` if the passed `round` address is valid on any house /// @param round The round address function isRound(address round) external view returns (bool); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; interface IStarknetCore { /// @notice Send a message to an L2 contract and return the hash of the message /// @param toAddress The callee address /// @param selector The function selector /// @param payload The message payload function sendMessageToL2( uint256 toAddress, uint256 selector, uint256[] calldata payload ) external payable returns (bytes32); /// @notice Starts the cancellation of an L1 to L2 message /// @param toAddress The callee address /// @param selector The function selector /// @param payload The message payload /// @param nonce The message nonce function startL1ToL2MessageCancellation( uint256 toAddress, uint256 selector, uint256[] calldata payload, uint256 nonce ) external; /// @notice Cancels an L1 to L2 message, this function should be called messageCancellationDelay() seconds /// after the call to startL1ToL2MessageCancellation() /// @param selector The function selector /// @param payload The message payload /// @param nonce The message nonce function cancelL1ToL2Message( uint256 toAddress, uint256 selector, uint256[] calldata payload, uint256 nonce ) external; /// @notice Consume a message that was sent from an L2 contract and return the hash of the message /// @param fromAddress The caller address /// @param payload The message payload function consumeMessageFromL2(uint256 fromAddress, uint256[] calldata payload) external returns (bytes32); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { IStarknetCore } from './IStarknetCore.sol'; interface IMessenger { /// @notice Thrown when the caller of a guarded function is not a valid round error ONLY_ROUND(); /// @notice Returns the Starknet core contract instance function starknet() external view returns (IStarknetCore); /// @notice Send a message to an L2 contract and return the hash of the message /// @param toAddress The callee address /// @param selector The function selector /// @param payload The message payload function sendMessageToL2( uint256 toAddress, uint256 selector, uint256[] calldata payload ) external payable returns (bytes32); /// @notice Starts the cancellation of an L1 to L2 message /// @param toAddress The callee address /// @param selector The function selector /// @param payload The message payload /// @param nonce The message cancellation nonce function startL1ToL2MessageCancellation( uint256 toAddress, uint256 selector, uint256[] calldata payload, uint256 nonce ) external; /// @notice Cancels an L1 to L2 message, this function should be called messageCancellationDelay() seconds /// after the call to startL1ToL2MessageCancellation() /// @param selector The function selector /// @param payload The message payload /// @param nonce The message cancellation nonce function cancelL1ToL2Message( uint256 toAddress, uint256 selector, uint256[] calldata payload, uint256 nonce ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch( address[] calldata accounts, uint256[] calldata ids ) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { IRound } from './IRound.sol'; /// @notice Interface that can be implemented by rounds that receive deposits interface IDepositReceiver is IRound { /// @notice A callback that is called when a deposit is received function onDepositReceived(address depositor, uint256 id, uint256 amount) external; /// @notice A callback that is called when a batch of deposits is received function onDepositsReceived(address depositor, uint256[] calldata ids, uint256[] calldata amounts) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { IERC165 } from '../../interfaces/IERC165.sol'; abstract contract ERC165 is IERC165 { /// @dev See {IERC165-supportsInterface}. function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import { IERC165 } from '../../interfaces/IERC165.sol'; /// @notice A generic interface for a contract which properly accepts ERC721 tokens. abstract contract ERC721TokenReceiver { function onERC721Received(address, address, uint256, bytes calldata) external virtual returns (bytes4) { return this.onERC721Received.selector; } } /// @notice A generic interface for a contract which properly accepts ERC1155 tokens. abstract contract ERC1155TokenReceiver is IERC165 { function onERC1155Received( address, address, uint256, uint256, bytes calldata ) external view virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] calldata, uint256[] calldata, bytes calldata ) external view virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; interface ITokenMetadataRenderer { /// @notice Returns metadata for `tokenId` as a Base64-JSON blob /// @param tokenId The token ID function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; /// @title IERC1155 /// @notice The external ERC1155 events, errors, and functions interface IERC1155 { /// @notice Thrown when the caller is not authorized error NOT_AUTHORIZED(); /// @notice Thrown when the receiver is the zero address or fails to accept the transfer error UNSAFE_RECIPIENT(); /// @notice Thrown when provided array lengths are not equal error LENGTH_MISMATCH(); /// @notice Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator` event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /// @notice Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /// @notice Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to /// `approved` event ApprovalForAll(address indexed account, address indexed operator, bool approved); /// @notice Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI event URI(string value, uint256 indexed id); /// @notice Returns the amount of tokens of token type `id` owned by `account` function balanceOf(address account, uint256 id) external view returns (uint256); /// @notice Batched version of {balanceOf} function balanceOfBatch( address[] calldata accounts, uint256[] calldata ids ) external view returns (uint256[] memory); /// @notice Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved` function setApprovalForAll(address operator, bool approved) external; /// @notice Returns true if `operator` is approved to transfer `account`'s tokens function isApprovedForAll(address account, address operator) external view returns (bool); /// @notice Transfers `amount` tokens of token type `id` from `from` to `to` function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external; /// @notice Batched version of {safeTransferFrom} function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; /// @title IERC721 /// @notice The external ERC721 events, errors, and functions interface IERC721 { /// @dev Thrown when a caller is not authorized to approve or transfer a token error INVALID_APPROVAL(); /// @dev Thrown when a transfer is called with the incorrect token owner error INVALID_OWNER(); /// @dev Thrown when a transfer is attempted to address(0) error INVALID_RECIPIENT(); /// @dev Thrown when an existing token is called to be minted error ALREADY_MINTED(); /// @dev Thrown when a non-existent token is called to be burned error NOT_MINTED(); /// @dev Thrown when address(0) is incorrectly provided error ADDRESS_ZERO(); /// @notice Emitted when a token is transferred from sender to recipient /// @param from The sender address /// @param to The recipient address /// @param tokenId The ERC-721 token id event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /// @notice Emitted when an owner approves an account to manage a token /// @param owner The owner address /// @param approved The account address /// @param tokenId The ERC-721 token id event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /// @notice Emitted when an owner sets an approval for a spender to manage all tokens /// @param owner The owner address /// @param operator The spender address /// @param approved If the approval is being set or removed event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /// @notice Emitted when the contract URI is updated /// @param uri The updated contract URI event ContractURIUpdated(string uri); /// @notice Contract-level metadata function contractURI() external view returns (string memory); /// @notice The number of tokens owned /// @param owner The owner address function balanceOf(address owner) external view returns (uint256); /// @notice The owner of a token /// @param tokenId The ERC-721 token id function ownerOf(uint256 tokenId) external view returns (address); /// @notice The account approved to manage a token /// @param tokenId The ERC-721 token id function getApproved(uint256 tokenId) external view returns (address); /// @notice If an operator is authorized to manage all of an owner's tokens /// @param owner The owner address /// @param operator The operator address function isApprovedForAll(address owner, address operator) external view returns (bool); /// @notice Authorizes an account to manage a token /// @param to The account address /// @param tokenId The ERC-721 token id function approve(address to, uint256 tokenId) external; /// @notice Authorizes an account to manage all tokens /// @param operator The account address /// @param approved If permission is being given or removed function setApprovalForAll(address operator, bool approved) external; /// @notice Safe transfers a token from sender to recipient with additional data /// @param from The sender address /// @param to The recipient address /// @param tokenId The ERC-721 token id /// @param data The additional data sent in the call to the recipient function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /// @notice Safe transfers a token from sender to recipient /// @param from The sender address /// @param to The recipient address /// @param tokenId The ERC-721 token id function safeTransferFrom(address from, address to, uint256 tokenId) external; /// @notice Transfers a token from sender to recipient /// @param from The sender address /// @param to The recipient address /// @param tokenId The ERC-721 token id function transferFrom(address from, address to, uint256 tokenId) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "@ensdomains/=/Users/prop-house/node_modules/@ensdomains/", "@openzeppelin/=/Users/prop-house/node_modules/@openzeppelin/", "@prophouse/=/Users/prop-house/node_modules/@prophouse/", "hardhat/=/Users/prop-house/node_modules/hardhat/", "solady/=/Users/prop-house/node_modules/solady/", "solmate/=/Users/prop-house/node_modules/solmate/", "token/=/Users/prop-house/node_modules/@prophouse/protocol/contracts/ethereum/lib/token/", "types/=/Users/prop-house/node_modules/@prophouse/protocol/contracts/ethereum/lib/types/", "utils/=/Users/prop-house/node_modules/@prophouse/protocol/contracts/ethereum/lib/utils/" ], "optimizer": { "enabled": true, "runs": 10000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"_classHash","type":"uint256"},{"internalType":"address","name":"_propHouse","type":"address"},{"internalType":"address","name":"_starknet","type":"address"},{"internalType":"address","name":"_messenger","type":"address"},{"internalType":"uint256","name":"_roundFactory","type":"uint256"},{"internalType":"uint256","name":"_executionRelayer","type":"uint256"},{"internalType":"address","name":"_manager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ALREADY_CLAIMED","type":"error"},{"inputs":[],"name":"AWARD_AMOUNT_NOT_MULTIPLE_OF_WINNER_COUNT","type":"error"},{"inputs":[],"name":"AWARD_LENGTH_MISMATCH","type":"error"},{"inputs":[],"name":"CANCELLATION_NOT_AVAILABLE","type":"error"},{"inputs":[],"name":"EMERGENCY_WITHDRAWAL_NOT_AVAILABLE","type":"error"},{"inputs":[],"name":"ETHER_TRANSFER_FAILED","type":"error"},{"inputs":[],"name":"FINALIZATION_NOT_AVAILABLE","type":"error"},{"inputs":[],"name":"INSUFFICIENT_ETHER_SUPPLIED","type":"error"},{"inputs":[],"name":"INVALID_ASSET_TYPE","type":"error"},{"inputs":[],"name":"INVALID_ERC721_TRANSFER_AMOUNT","type":"error"},{"inputs":[],"name":"INVALID_MERKLE_PROOF","type":"error"},{"inputs":[{"internalType":"uint256","name":"strategy","type":"uint256"}],"name":"INVALID_STRATEGY","type":"error"},{"inputs":[],"name":"LENGTH_MISMATCH","type":"error"},{"inputs":[],"name":"MISSING_ASSET_AMOUNT","type":"error"},{"inputs":[],"name":"NOT_AUTHORIZED","type":"error"},{"inputs":[],"name":"NO_META_TX_RELAYER_PROVIDED","type":"error"},{"inputs":[],"name":"NO_PROPOSING_STRATEGIES_PROVIDED","type":"error"},{"inputs":[],"name":"NO_VOTING_STRATEGIES_PROVIDED","type":"error"},{"inputs":[],"name":"ONLY_PROP_HOUSE","type":"error"},{"inputs":[],"name":"ONLY_ROUND_MANAGER","type":"error"},{"inputs":[],"name":"ONLY_SECURITY_COUNCIL","type":"error"},{"inputs":[],"name":"PROPOSAL_PERIOD_DURATION_TOO_SHORT","type":"error"},{"inputs":[],"name":"RECLAMATION_NOT_AVAILABLE","type":"error"},{"inputs":[],"name":"UNSAFE_RECIPIENT","type":"error"},{"inputs":[],"name":"UNUSED_ASSET_PARAMETERS","type":"error"},{"inputs":[],"name":"VOTE_PERIOD_DURATION_TOO_SHORT","type":"error"},{"inputs":[],"name":"WINNER_COUNT_OUT_OF_RANGE","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"address","name":"claimer","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"components":[{"internalType":"uint256","name":"assetId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"indexed":false,"internalType":"struct PackedAsset","name":"asset","type":"tuple"}],"name":"AssetClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"address","name":"claimer","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"components":[{"internalType":"uint256","name":"assetId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"indexed":false,"internalType":"struct PackedAsset[]","name":"assets","type":"tuple[]"}],"name":"AssetsClaimed","type":"event"},{"anonymous":false,"inputs":[],"name":"RoundCancelled","type":"event"},{"anonymous":false,"inputs":[],"name":"RoundEmergencyCancelled","type":"event"},{"anonymous":false,"inputs":[],"name":"RoundFinalized","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"enum AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"indexed":false,"internalType":"struct Asset[]","name":"awards","type":"tuple[]"},{"components":[{"internalType":"address","name":"relayer","type":"address"},{"internalType":"uint256","name":"deposit","type":"uint256"}],"indexed":false,"internalType":"struct MetaTransaction","name":"metaTx","type":"tuple"},{"indexed":false,"internalType":"uint248","name":"proposalThreshold","type":"uint248"},{"indexed":false,"internalType":"uint256[]","name":"proposingStrategies","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"proposingStrategyParamsFlat","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"votingStrategies","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"votingStrategyParamsFlat","type":"uint256[]"},{"indexed":false,"internalType":"uint40","name":"proposalPeriodStartTimestamp","type":"uint40"},{"indexed":false,"internalType":"uint40","name":"proposalPeriodDuration","type":"uint40"},{"indexed":false,"internalType":"uint40","name":"votePeriodDuration","type":"uint40"},{"indexed":false,"internalType":"uint16","name":"winnerCount","type":"uint16"}],"name":"RoundRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"EMERGENCY_WITHDRAW_ASSETS_AFTER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_WINNER_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_PROPOSAL_PERIOD_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_VOTE_PERIOD_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RECLAIM_UNCLAIMED_ASSETS_AFTER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"owners","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancel","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"position","type":"uint256"},{"components":[{"internalType":"enum AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Asset","name":"asset","type":"tuple"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"position","type":"uint256"},{"components":[{"internalType":"enum AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Asset","name":"asset","type":"tuple"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"claimTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"classHash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emergencyCancel","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"components":[{"internalType":"enum AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Asset[]","name":"assets","type":"tuple[]"}],"name":"emergencyWithdrawTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"executionRelayer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"merkleRootLow","type":"uint256"},{"internalType":"uint256","name":"merkleRootHigh","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finalizedAt","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"enum AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Asset[]","name":"awards","type":"tuple[]"},{"components":[{"internalType":"address","name":"relayer","type":"address"},{"internalType":"uint256","name":"deposit","type":"uint256"}],"internalType":"struct MetaTransaction","name":"metaTx","type":"tuple"},{"internalType":"uint248","name":"proposalThreshold","type":"uint248"},{"internalType":"uint256[]","name":"proposingStrategies","type":"uint256[]"},{"internalType":"uint256[]","name":"proposingStrategyParamsFlat","type":"uint256[]"},{"internalType":"uint256[]","name":"votingStrategies","type":"uint256[]"},{"internalType":"uint256[]","name":"votingStrategyParamsFlat","type":"uint256[]"},{"internalType":"uint40","name":"proposalPeriodStartTimestamp","type":"uint40"},{"internalType":"uint40","name":"proposalPeriodDuration","type":"uint40"},{"internalType":"uint40","name":"votePeriodDuration","type":"uint40"},{"internalType":"uint16","name":"winnerCount","type":"uint16"}],"internalType":"struct ITimedRound.RoundConfig","name":"config","type":"tuple"}],"name":"getRegistrationPayload","outputs":[{"internalType":"uint256[]","name":"payload","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"house","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"id","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"initialize","outputs":[],"stateMutability":"payable","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":"user","type":"address"},{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"position","type":"uint256"},{"components":[{"internalType":"enum AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Asset","name":"asset","type":"tuple"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"isAssetWinner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"isClaimed","outputs":[{"internalType":"bool","name":"claimed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"position","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"isWinner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"kind","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"manager","outputs":[{"internalType":"contract IManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"messenger","outputs":[{"internalType":"contract IMessenger","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"depositor","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"onDepositReceived","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"depositor","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"onDepositsReceived","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"propHouse","outputs":[{"internalType":"contract IPropHouse","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalPeriodDuration","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalPeriodStartTimestamp","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"enum AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Asset[]","name":"assets","type":"tuple[]"}],"name":"reclaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"components":[{"internalType":"enum AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Asset[]","name":"assets","type":"tuple[]"}],"name":"reclaimTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","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":[],"name":"starknet","outputs":[{"internalType":"contract IStarknetCore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state","outputs":[{"internalType":"enum ITimedRound.RoundState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"title","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votePeriodDuration","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"winnerCount","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"winnerMerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6101a06040523480156200001257600080fd5b50604051620053e7380380620053e7833981016040819052620000359162000097565b64151253515160da1b60805260a0969096526001600160a01b0394851660c05292841660e0529083166101005261012052610140521661016052306101805262000111565b80516001600160a01b03811681146200009257600080fd5b919050565b600080600080600080600060e0888a031215620000b357600080fd5b87519650620000c5602089016200007a565b9550620000d5604089016200007a565b9450620000e5606089016200007a565b93506080880151925060a088015191506200010360c089016200007a565b905092959891949750929550565b60805160a05160c05160e0516101005161012051610140516101605161018051615211620001d66000396000610e560152600081816105c501528181610e8101528181610f8d0152611b6f0152600081816108b40152611a560152600081816129fd0152613ab101526000818161057e015281816129cd0152613a820152600081816108110152611a2901526000818161053201528181610b250152818161141f015261172f01526000818161092f0152610c31015260006103a401526152116000f3fe6080604052600436106103125760003560e01c80639c4cd98c1161019a578063c5a3f532116100e1578063ea8a1af01161008a578063fcd73bf811610064578063fcd73bf814610a1a578063fd15fa1a14610a47578063ff9b3acf14610a6f57600080fd5b8063ea8a1af0146109ac578063f23a6e61146109b4578063f242432a146109fa57600080fd5b8063e094a8e9116100bb578063e094a8e914610789578063e710328014610951578063e985e9c51461097157600080fd5b8063c5a3f532146108a2578063caa02e08146108d6578063d186aafe1461091d57600080fd5b8063b430c28411610143578063bb903eea1161011d578063bb903eea146107ff578063bc197c8114610833578063c19d93fb1461087b57600080fd5b8063b430c2841461079f578063b6013cef146107bf578063b94bcd14146107df57600080fd5b8063a30c956211610174578063a30c956214610756578063af640d0f14610776578063b0633bdd1461078957600080fd5b80639c4cd98c146106db5780639e34070f146106fb578063a22cb4651461073657600080fd5b80633b8a83a61161025e5780634e1273f4116102075780637ffb361b116101e15780637ffb361b14610685578063819e4eea1461069b57806399a6689c146106bb57600080fd5b80634e1273f41461061c5780635c937ad91461063c5780636cebfd0a1461066e57600080fd5b8063481c6a7511610238578063481c6a75146105b35780634a79d50c146105e75780634b31b201146105fc57600080fd5b80633b8a83a6146105205780633cb747bf1461056c578063439fab91146105a057600080fd5b8063150b7a02116102c05780632c4b23081161029a5780632c4b2308146104bf5780632eb2c2d6146104c7578063365d57a4146104e757600080fd5b8063150b7a021461044257806319424e51146104935780632484023e146104a857600080fd5b80630577ac4e116102f15780630577ac4e146103c65780630dc8e3a1146103e85780630e89341c1461041557600080fd5b8062fdd58e1461031757806301ffc9a71461036257806304baa00b14610392575b600080fd5b34801561032357600080fd5b5061034f610332366004613ed2565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b34801561036e57600080fd5b5061038261037d366004613f2c565b610aaf565b6040519015158152602001610359565b34801561039e57600080fd5b5061034f7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103d257600080fd5b506103e66103e1366004613f49565b610b1a565b005b3480156103f457600080fd5b5061040861040336600461422b565b610b9f565b60405161035991906143d5565b34801561042157600080fd5b506104356104303660046143e8565b610e26565b6040516103599190614451565b34801561044e57600080fd5b5061046261045d3660046144ad565b610f60565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610359565b34801561049f57600080fd5b5061034f601981565b3480156104b457600080fd5b5061034f6224ea0081565b6103e6610f8b565b3480156104d357600080fd5b506103e66104e2366004614565565b61108a565b3480156104f357600080fd5b5060045461050a90610100900464ffffffffff1681565b60405164ffffffffff9091168152602001610359565b34801561052c57600080fd5b506105547f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610359565b34801561057857600080fd5b506105547f000000000000000000000000000000000000000000000000000000000000000081565b6103e66105ae366004614624565b611414565b3480156105bf57600080fd5b506105547f000000000000000000000000000000000000000000000000000000000000000081565b3480156105f357600080fd5b5061043561148e565b34801561060857600080fd5b506103e661061736600461467e565b6114d0565b34801561062857600080fd5b506104086106373660046146fa565b6114e6565b34801561064857600080fd5b5060045461050a90700100000000000000000000000000000000900464ffffffffff1681565b34801561067a57600080fd5b5061034f6249d40081565b34801561069157600080fd5b5061034f60005481565b3480156106a757600080fd5b506103e66106b63660046147ab565b611614565b3480156106c757600080fd5b506103826106d636600461467e565b6116b7565b3480156106e757600080fd5b506103e66106f6366004614800565b611724565b34801561070757600080fd5b506103826107163660046143e8565b600881901c600090815260036020526040902054600160ff9092161c1690565b34801561074257600080fd5b506103e6610751366004614880565b61182b565b34801561076257600080fd5b506103e66107713660046148b9565b6118b5565b34801561078257600080fd5b503061034f565b34801561079557600080fd5b5061034f610e1081565b3480156107ab57600080fd5b506103826107ba3660046148ef565b6118c0565b3480156107cb57600080fd5b506103e66107da366004614948565b611949565b3480156107eb57600080fd5b506103e66107fa36600461496a565b611b5f565b34801561080b57600080fd5b506105547f000000000000000000000000000000000000000000000000000000000000000081565b34801561083f57600080fd5b5061046261084e366004614565565b7fbc197c810000000000000000000000000000000000000000000000000000000098975050505050505050565b34801561088757600080fd5b506004546108959060ff1681565b60405161035991906149e5565b3480156108ae57600080fd5b5061034f7f000000000000000000000000000000000000000000000000000000000000000081565b3480156108e257600080fd5b5060045461090a907501000000000000000000000000000000000000000000900461ffff1681565b60405161ffff9091168152602001610359565b34801561092957600080fd5b5061034f7f000000000000000000000000000000000000000000000000000000000000000081565b34801561095d57600080fd5b506103e661096c3660046147ab565b611b6d565b34801561097d57600080fd5b5061038261098c3660046149ff565b600260209081526000928352604080842090915290825290205460ff1681565b6103e6611d32565b3480156109c057600080fd5b506104626109cf366004614a2d565b7ff23a6e61000000000000000000000000000000000000000000000000000000009695505050505050565b348015610a0657600080fd5b506103e6610a15366004614a2d565b611e60565b348015610a2657600080fd5b5060045461050a906b010000000000000000000000900464ffffffffff1681565b348015610a5357600080fd5b5060045461050a906601000000000000900464ffffffffff1681565b348015610a7b57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610554565b60007f993b75c2000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161480610b055750610b0582612105565b80610b145750610b14826121e8565b92915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b7c576040517fde5ad18b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516000815260208101909152610b9a908490849084906122c9565b505050565b60a08101515160c082015151606083810151516080850151519193929160008183610bca8688614ac6565b610bd49190614ac6565b610bde9190614ac6565b9050610beb81600e614ac6565b67ffffffffffffffff811115610c0357610c03613f7e565b604051908082528060200260200182016040528015610c2c578160200160208202803683370190505b5095507f000000000000000000000000000000000000000000000000000000000000000086600181518110610c6357610c63614ad9565b6020908102919091010152610c7981600b614ac6565b86600281518110610c8c57610c8c614ad9565b6020908102919091010152610ca281600a614ac6565b86600381518110610cb557610cb5614ad9565b60209081029190910101528651610ccb906125a6565b86600481518110610cde57610cde614ad9565b6020026020010181815250508660e0015164ffffffffff1686600581518110610d0957610d09614ad9565b60200260200101818152505086610100015164ffffffffff1686600681518110610d3557610d35614ad9565b60200260200101818152505086610120015164ffffffffff1686600781518110610d6157610d61614ad9565b60200260200101818152505086610140015161ffff1686600881518110610d8a57610d8a614ad9565b60200260200101818152505086604001517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1686600981518110610dcf57610dcf614ad9565b6020026020010181815250506000600a9050610df587828a606001518b60800151612610565b9097509050610e1987610e0783614b08565b9250828a60a001518b60c00151612610565b5098975050505050505050565b6040517f59437a500000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301526060917f0000000000000000000000000000000000000000000000000000000000000000909116906359437a5090602401602060405180830381865afa158015610eca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eee9190614b40565b6001600160a01b031663c87b56dd836040518263ffffffff1660e01b8152600401610f1b91815260200190565b600060405180830381865afa158015610f38573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b149190810190614b5d565b7f150b7a02000000000000000000000000000000000000000000000000000000005b95945050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630ef240a06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fe9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100d9190614b40565b6001600160a01b0316336001600160a01b031614611057576040517fc103f65e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61105f612759565b6040517fc0f288cd55e46e1a689ade8d29d0b7bfdc7e6c6b0eed6dc8a8a108f32d2db31590600090a1565b8483146110c3576040517f899ef10d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336001600160a01b0389161480159061110057506001600160a01b038816600090815260026020908152604080832033845290915290205460ff16155b15611137576040517f3d83866f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111db33898989898080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b91829185019084908082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a91508990819084018382808284376000920191909152506114de92505050565b60008060005b8781101561129a578888828181106111fb576111fb614ad9565b90506020020135925086868281811061121657611216614ad9565b6001600160a01b038e16600090815260016020908152604080832089845282528220805493909102949094013595508593925090611255908490614be8565b90915550506001600160a01b038a1660009081526001602090815260408083208684529091528120805484929061128d908490614ac6565b90915550506001016111e1565b50886001600160a01b03168a6001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8b8b8b8b6040516112ee9493929190614c46565b60405180910390a46001600160a01b0389163b156113c5576040517fbc197c8100000000000000000000000000000000000000000000000000000000808252906001600160a01b038b169063bc197c819061135b9033908f908e908e908e908e908e908e90600401614c98565b602060405180830381865afa158015611378573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139c9190614cfc565b7fffffffff000000000000000000000000000000000000000000000000000000001614156113d1565b6001600160a01b038916155b15611408576040517fe704847100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611476576040517fde5ad18b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61148a6114858284018461422b565b6127de565b5050565b60606114cb6015367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560f81c612b26565b905090565b6114de868686868686612b72565b505050505050565b6060838214611521576040517f899ef10d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8367ffffffffffffffff81111561153a5761153a613f7e565b604051908082528060200260200182016040528015611563578160200160208202803683370190505b50905060005b8481101561160b576001600087878481811061158757611587614ad9565b905060200201602081019061159c9190614d19565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008585848181106115d0576115d0614ad9565b905060200201358152602001908152602001600020548282815181106115f8576115f8614ad9565b6020908102919091010152600101611569565b50949350505050565b600060045460ff16600281111561162d5761162d6149b6565b14806116755750600260045460ff16600281111561164d5761164d6149b6565b14801561167557506004546224ea009061167390610100900464ffffffffff1642614be8565b105b156116ac576040517f40af00ce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b9a838383612cd4565b6000611719838380806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054925061171491508a9050898c61170f61170a368d90038d018d614d36565b612d6f565b612dab565b612de5565b979650505050505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611786576040517fde5ad18b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118248585858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808902828101820190935288825290935088925087918291850190849080828437600092018290525092506117f4915050565b6040519080825280601f01601f19166020018201604052801561181e576020820181803683370190505b50612e27565b5050505050565b3360008181526002602090815260408083206001600160a01b0387168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b61148a338383611614565b600061193f838380806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054604080516001600160a01b038e1660208201529081018c9052606081018b905290935060800191506119249050565b60405160208183030381529060405280519060200120612de5565b9695505050505050565b600060045460ff166002811115611962576119626149b6565b14611999576040517fafb7609900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051600280825260608201835260009260208301908036833701905050905082816000815181106119ce576119ce614ad9565b60200260200101818152505081816001815181106119ee576119ee614ad9565b60209081029190910101526040517f2c9dd5c00000000000000000000000000000000000000000000000000000000081526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632c9dd5c090611a80907f0000000000000000000000000000000000000000000000000000000000000000908590600401614d52565b6020604051808303816000875af1158015611a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ac39190614d6b565b50611ad283608084901b614ac6565b6000908155600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0064ffffffffff421661010002167fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000009091161760021790556040517f592e67f0ea96f60b5b007072427213c8dd69b145824051a5d8ac4bef38c809cd9190a1505050565b611824338686868686612b72565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630ef240a06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bef9190614b40565b6001600160a01b0316336001600160a01b031614611c39576040517fc103f65e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60045460009064ffffffffff7001000000000000000000000000000000008204811691611c82916b01000000000000000000000082048116916601000000000000900416614d84565b611c8c9190614d84565b64ffffffffff16905080421080611cae57506249d400611cac8242614be8565b105b15611ce5576040517f78a931db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561182457611d22848483818110611d0557611d05614ad9565b905060800201803603810190611d1b9190614d36565b3087613185565b611d2b81614b08565b9050611ce8565b367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c6040517f6352211e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b039190911690636352211e90602401602060405180830381865afa158015611dbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611de39190614b40565b6001600160a01b0316336001600160a01b031614611e2d576040517f36b57cf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e35612759565b6040517fdd287b702179a5c0cb1da128f0c74f3d92185d10282e995ed8ad9285d24c749390600090a1565b336001600160a01b03871614801590611e9d57506001600160a01b038616600090815260026020908152604080832033845290915290205460ff16155b15611ed4576040517f3d83866f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611edf856132fa565b90506000611eec856132fa565b9050611f32338989858589898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506114de92505050565b6001600160a01b038816600090815260016020908152604080832089845290915281208054879290611f65908490614be8565b90915550506001600160a01b038716600090815260016020908152604080832089845290915281208054879290611f9d908490614ac6565b909155505060408051878152602081018790526001600160a01b03808a1692908b169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46001600160a01b0387163b156120b8576040517ff23a6e6100000000000000000000000000000000000000000000000000000000808252906001600160a01b0389169063f23a6e619061204e9033908d908c908c908c908c90600401614da9565b602060405180830381865afa15801561206b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061208f9190614cfc565b7fffffffff000000000000000000000000000000000000000000000000000000001614156120c4565b6001600160a01b038716155b156120fb576040517fe704847100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f150b7a0200000000000000000000000000000000000000000000000000000000148061219857507fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e000000000000000000000000000000000000000000000000000000000145b80610b1457507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610b14565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316148061227b57507fd9b67a26000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b80610b145750507fffffffff00000000000000000000000000000000000000000000000000000000167f0e89341c000000000000000000000000000000000000000000000000000000001490565b60006122d4846132fa565b905060006122e1846132fa565b90506001600160a01b038616600090815260016020908152604080832088845290915281208054869290612316908490614ac6565b909155505060408051868152602081018690526001600160a01b0388169160009133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4856001600160a01b03163b6000036123bb576001600160a01b0386166123b6576040517fe704847100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114de565b6040517ff23a6e610000000000000000000000000000000000000000000000000000000081526001600160a01b0387169063f23a6e61906124099033906000908a908a908a90600401614dee565b602060405180830381865afa925050508015612442575060408051601f3d908101601f1916820190925261243f91810190614cfc565b60015b612522576040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f4e2312e00000000000000000000000000000000000000000000000000000000060048201526001600160a01b038716906301ffc9a790602401602060405180830381865afa9250505080156124df575060408051601f3d908101601f191682019092526124dc91810190614e26565b60015b156123b657801561251c576040517fe704847100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506114de565b7fffffffff0000000000000000000000000000000000000000000000000000000081167ff23a6e61000000000000000000000000000000000000000000000000000000001461259d576040517fe704847100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050565b600081516000036125b957506000919050565b610b146125c583613341565b6040516020016125d59190614e43565b604051602081830303815290604052805190602001207f03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b6060600080845190506000845190508188888151811061263257612632614ad9565b60200260200101818152505060005b828110156126d657600087828151811061265d5761265d614ad9565b60200260200101519050806000036126a9576040517f972c8031000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b808a8a6001019a508a815181106126c2576126c2614ad9565b602090810291909101015250600101612641565b50808888600101985088815181106126f0576126f0614ad9565b60200260200101818152505060005b8181101561274c5785818151811061271957612719614ad9565b602002602001015189896001019950898151811061273957612739614ad9565b60209081029190910101526001016126ff565b5096979596505050505050565b600060045460ff166002811115612772576127726149b6565b146127a9576040517fab8bbfcb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556127dc613400565b565b6127e78161346e565b6127f58160e00151426136cf565b64ffffffffff90811660e08301819052600480546101008501516101208601516101408701517fffffffffffffffffffffffffffffffff00000000000000000000ffffffffffff90931666010000000000009095027fffffffffffffffffffffffffffffffff0000000000ffffffffffffffffffffff16949094176b01000000000000000000000091861691909102177fffffffffffffffffff00000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000093909416929092027fffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffffff1692909217750100000000000000000000000000000000000000000061ffff9092169190910217905560208082015101513490156129cb576020820151516001600160a01b031661295f576040517fb89ca71700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8082602001516020015111156129a1576040517f5471cb3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208083015180519101516129b691906136f5565b60208083015101516129c89082614be8565b90505b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633e3aa6c5827f00000000000000000000000000000000000000000000000000000000000000007f026490f901ea8ad5a245d987479919f1d20fbb0c164367e33ef09a9ea4ba8d04612a4687610b9f565b6040518563ffffffff1660e01b8152600401612a6493929190614e9a565b60206040518083038185885af1158015612a82573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612aa79190614d6b565b507ff93b0473b6b241759edb8067d8e2dcd903c30c0fc0e6ddc420c5935a8147883e826000015183602001518460400151856060015186608001518760a001518860c001518960e001518a61010001518b61012001518c6101400151604051612b1a9b9a99989796959493929190614eb9565b60405180910390a15050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900382848201602084013750908101603f01601f1916604052919050565b600885901c60009081526003602052604090205460ff86161c60011615612bc5576040517fa308b6e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612bd961170a36869003860186614d36565b9050612c20838380806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054925061171491508a9050893387612dab565b612c56576040517f7d23b90100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600886901c60009081526003602052604090208054600160ff89161b179055612c8e612c8736869003860186614d36565b3089613185565b7fba1802a545423fb47284e96829dad7921d663eeaf62f97cfe3a152593dd9406f86338984604051612cc3949392919061501d565b60405180910390a150505050505050565b803360005b828110156114de576000612d13868684818110612cf857612cf8614ad9565b905060800201803603810190612d0e9190614d36565b613745565b9050612d3b8382888886818110612d2c57612d2c614ad9565b9050608002016060013561382c565b612d66868684818110612d5057612d50614ad9565b905060800201803603810190612c879190614d36565b50600101612cd9565b60408051808201909152600080825260208201526040518060400160405280612d9784613745565b815260200183606001518152509050919050565b600084848484604051602001612dc49493929190615052565b6040516020818303038152906040528051906020012090505b949350505050565b6000835115612e205760208401845160051b81015b8151841160051b938452815160209485185260406000209390910190808210612dfa5750505b5014919050565b825182518114612e63576040517f899ef10d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612ef357838181518110612e8057612e80614ad9565b602002602001015160016000886001600160a01b03166001600160a01b031681526020019081526020016000206000878481518110612ec157612ec1614ad9565b602002602001015181526020019081526020016000206000828254612ee69190614ac6565b9091555050600101612e66565b50846001600160a01b031660006001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051612f44929190615084565b60405180910390a4846001600160a01b03163b600003612fa3576001600160a01b038516612f9e576040517fe704847100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611824565b6040517fbc197c810000000000000000000000000000000000000000000000000000000081526001600160a01b0386169063bc197c8190612ff19033906000908990899089906004016150a9565b602060405180830381865afa92505050801561302a575060408051601f3d908101601f1916820190925261302791810190614cfc565b60015b61310a576040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f4e2312e00000000000000000000000000000000000000000000000000000000060048201526001600160a01b038616906301ffc9a790602401602060405180830381865afa9250505080156130c7575060408051601f3d908101601f191682019092526130c491810190614e26565b60015b15612f9e578015613104576040517fe704847100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611824565b7fffffffff0000000000000000000000000000000000000000000000000000000081167fbc197c8100000000000000000000000000000000000000000000000000000000146114de576040517fe704847100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008351600381111561319a5761319a6149b6565b036131f857604083015160208401516001600160a01b031617156131ea576040517f2de52bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b9a8184606001516136f5565b60018351600381111561320d5761320d6149b6565b036132625760408301511561324e576040517f2de52bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b9a8360200151838386606001516138dd565b600283516003811115613277576132776149b6565b0361329557610b9a836020015184604001518484876060015161392a565b6003835160038111156132aa576132aa6149b6565b036132c857610b9a83602001518460400151848487606001516139ef565b6040517f4ed63ade00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051600180825281830190925260609160208083019080368337019050509050818160008151811061333057613330614ad9565b602002602001018181525050919050565b80516060908067ffffffffffffffff81111561335f5761335f613f7e565b6040519080825280602002602001820160405280156133a457816020015b604080518082019091526000808252602082015281526020019060019003908161337d5790505b50915060005b818110156133f9576133d48482815181106133c7576133c7614ad9565b6020026020010151612d6f565b8382815181106133e6576133e6614ad9565b60209081029190910101526001016133aa565b5050919050565b60408051600380825260808201909252600091602082016060803683370190505090507e8af3ea41808c9515720e56add54a2d8008458a8bc5e347b791c6d75cd0e4078160018151811061345657613456614ad9565b60200260200101818152505061346b81613a52565b50565b610e1081610100015164ffffffffff1610156134b6576040517f8b2625cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e1081610120015164ffffffffff1610156134fe576040517fa6314e8e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61014081015161ffff16158061351d5750601981610140015161ffff16115b15613554576040517f51f09de700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408101517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff161580159061358b5750606081015151155b156135c2576040517f1bf0e08400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060a0015151600003613601576040517f870c2a7200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80515115801590613620575080610140015161ffff1681600001515114155b1561346b57805151600114613661576040517fd6a5c38a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80610140015161ffff16816000015160008151811061368257613682614ad9565b60200260200101516060015161369891906150fb565b1561346b576040517fa08d106700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008164ffffffffff168364ffffffffff16116136ec57816136ee565b825b9392505050565b6136fe81613b40565b60008060008060008587612710f1905080610b9a576040517f46fcf95700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808251600381111561375b5761375b6149b6565b036137735781516003811115610b1457610b146149b6565b600182516003811115613788576137886149b6565b036137bb5781516020808401516040516137a393920161514d565b604051602081830303815290604052610b149061518c565b81516020808401516040808601519051613805930160609290921b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000168252601482015260340190565b604051602081830303815290604052805190602001206040516020016137a39291906151ce565b6000613837836132fa565b90506000613844836132fa565b60408051602081019091526000905290506001600160a01b038516600090815260016020908152604080832087845290915281208054859290613888908490614be8565b909155505060408051858152602081018590526000916001600160a01b0388169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050505050565b6138e681613b40565b306001600160a01b0384160361390f5761390a6001600160a01b0385168383613b7a565b613924565b6139246001600160a01b038516848484613c23565b50505050565b80600114613964576040517fe362007300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301528381166024830152604482018690528616906323b872dd906064015b600060405180830381600087803b1580156139d057600080fd5b505af11580156139e4573d6000803e3d6000fd5b505050505050505050565b6139f881613b40565b604080516000815260208101918290527ff242432a000000000000000000000000000000000000000000000000000000009091526001600160a01b0386169063f242432a906139b690869086908990879060248101614dee565b6040517f3e3aa6c50000000000000000000000000000000000000000000000000000000081526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633e3aa6c5903490613afd907f0000000000000000000000000000000000000000000000000000000000000000907f024931ca109ce0ffa87913d91f12d6ac327550c015a573c7b17a187c29ed8c1a908790600401614e9a565b60206040518083038185885af1158015613b1b573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061148a9190614d6b565b8060000361346b576040517fccd1eba200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052610b9a9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613c74565b6040516001600160a01b03808516602483015283166044820152606481018290526139249085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401613bbf565b6000613cc9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613d769092919063ffffffff16565b9050805160001480613cea575080806020019051810190613cea9190614e26565b610b9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016126a0565b6060612ddd848460008585600080866001600160a01b03168587604051613d9d91906151e8565b60006040518083038185875af1925050503d8060008114613dda576040519150601f19603f3d011682016040523d82523d6000602084013e613ddf565b606091505b50915091506117198783838760608315613e74578251600003613e6d576001600160a01b0385163b613e6d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016126a0565b5081612ddd565b612ddd8383815115613e895781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126a09190614451565b6001600160a01b038116811461346b57600080fd5b60008060408385031215613ee557600080fd5b8235613ef081613ebd565b946020939093013593505050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461346b57600080fd5b600060208284031215613f3e57600080fd5b81356136ee81613efe565b600080600060608486031215613f5e57600080fd5b8335613f6981613ebd565b95602085013595506040909401359392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610160810167ffffffffffffffff81118282101715613fd157613fd1613f7e565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561400057614000613f7e565b604052919050565b600067ffffffffffffffff82111561402257614022613f7e565b5060051b60200190565b60006080828403121561403e57600080fd5b6040516080810181811067ffffffffffffffff8211171561406157614061613f7e565b60405290508082356004811061407657600080fd5b8152602083013561408681613ebd565b8060208301525060408301356040820152606083013560608201525092915050565b600082601f8301126140b957600080fd5b813560206140ce6140c983614008565b613fd7565b82815260079290921b840181019181810190868411156140ed57600080fd5b8286015b8481101561411157614103888261402c565b8352918301916080016140f1565b509695505050505050565b60006040828403121561412e57600080fd5b6040516040810181811067ffffffffffffffff8211171561415157614151613f7e565b604052905080823561416281613ebd565b8152602092830135920191909152919050565b80357effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146141a457600080fd5b919050565b600082601f8301126141ba57600080fd5b813560206141ca6140c983614008565b82815260059290921b840181019181810190868411156141e957600080fd5b8286015b8481101561411157803583529183019183016141ed565b803564ffffffffff811681146141a457600080fd5b803561ffff811681146141a457600080fd5b60006020828403121561423d57600080fd5b813567ffffffffffffffff8082111561425557600080fd5b90830190610180828603121561426a57600080fd5b614272613fad565b82358281111561428157600080fd5b61428d878286016140a8565b82525061429d866020850161411c565b60208201526142ae60608401614175565b60408201526080830135828111156142c557600080fd5b6142d1878286016141a9565b60608301525060a0830135828111156142e957600080fd5b6142f5878286016141a9565b60808301525060c08301358281111561430d57600080fd5b614319878286016141a9565b60a08301525060e08301358281111561433157600080fd5b61433d878286016141a9565b60c0830152506101009150614353828401614204565b60e0820152610120614366818501614204565b83830152610140925061437a838501614204565b9082015261438b6101608401614219565b91810191909152949350505050565b600081518084526020808501945080840160005b838110156143ca578151875295820195908201906001016143ae565b509495945050505050565b6020815260006136ee602083018461439a565b6000602082840312156143fa57600080fd5b5035919050565b60005b8381101561441c578181015183820152602001614404565b50506000910152565b6000815180845261443d816020860160208601614401565b601f01601f19169290920160200192915050565b6020815260006136ee6020830184614425565b60008083601f84011261447657600080fd5b50813567ffffffffffffffff81111561448e57600080fd5b6020830191508360208285010111156144a657600080fd5b9250929050565b6000806000806000608086880312156144c557600080fd5b85356144d081613ebd565b945060208601356144e081613ebd565b935060408601359250606086013567ffffffffffffffff81111561450357600080fd5b61450f88828901614464565b969995985093965092949392505050565b60008083601f84011261453257600080fd5b50813567ffffffffffffffff81111561454a57600080fd5b6020830191508360208260051b85010111156144a657600080fd5b60008060008060008060008060a0898b03121561458157600080fd5b883561458c81613ebd565b9750602089013561459c81613ebd565b9650604089013567ffffffffffffffff808211156145b957600080fd5b6145c58c838d01614520565b909850965060608b01359150808211156145de57600080fd5b6145ea8c838d01614520565b909650945060808b013591508082111561460357600080fd5b506146108b828c01614464565b999c989b5096995094979396929594505050565b6000806020838503121561463757600080fd5b823567ffffffffffffffff81111561464e57600080fd5b61465a85828601614464565b90969095509350505050565b60006080828403121561467857600080fd5b50919050565b600080600080600080610100878903121561469857600080fd5b86356146a381613ebd565b955060208701359450604087013593506146c08860608901614666565b925060e087013567ffffffffffffffff8111156146dc57600080fd5b6146e889828a01614520565b979a9699509497509295939492505050565b6000806000806040858703121561471057600080fd5b843567ffffffffffffffff8082111561472857600080fd5b61473488838901614520565b9096509450602087013591508082111561474d57600080fd5b5061475a87828801614520565b95989497509550505050565b60008083601f84011261477857600080fd5b50813567ffffffffffffffff81111561479057600080fd5b6020830191508360208260071b85010111156144a657600080fd5b6000806000604084860312156147c057600080fd5b83356147cb81613ebd565b9250602084013567ffffffffffffffff8111156147e757600080fd5b6147f386828701614766565b9497909650939450505050565b60008060008060006060868803121561481857600080fd5b853561482381613ebd565b9450602086013567ffffffffffffffff8082111561484057600080fd5b61484c89838a01614520565b9096509450604088013591508082111561486557600080fd5b5061450f88828901614520565b801515811461346b57600080fd5b6000806040838503121561489357600080fd5b823561489e81613ebd565b915060208301356148ae81614872565b809150509250929050565b600080602083850312156148cc57600080fd5b823567ffffffffffffffff8111156148e357600080fd5b61465a85828601614766565b60008060008060006080868803121561490757600080fd5b853561491281613ebd565b94506020860135935060408601359250606086013567ffffffffffffffff81111561493c57600080fd5b61450f88828901614520565b6000806040838503121561495b57600080fd5b50508035926020909101359150565b600080600080600060e0868803121561498257600080fd5b853594506020860135935061499a8760408801614666565b925060c086013567ffffffffffffffff81111561493c57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600383106149f9576149f96149b6565b91905290565b60008060408385031215614a1257600080fd5b8235614a1d81613ebd565b915060208301356148ae81613ebd565b60008060008060008060a08789031215614a4657600080fd5b8635614a5181613ebd565b95506020870135614a6181613ebd565b94506040870135935060608701359250608087013567ffffffffffffffff811115614a8b57600080fd5b6146e889828a01614464565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115610b1457610b14614a97565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614b3957614b39614a97565b5060010190565b600060208284031215614b5257600080fd5b81516136ee81613ebd565b600060208284031215614b6f57600080fd5b815167ffffffffffffffff80821115614b8757600080fd5b818401915084601f830112614b9b57600080fd5b815181811115614bad57614bad613f7e565b614bc06020601f19601f84011601613fd7565b9150808252856020828501011115614bd757600080fd5b61160b816020840160208601614401565b81810381811115610b1457610b14614a97565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115614c2d57600080fd5b8260051b80836020870137939093016020019392505050565b604081526000614c5a604083018688614bfb565b8281036020840152611719818587614bfb565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b60006001600160a01b03808b168352808a1660208401525060a06040830152614cc560a08301888a614bfb565b8281036060840152614cd8818789614bfb565b90508281036080840152614ced818587614c6d565b9b9a5050505050505050505050565b600060208284031215614d0e57600080fd5b81516136ee81613efe565b600060208284031215614d2b57600080fd5b81356136ee81613ebd565b600060808284031215614d4857600080fd5b6136ee838361402c565b828152604060208201526000612ddd604083018461439a565b600060208284031215614d7d57600080fd5b5051919050565b64ffffffffff818116838216019080821115614da257614da2614a97565b5092915050565b60006001600160a01b03808916835280881660208401525085604083015284606083015260a06080830152614de260a083018486614c6d565b98975050505050505050565b60006001600160a01b03808816835280871660208401525084604083015283606083015260a0608083015261171960a0830184614425565b600060208284031215614e3857600080fd5b81516136ee81614872565b602080825282518282018190526000919060409081850190868401855b82811015614e8d57614e7d84835180518252602090810151910152565b9284019290850190600101614e60565b5091979650505050505050565b838152826020820152606060408201526000610f82606083018461439a565b6101808152600061018082018d518082526101a08401915060208f0160005b82811015614f37578151805160048110614ef457614ef46149b6565b808652506001600160a01b036020820151166020860152604081015160408601526060810151606086015250608084019350602082019150600181019050614ed8565b505050614f5a602084018e80516001600160a01b03168252602090810151910152565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8c1660608401528281036080840152614f93818c61439a565b905082810360a0840152614fa7818b61439a565b905082810360c0840152614fbb818a61439a565b905082810360e0840152614fcf818961439a565b915050614fe661010083018764ffffffffff169052565b64ffffffffff851661012083015264ffffffffff841661014083015261ffff83166101608301529c9b505050505050505050505050565b8481526001600160a01b0384811660208301528316604082015260a08101610f82606083018480518252602090810151910152565b84815260208082018590526001600160a01b038416604083015282516060830152820151608082015260a08101610f82565b604081526000615097604083018561439a565b8281036020840152610f82818561439a565b60006001600160a01b03808816835280871660208401525060a060408301526150d560a083018661439a565b82810360608401526150e7818661439a565b90508281036080840152614de28185614425565b600082615131577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b60048110615146576151466149b6565b60f81b9052565b6151578184615136565b60609190911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166001820152601501919050565b80516020808301519190811015614678577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60209190910360031b1b16919050565b6151d88184615136565b6001810191909152602101919050565b600082516151fa818460208701614401565b919091019291505056fea164736f6c6343000815000a0091fa917c9800be6c78603a53148e005b5482c5fb42350b775c2419031e34a2000000000000000000000000000000002c93cad6f9cfd00c603aef62458d8a48000000000000000000000000c662c410c0ecf747543f5ba90660f6abebd9c8c4000000000000000000000000f6a66b137b993a4571329cdc9f2523ac8da01649054b7b08b5389709af79a65b21574231b9adb0c313c1598aac94ee44fe99d21305f2121d1831e68803d656f4e1632e72047faae731f3f7dd042b6efb7d6bbd4b000000000000000000000000e867928874439b6c48fb42e908ba0519f287932a
Deployed Bytecode
0x6080604052600436106103125760003560e01c80639c4cd98c1161019a578063c5a3f532116100e1578063ea8a1af01161008a578063fcd73bf811610064578063fcd73bf814610a1a578063fd15fa1a14610a47578063ff9b3acf14610a6f57600080fd5b8063ea8a1af0146109ac578063f23a6e61146109b4578063f242432a146109fa57600080fd5b8063e094a8e9116100bb578063e094a8e914610789578063e710328014610951578063e985e9c51461097157600080fd5b8063c5a3f532146108a2578063caa02e08146108d6578063d186aafe1461091d57600080fd5b8063b430c28411610143578063bb903eea1161011d578063bb903eea146107ff578063bc197c8114610833578063c19d93fb1461087b57600080fd5b8063b430c2841461079f578063b6013cef146107bf578063b94bcd14146107df57600080fd5b8063a30c956211610174578063a30c956214610756578063af640d0f14610776578063b0633bdd1461078957600080fd5b80639c4cd98c146106db5780639e34070f146106fb578063a22cb4651461073657600080fd5b80633b8a83a61161025e5780634e1273f4116102075780637ffb361b116101e15780637ffb361b14610685578063819e4eea1461069b57806399a6689c146106bb57600080fd5b80634e1273f41461061c5780635c937ad91461063c5780636cebfd0a1461066e57600080fd5b8063481c6a7511610238578063481c6a75146105b35780634a79d50c146105e75780634b31b201146105fc57600080fd5b80633b8a83a6146105205780633cb747bf1461056c578063439fab91146105a057600080fd5b8063150b7a02116102c05780632c4b23081161029a5780632c4b2308146104bf5780632eb2c2d6146104c7578063365d57a4146104e757600080fd5b8063150b7a021461044257806319424e51146104935780632484023e146104a857600080fd5b80630577ac4e116102f15780630577ac4e146103c65780630dc8e3a1146103e85780630e89341c1461041557600080fd5b8062fdd58e1461031757806301ffc9a71461036257806304baa00b14610392575b600080fd5b34801561032357600080fd5b5061034f610332366004613ed2565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b34801561036e57600080fd5b5061038261037d366004613f2c565b610aaf565b6040519015158152602001610359565b34801561039e57600080fd5b5061034f7f54494d454400000000000000000000000000000000000000000000000000000081565b3480156103d257600080fd5b506103e66103e1366004613f49565b610b1a565b005b3480156103f457600080fd5b5061040861040336600461422b565b610b9f565b60405161035991906143d5565b34801561042157600080fd5b506104356104303660046143e8565b610e26565b6040516103599190614451565b34801561044e57600080fd5b5061046261045d3660046144ad565b610f60565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610359565b34801561049f57600080fd5b5061034f601981565b3480156104b457600080fd5b5061034f6224ea0081565b6103e6610f8b565b3480156104d357600080fd5b506103e66104e2366004614565565b61108a565b3480156104f357600080fd5b5060045461050a90610100900464ffffffffff1681565b60405164ffffffffff9091168152602001610359565b34801561052c57600080fd5b506105547f000000000000000000000000000000002c93cad6f9cfd00c603aef62458d8a4881565b6040516001600160a01b039091168152602001610359565b34801561057857600080fd5b506105547f000000000000000000000000f6a66b137b993a4571329cdc9f2523ac8da0164981565b6103e66105ae366004614624565b611414565b3480156105bf57600080fd5b506105547f000000000000000000000000e867928874439b6c48fb42e908ba0519f287932a81565b3480156105f357600080fd5b5061043561148e565b34801561060857600080fd5b506103e661061736600461467e565b6114d0565b34801561062857600080fd5b506104086106373660046146fa565b6114e6565b34801561064857600080fd5b5060045461050a90700100000000000000000000000000000000900464ffffffffff1681565b34801561067a57600080fd5b5061034f6249d40081565b34801561069157600080fd5b5061034f60005481565b3480156106a757600080fd5b506103e66106b63660046147ab565b611614565b3480156106c757600080fd5b506103826106d636600461467e565b6116b7565b3480156106e757600080fd5b506103e66106f6366004614800565b611724565b34801561070757600080fd5b506103826107163660046143e8565b600881901c600090815260036020526040902054600160ff9092161c1690565b34801561074257600080fd5b506103e6610751366004614880565b61182b565b34801561076257600080fd5b506103e66107713660046148b9565b6118b5565b34801561078257600080fd5b503061034f565b34801561079557600080fd5b5061034f610e1081565b3480156107ab57600080fd5b506103826107ba3660046148ef565b6118c0565b3480156107cb57600080fd5b506103e66107da366004614948565b611949565b3480156107eb57600080fd5b506103e66107fa36600461496a565b611b5f565b34801561080b57600080fd5b506105547f000000000000000000000000c662c410c0ecf747543f5ba90660f6abebd9c8c481565b34801561083f57600080fd5b5061046261084e366004614565565b7fbc197c810000000000000000000000000000000000000000000000000000000098975050505050505050565b34801561088757600080fd5b506004546108959060ff1681565b60405161035991906149e5565b3480156108ae57600080fd5b5061034f7f05f2121d1831e68803d656f4e1632e72047faae731f3f7dd042b6efb7d6bbd4b81565b3480156108e257600080fd5b5060045461090a907501000000000000000000000000000000000000000000900461ffff1681565b60405161ffff9091168152602001610359565b34801561092957600080fd5b5061034f7f0091fa917c9800be6c78603a53148e005b5482c5fb42350b775c2419031e34a281565b34801561095d57600080fd5b506103e661096c3660046147ab565b611b6d565b34801561097d57600080fd5b5061038261098c3660046149ff565b600260209081526000928352604080842090915290825290205460ff1681565b6103e6611d32565b3480156109c057600080fd5b506104626109cf366004614a2d565b7ff23a6e61000000000000000000000000000000000000000000000000000000009695505050505050565b348015610a0657600080fd5b506103e6610a15366004614a2d565b611e60565b348015610a2657600080fd5b5060045461050a906b010000000000000000000000900464ffffffffff1681565b348015610a5357600080fd5b5060045461050a906601000000000000900464ffffffffff1681565b348015610a7b57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610554565b60007f993b75c2000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161480610b055750610b0582612105565b80610b145750610b14826121e8565b92915050565b336001600160a01b037f000000000000000000000000000000002c93cad6f9cfd00c603aef62458d8a481614610b7c576040517fde5ad18b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516000815260208101909152610b9a908490849084906122c9565b505050565b60a08101515160c082015151606083810151516080850151519193929160008183610bca8688614ac6565b610bd49190614ac6565b610bde9190614ac6565b9050610beb81600e614ac6565b67ffffffffffffffff811115610c0357610c03613f7e565b604051908082528060200260200182016040528015610c2c578160200160208202803683370190505b5095507f0091fa917c9800be6c78603a53148e005b5482c5fb42350b775c2419031e34a286600181518110610c6357610c63614ad9565b6020908102919091010152610c7981600b614ac6565b86600281518110610c8c57610c8c614ad9565b6020908102919091010152610ca281600a614ac6565b86600381518110610cb557610cb5614ad9565b60209081029190910101528651610ccb906125a6565b86600481518110610cde57610cde614ad9565b6020026020010181815250508660e0015164ffffffffff1686600581518110610d0957610d09614ad9565b60200260200101818152505086610100015164ffffffffff1686600681518110610d3557610d35614ad9565b60200260200101818152505086610120015164ffffffffff1686600781518110610d6157610d61614ad9565b60200260200101818152505086610140015161ffff1686600881518110610d8a57610d8a614ad9565b60200260200101818152505086604001517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1686600981518110610dcf57610dcf614ad9565b6020026020010181815250506000600a9050610df587828a606001518b60800151612610565b9097509050610e1987610e0783614b08565b9250828a60a001518b60c00151612610565b5098975050505050505050565b6040517f59437a500000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000b9d919006cefcc873a2154ee4fd4662577f4b400811660048301526060917f000000000000000000000000e867928874439b6c48fb42e908ba0519f287932a909116906359437a5090602401602060405180830381865afa158015610eca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eee9190614b40565b6001600160a01b031663c87b56dd836040518263ffffffff1660e01b8152600401610f1b91815260200190565b600060405180830381865afa158015610f38573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b149190810190614b5d565b7f150b7a02000000000000000000000000000000000000000000000000000000005b95945050505050565b7f000000000000000000000000e867928874439b6c48fb42e908ba0519f287932a6001600160a01b0316630ef240a06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fe9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100d9190614b40565b6001600160a01b0316336001600160a01b031614611057576040517fc103f65e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61105f612759565b6040517fc0f288cd55e46e1a689ade8d29d0b7bfdc7e6c6b0eed6dc8a8a108f32d2db31590600090a1565b8483146110c3576040517f899ef10d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336001600160a01b0389161480159061110057506001600160a01b038816600090815260026020908152604080832033845290915290205460ff16155b15611137576040517f3d83866f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111db33898989898080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b91829185019084908082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a91508990819084018382808284376000920191909152506114de92505050565b60008060005b8781101561129a578888828181106111fb576111fb614ad9565b90506020020135925086868281811061121657611216614ad9565b6001600160a01b038e16600090815260016020908152604080832089845282528220805493909102949094013595508593925090611255908490614be8565b90915550506001600160a01b038a1660009081526001602090815260408083208684529091528120805484929061128d908490614ac6565b90915550506001016111e1565b50886001600160a01b03168a6001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8b8b8b8b6040516112ee9493929190614c46565b60405180910390a46001600160a01b0389163b156113c5576040517fbc197c8100000000000000000000000000000000000000000000000000000000808252906001600160a01b038b169063bc197c819061135b9033908f908e908e908e908e908e908e90600401614c98565b602060405180830381865afa158015611378573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139c9190614cfc565b7fffffffff000000000000000000000000000000000000000000000000000000001614156113d1565b6001600160a01b038916155b15611408576040517fe704847100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050505050565b336001600160a01b037f000000000000000000000000000000002c93cad6f9cfd00c603aef62458d8a481614611476576040517fde5ad18b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61148a6114858284018461422b565b6127de565b5050565b60606114cb6015367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560f81c612b26565b905090565b6114de868686868686612b72565b505050505050565b6060838214611521576040517f899ef10d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8367ffffffffffffffff81111561153a5761153a613f7e565b604051908082528060200260200182016040528015611563578160200160208202803683370190505b50905060005b8481101561160b576001600087878481811061158757611587614ad9565b905060200201602081019061159c9190614d19565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008585848181106115d0576115d0614ad9565b905060200201358152602001908152602001600020548282815181106115f8576115f8614ad9565b6020908102919091010152600101611569565b50949350505050565b600060045460ff16600281111561162d5761162d6149b6565b14806116755750600260045460ff16600281111561164d5761164d6149b6565b14801561167557506004546224ea009061167390610100900464ffffffffff1642614be8565b105b156116ac576040517f40af00ce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b9a838383612cd4565b6000611719838380806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054925061171491508a9050898c61170f61170a368d90038d018d614d36565b612d6f565b612dab565b612de5565b979650505050505050565b336001600160a01b037f000000000000000000000000000000002c93cad6f9cfd00c603aef62458d8a481614611786576040517fde5ad18b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118248585858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808902828101820190935288825290935088925087918291850190849080828437600092018290525092506117f4915050565b6040519080825280601f01601f19166020018201604052801561181e576020820181803683370190505b50612e27565b5050505050565b3360008181526002602090815260408083206001600160a01b0387168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b61148a338383611614565b600061193f838380806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054604080516001600160a01b038e1660208201529081018c9052606081018b905290935060800191506119249050565b60405160208183030381529060405280519060200120612de5565b9695505050505050565b600060045460ff166002811115611962576119626149b6565b14611999576040517fafb7609900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051600280825260608201835260009260208301908036833701905050905082816000815181106119ce576119ce614ad9565b60200260200101818152505081816001815181106119ee576119ee614ad9565b60209081029190910101526040517f2c9dd5c00000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000c662c410c0ecf747543f5ba90660f6abebd9c8c41690632c9dd5c090611a80907f05f2121d1831e68803d656f4e1632e72047faae731f3f7dd042b6efb7d6bbd4b908590600401614d52565b6020604051808303816000875af1158015611a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ac39190614d6b565b50611ad283608084901b614ac6565b6000908155600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0064ffffffffff421661010002167fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000009091161760021790556040517f592e67f0ea96f60b5b007072427213c8dd69b145824051a5d8ac4bef38c809cd9190a1505050565b611824338686868686612b72565b7f000000000000000000000000e867928874439b6c48fb42e908ba0519f287932a6001600160a01b0316630ef240a06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bef9190614b40565b6001600160a01b0316336001600160a01b031614611c39576040517fc103f65e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60045460009064ffffffffff7001000000000000000000000000000000008204811691611c82916b01000000000000000000000082048116916601000000000000900416614d84565b611c8c9190614d84565b64ffffffffff16905080421080611cae57506249d400611cac8242614be8565b105b15611ce5576040517f78a931db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561182457611d22848483818110611d0557611d05614ad9565b905060800201803603810190611d1b9190614d36565b3087613185565b611d2b81614b08565b9050611ce8565b367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c6040517f6352211e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b039190911690636352211e90602401602060405180830381865afa158015611dbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611de39190614b40565b6001600160a01b0316336001600160a01b031614611e2d576040517f36b57cf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e35612759565b6040517fdd287b702179a5c0cb1da128f0c74f3d92185d10282e995ed8ad9285d24c749390600090a1565b336001600160a01b03871614801590611e9d57506001600160a01b038616600090815260026020908152604080832033845290915290205460ff16155b15611ed4576040517f3d83866f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611edf856132fa565b90506000611eec856132fa565b9050611f32338989858589898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506114de92505050565b6001600160a01b038816600090815260016020908152604080832089845290915281208054879290611f65908490614be8565b90915550506001600160a01b038716600090815260016020908152604080832089845290915281208054879290611f9d908490614ac6565b909155505060408051878152602081018790526001600160a01b03808a1692908b169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46001600160a01b0387163b156120b8576040517ff23a6e6100000000000000000000000000000000000000000000000000000000808252906001600160a01b0389169063f23a6e619061204e9033908d908c908c908c908c90600401614da9565b602060405180830381865afa15801561206b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061208f9190614cfc565b7fffffffff000000000000000000000000000000000000000000000000000000001614156120c4565b6001600160a01b038716155b156120fb576040517fe704847100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f150b7a0200000000000000000000000000000000000000000000000000000000148061219857507fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e000000000000000000000000000000000000000000000000000000000145b80610b1457507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610b14565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316148061227b57507fd9b67a26000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b80610b145750507fffffffff00000000000000000000000000000000000000000000000000000000167f0e89341c000000000000000000000000000000000000000000000000000000001490565b60006122d4846132fa565b905060006122e1846132fa565b90506001600160a01b038616600090815260016020908152604080832088845290915281208054869290612316908490614ac6565b909155505060408051868152602081018690526001600160a01b0388169160009133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4856001600160a01b03163b6000036123bb576001600160a01b0386166123b6576040517fe704847100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114de565b6040517ff23a6e610000000000000000000000000000000000000000000000000000000081526001600160a01b0387169063f23a6e61906124099033906000908a908a908a90600401614dee565b602060405180830381865afa925050508015612442575060408051601f3d908101601f1916820190925261243f91810190614cfc565b60015b612522576040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f4e2312e00000000000000000000000000000000000000000000000000000000060048201526001600160a01b038716906301ffc9a790602401602060405180830381865afa9250505080156124df575060408051601f3d908101601f191682019092526124dc91810190614e26565b60015b156123b657801561251c576040517fe704847100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506114de565b7fffffffff0000000000000000000000000000000000000000000000000000000081167ff23a6e61000000000000000000000000000000000000000000000000000000001461259d576040517fe704847100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050565b600081516000036125b957506000919050565b610b146125c583613341565b6040516020016125d59190614e43565b604051602081830303815290604052805190602001207f03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b6060600080845190506000845190508188888151811061263257612632614ad9565b60200260200101818152505060005b828110156126d657600087828151811061265d5761265d614ad9565b60200260200101519050806000036126a9576040517f972c8031000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b808a8a6001019a508a815181106126c2576126c2614ad9565b602090810291909101015250600101612641565b50808888600101985088815181106126f0576126f0614ad9565b60200260200101818152505060005b8181101561274c5785818151811061271957612719614ad9565b602002602001015189896001019950898151811061273957612739614ad9565b60209081029190910101526001016126ff565b5096979596505050505050565b600060045460ff166002811115612772576127726149b6565b146127a9576040517fab8bbfcb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556127dc613400565b565b6127e78161346e565b6127f58160e00151426136cf565b64ffffffffff90811660e08301819052600480546101008501516101208601516101408701517fffffffffffffffffffffffffffffffff00000000000000000000ffffffffffff90931666010000000000009095027fffffffffffffffffffffffffffffffff0000000000ffffffffffffffffffffff16949094176b01000000000000000000000091861691909102177fffffffffffffffffff00000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000093909416929092027fffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffffff1692909217750100000000000000000000000000000000000000000061ffff9092169190910217905560208082015101513490156129cb576020820151516001600160a01b031661295f576040517fb89ca71700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8082602001516020015111156129a1576040517f5471cb3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208083015180519101516129b691906136f5565b60208083015101516129c89082614be8565b90505b7f000000000000000000000000f6a66b137b993a4571329cdc9f2523ac8da016496001600160a01b0316633e3aa6c5827f054b7b08b5389709af79a65b21574231b9adb0c313c1598aac94ee44fe99d2137f026490f901ea8ad5a245d987479919f1d20fbb0c164367e33ef09a9ea4ba8d04612a4687610b9f565b6040518563ffffffff1660e01b8152600401612a6493929190614e9a565b60206040518083038185885af1158015612a82573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612aa79190614d6b565b507ff93b0473b6b241759edb8067d8e2dcd903c30c0fc0e6ddc420c5935a8147883e826000015183602001518460400151856060015186608001518760a001518860c001518960e001518a61010001518b61012001518c6101400151604051612b1a9b9a99989796959493929190614eb9565b60405180910390a15050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900382848201602084013750908101603f01601f1916604052919050565b600885901c60009081526003602052604090205460ff86161c60011615612bc5576040517fa308b6e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612bd961170a36869003860186614d36565b9050612c20838380806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054925061171491508a9050893387612dab565b612c56576040517f7d23b90100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600886901c60009081526003602052604090208054600160ff89161b179055612c8e612c8736869003860186614d36565b3089613185565b7fba1802a545423fb47284e96829dad7921d663eeaf62f97cfe3a152593dd9406f86338984604051612cc3949392919061501d565b60405180910390a150505050505050565b803360005b828110156114de576000612d13868684818110612cf857612cf8614ad9565b905060800201803603810190612d0e9190614d36565b613745565b9050612d3b8382888886818110612d2c57612d2c614ad9565b9050608002016060013561382c565b612d66868684818110612d5057612d50614ad9565b905060800201803603810190612c879190614d36565b50600101612cd9565b60408051808201909152600080825260208201526040518060400160405280612d9784613745565b815260200183606001518152509050919050565b600084848484604051602001612dc49493929190615052565b6040516020818303038152906040528051906020012090505b949350505050565b6000835115612e205760208401845160051b81015b8151841160051b938452815160209485185260406000209390910190808210612dfa5750505b5014919050565b825182518114612e63576040517f899ef10d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612ef357838181518110612e8057612e80614ad9565b602002602001015160016000886001600160a01b03166001600160a01b031681526020019081526020016000206000878481518110612ec157612ec1614ad9565b602002602001015181526020019081526020016000206000828254612ee69190614ac6565b9091555050600101612e66565b50846001600160a01b031660006001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051612f44929190615084565b60405180910390a4846001600160a01b03163b600003612fa3576001600160a01b038516612f9e576040517fe704847100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611824565b6040517fbc197c810000000000000000000000000000000000000000000000000000000081526001600160a01b0386169063bc197c8190612ff19033906000908990899089906004016150a9565b602060405180830381865afa92505050801561302a575060408051601f3d908101601f1916820190925261302791810190614cfc565b60015b61310a576040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f4e2312e00000000000000000000000000000000000000000000000000000000060048201526001600160a01b038616906301ffc9a790602401602060405180830381865afa9250505080156130c7575060408051601f3d908101601f191682019092526130c491810190614e26565b60015b15612f9e578015613104576040517fe704847100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611824565b7fffffffff0000000000000000000000000000000000000000000000000000000081167fbc197c8100000000000000000000000000000000000000000000000000000000146114de576040517fe704847100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008351600381111561319a5761319a6149b6565b036131f857604083015160208401516001600160a01b031617156131ea576040517f2de52bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b9a8184606001516136f5565b60018351600381111561320d5761320d6149b6565b036132625760408301511561324e576040517f2de52bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b9a8360200151838386606001516138dd565b600283516003811115613277576132776149b6565b0361329557610b9a836020015184604001518484876060015161392a565b6003835160038111156132aa576132aa6149b6565b036132c857610b9a83602001518460400151848487606001516139ef565b6040517f4ed63ade00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051600180825281830190925260609160208083019080368337019050509050818160008151811061333057613330614ad9565b602002602001018181525050919050565b80516060908067ffffffffffffffff81111561335f5761335f613f7e565b6040519080825280602002602001820160405280156133a457816020015b604080518082019091526000808252602082015281526020019060019003908161337d5790505b50915060005b818110156133f9576133d48482815181106133c7576133c7614ad9565b6020026020010151612d6f565b8382815181106133e6576133e6614ad9565b60209081029190910101526001016133aa565b5050919050565b60408051600380825260808201909252600091602082016060803683370190505090507e8af3ea41808c9515720e56add54a2d8008458a8bc5e347b791c6d75cd0e4078160018151811061345657613456614ad9565b60200260200101818152505061346b81613a52565b50565b610e1081610100015164ffffffffff1610156134b6576040517f8b2625cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e1081610120015164ffffffffff1610156134fe576040517fa6314e8e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61014081015161ffff16158061351d5750601981610140015161ffff16115b15613554576040517f51f09de700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408101517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff161580159061358b5750606081015151155b156135c2576040517f1bf0e08400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060a0015151600003613601576040517f870c2a7200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80515115801590613620575080610140015161ffff1681600001515114155b1561346b57805151600114613661576040517fd6a5c38a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80610140015161ffff16816000015160008151811061368257613682614ad9565b60200260200101516060015161369891906150fb565b1561346b576040517fa08d106700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008164ffffffffff168364ffffffffff16116136ec57816136ee565b825b9392505050565b6136fe81613b40565b60008060008060008587612710f1905080610b9a576040517f46fcf95700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808251600381111561375b5761375b6149b6565b036137735781516003811115610b1457610b146149b6565b600182516003811115613788576137886149b6565b036137bb5781516020808401516040516137a393920161514d565b604051602081830303815290604052610b149061518c565b81516020808401516040808601519051613805930160609290921b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000168252601482015260340190565b604051602081830303815290604052805190602001206040516020016137a39291906151ce565b6000613837836132fa565b90506000613844836132fa565b60408051602081019091526000905290506001600160a01b038516600090815260016020908152604080832087845290915281208054859290613888908490614be8565b909155505060408051858152602081018590526000916001600160a01b0388169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050505050565b6138e681613b40565b306001600160a01b0384160361390f5761390a6001600160a01b0385168383613b7a565b613924565b6139246001600160a01b038516848484613c23565b50505050565b80600114613964576040517fe362007300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301528381166024830152604482018690528616906323b872dd906064015b600060405180830381600087803b1580156139d057600080fd5b505af11580156139e4573d6000803e3d6000fd5b505050505050505050565b6139f881613b40565b604080516000815260208101918290527ff242432a000000000000000000000000000000000000000000000000000000009091526001600160a01b0386169063f242432a906139b690869086908990879060248101614dee565b6040517f3e3aa6c50000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000f6a66b137b993a4571329cdc9f2523ac8da016491690633e3aa6c5903490613afd907f054b7b08b5389709af79a65b21574231b9adb0c313c1598aac94ee44fe99d213907f024931ca109ce0ffa87913d91f12d6ac327550c015a573c7b17a187c29ed8c1a908790600401614e9a565b60206040518083038185885af1158015613b1b573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061148a9190614d6b565b8060000361346b576040517fccd1eba200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052610b9a9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613c74565b6040516001600160a01b03808516602483015283166044820152606481018290526139249085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401613bbf565b6000613cc9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613d769092919063ffffffff16565b9050805160001480613cea575080806020019051810190613cea9190614e26565b610b9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016126a0565b6060612ddd848460008585600080866001600160a01b03168587604051613d9d91906151e8565b60006040518083038185875af1925050503d8060008114613dda576040519150601f19603f3d011682016040523d82523d6000602084013e613ddf565b606091505b50915091506117198783838760608315613e74578251600003613e6d576001600160a01b0385163b613e6d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016126a0565b5081612ddd565b612ddd8383815115613e895781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126a09190614451565b6001600160a01b038116811461346b57600080fd5b60008060408385031215613ee557600080fd5b8235613ef081613ebd565b946020939093013593505050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461346b57600080fd5b600060208284031215613f3e57600080fd5b81356136ee81613efe565b600080600060608486031215613f5e57600080fd5b8335613f6981613ebd565b95602085013595506040909401359392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610160810167ffffffffffffffff81118282101715613fd157613fd1613f7e565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561400057614000613f7e565b604052919050565b600067ffffffffffffffff82111561402257614022613f7e565b5060051b60200190565b60006080828403121561403e57600080fd5b6040516080810181811067ffffffffffffffff8211171561406157614061613f7e565b60405290508082356004811061407657600080fd5b8152602083013561408681613ebd565b8060208301525060408301356040820152606083013560608201525092915050565b600082601f8301126140b957600080fd5b813560206140ce6140c983614008565b613fd7565b82815260079290921b840181019181810190868411156140ed57600080fd5b8286015b8481101561411157614103888261402c565b8352918301916080016140f1565b509695505050505050565b60006040828403121561412e57600080fd5b6040516040810181811067ffffffffffffffff8211171561415157614151613f7e565b604052905080823561416281613ebd565b8152602092830135920191909152919050565b80357effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146141a457600080fd5b919050565b600082601f8301126141ba57600080fd5b813560206141ca6140c983614008565b82815260059290921b840181019181810190868411156141e957600080fd5b8286015b8481101561411157803583529183019183016141ed565b803564ffffffffff811681146141a457600080fd5b803561ffff811681146141a457600080fd5b60006020828403121561423d57600080fd5b813567ffffffffffffffff8082111561425557600080fd5b90830190610180828603121561426a57600080fd5b614272613fad565b82358281111561428157600080fd5b61428d878286016140a8565b82525061429d866020850161411c565b60208201526142ae60608401614175565b60408201526080830135828111156142c557600080fd5b6142d1878286016141a9565b60608301525060a0830135828111156142e957600080fd5b6142f5878286016141a9565b60808301525060c08301358281111561430d57600080fd5b614319878286016141a9565b60a08301525060e08301358281111561433157600080fd5b61433d878286016141a9565b60c0830152506101009150614353828401614204565b60e0820152610120614366818501614204565b83830152610140925061437a838501614204565b9082015261438b6101608401614219565b91810191909152949350505050565b600081518084526020808501945080840160005b838110156143ca578151875295820195908201906001016143ae565b509495945050505050565b6020815260006136ee602083018461439a565b6000602082840312156143fa57600080fd5b5035919050565b60005b8381101561441c578181015183820152602001614404565b50506000910152565b6000815180845261443d816020860160208601614401565b601f01601f19169290920160200192915050565b6020815260006136ee6020830184614425565b60008083601f84011261447657600080fd5b50813567ffffffffffffffff81111561448e57600080fd5b6020830191508360208285010111156144a657600080fd5b9250929050565b6000806000806000608086880312156144c557600080fd5b85356144d081613ebd565b945060208601356144e081613ebd565b935060408601359250606086013567ffffffffffffffff81111561450357600080fd5b61450f88828901614464565b969995985093965092949392505050565b60008083601f84011261453257600080fd5b50813567ffffffffffffffff81111561454a57600080fd5b6020830191508360208260051b85010111156144a657600080fd5b60008060008060008060008060a0898b03121561458157600080fd5b883561458c81613ebd565b9750602089013561459c81613ebd565b9650604089013567ffffffffffffffff808211156145b957600080fd5b6145c58c838d01614520565b909850965060608b01359150808211156145de57600080fd5b6145ea8c838d01614520565b909650945060808b013591508082111561460357600080fd5b506146108b828c01614464565b999c989b5096995094979396929594505050565b6000806020838503121561463757600080fd5b823567ffffffffffffffff81111561464e57600080fd5b61465a85828601614464565b90969095509350505050565b60006080828403121561467857600080fd5b50919050565b600080600080600080610100878903121561469857600080fd5b86356146a381613ebd565b955060208701359450604087013593506146c08860608901614666565b925060e087013567ffffffffffffffff8111156146dc57600080fd5b6146e889828a01614520565b979a9699509497509295939492505050565b6000806000806040858703121561471057600080fd5b843567ffffffffffffffff8082111561472857600080fd5b61473488838901614520565b9096509450602087013591508082111561474d57600080fd5b5061475a87828801614520565b95989497509550505050565b60008083601f84011261477857600080fd5b50813567ffffffffffffffff81111561479057600080fd5b6020830191508360208260071b85010111156144a657600080fd5b6000806000604084860312156147c057600080fd5b83356147cb81613ebd565b9250602084013567ffffffffffffffff8111156147e757600080fd5b6147f386828701614766565b9497909650939450505050565b60008060008060006060868803121561481857600080fd5b853561482381613ebd565b9450602086013567ffffffffffffffff8082111561484057600080fd5b61484c89838a01614520565b9096509450604088013591508082111561486557600080fd5b5061450f88828901614520565b801515811461346b57600080fd5b6000806040838503121561489357600080fd5b823561489e81613ebd565b915060208301356148ae81614872565b809150509250929050565b600080602083850312156148cc57600080fd5b823567ffffffffffffffff8111156148e357600080fd5b61465a85828601614766565b60008060008060006080868803121561490757600080fd5b853561491281613ebd565b94506020860135935060408601359250606086013567ffffffffffffffff81111561493c57600080fd5b61450f88828901614520565b6000806040838503121561495b57600080fd5b50508035926020909101359150565b600080600080600060e0868803121561498257600080fd5b853594506020860135935061499a8760408801614666565b925060c086013567ffffffffffffffff81111561493c57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600383106149f9576149f96149b6565b91905290565b60008060408385031215614a1257600080fd5b8235614a1d81613ebd565b915060208301356148ae81613ebd565b60008060008060008060a08789031215614a4657600080fd5b8635614a5181613ebd565b95506020870135614a6181613ebd565b94506040870135935060608701359250608087013567ffffffffffffffff811115614a8b57600080fd5b6146e889828a01614464565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115610b1457610b14614a97565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614b3957614b39614a97565b5060010190565b600060208284031215614b5257600080fd5b81516136ee81613ebd565b600060208284031215614b6f57600080fd5b815167ffffffffffffffff80821115614b8757600080fd5b818401915084601f830112614b9b57600080fd5b815181811115614bad57614bad613f7e565b614bc06020601f19601f84011601613fd7565b9150808252856020828501011115614bd757600080fd5b61160b816020840160208601614401565b81810381811115610b1457610b14614a97565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115614c2d57600080fd5b8260051b80836020870137939093016020019392505050565b604081526000614c5a604083018688614bfb565b8281036020840152611719818587614bfb565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b60006001600160a01b03808b168352808a1660208401525060a06040830152614cc560a08301888a614bfb565b8281036060840152614cd8818789614bfb565b90508281036080840152614ced818587614c6d565b9b9a5050505050505050505050565b600060208284031215614d0e57600080fd5b81516136ee81613efe565b600060208284031215614d2b57600080fd5b81356136ee81613ebd565b600060808284031215614d4857600080fd5b6136ee838361402c565b828152604060208201526000612ddd604083018461439a565b600060208284031215614d7d57600080fd5b5051919050565b64ffffffffff818116838216019080821115614da257614da2614a97565b5092915050565b60006001600160a01b03808916835280881660208401525085604083015284606083015260a06080830152614de260a083018486614c6d565b98975050505050505050565b60006001600160a01b03808816835280871660208401525084604083015283606083015260a0608083015261171960a0830184614425565b600060208284031215614e3857600080fd5b81516136ee81614872565b602080825282518282018190526000919060409081850190868401855b82811015614e8d57614e7d84835180518252602090810151910152565b9284019290850190600101614e60565b5091979650505050505050565b838152826020820152606060408201526000610f82606083018461439a565b6101808152600061018082018d518082526101a08401915060208f0160005b82811015614f37578151805160048110614ef457614ef46149b6565b808652506001600160a01b036020820151166020860152604081015160408601526060810151606086015250608084019350602082019150600181019050614ed8565b505050614f5a602084018e80516001600160a01b03168252602090810151910152565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8c1660608401528281036080840152614f93818c61439a565b905082810360a0840152614fa7818b61439a565b905082810360c0840152614fbb818a61439a565b905082810360e0840152614fcf818961439a565b915050614fe661010083018764ffffffffff169052565b64ffffffffff851661012083015264ffffffffff841661014083015261ffff83166101608301529c9b505050505050505050505050565b8481526001600160a01b0384811660208301528316604082015260a08101610f82606083018480518252602090810151910152565b84815260208082018590526001600160a01b038416604083015282516060830152820151608082015260a08101610f82565b604081526000615097604083018561439a565b8281036020840152610f82818561439a565b60006001600160a01b03808816835280871660208401525060a060408301526150d560a083018661439a565b82810360608401526150e7818661439a565b90508281036080840152614de28185614425565b600082615131577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b60048110615146576151466149b6565b60f81b9052565b6151578184615136565b60609190911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166001820152601501919050565b80516020808301519190811015614678577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60209190910360031b1b16919050565b6151d88184615136565b6001810191909152602101919050565b600082516151fa818460208701614401565b919091019291505056fea164736f6c6343000815000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0091fa917c9800be6c78603a53148e005b5482c5fb42350b775c2419031e34a2000000000000000000000000000000002c93cad6f9cfd00c603aef62458d8a48000000000000000000000000c662c410c0ecf747543f5ba90660f6abebd9c8c4000000000000000000000000f6a66b137b993a4571329cdc9f2523ac8da01649054b7b08b5389709af79a65b21574231b9adb0c313c1598aac94ee44fe99d21305f2121d1831e68803d656f4e1632e72047faae731f3f7dd042b6efb7d6bbd4b000000000000000000000000e867928874439b6c48fb42e908ba0519f287932a
-----Decoded View---------------
Arg [0] : _classHash (uint256): 257922183293084640967515771181938191608597406937141200910239598718010406050
Arg [1] : _propHouse (address): 0x000000002C93CAD6F9cFD00C603aEf62458d8A48
Arg [2] : _starknet (address): 0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4
Arg [3] : _messenger (address): 0xf6A66b137B993A4571329cdC9F2523AC8da01649
Arg [4] : _roundFactory (uint256): 2394926922339743907388926601851760374990396628270308606696456930994331177491
Arg [5] : _executionRelayer (uint256): 2689266248413419407545168950331895718713925766892610807350454942230433742155
Arg [6] : _manager (address): 0xE867928874439b6C48fB42e908BA0519f287932A
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0091fa917c9800be6c78603a53148e005b5482c5fb42350b775c2419031e34a2
Arg [1] : 000000000000000000000000000000002c93cad6f9cfd00c603aef62458d8a48
Arg [2] : 000000000000000000000000c662c410c0ecf747543f5ba90660f6abebd9c8c4
Arg [3] : 000000000000000000000000f6a66b137b993a4571329cdc9f2523ac8da01649
Arg [4] : 054b7b08b5389709af79a65b21574231b9adb0c313c1598aac94ee44fe99d213
Arg [5] : 05f2121d1831e68803d656f4e1632e72047faae731f3f7dd042b6efb7d6bbd4b
Arg [6] : 000000000000000000000000e867928874439b6c48fb42e908ba0519f287932a
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.