Source Code
Latest 25 from a total of 1,943 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Claim | 24491779 | 15 days ago | IN | 0 ETH | 0.00002658 | ||||
| Claim | 24398956 | 28 days ago | IN | 0 ETH | 0.00027841 | ||||
| Claim | 23765847 | 116 days ago | IN | 0 ETH | 0.00015672 | ||||
| Claim | 23309841 | 180 days ago | IN | 0 ETH | 0.00006706 | ||||
| Claim | 23001180 | 223 days ago | IN | 0 ETH | 0.0001317 | ||||
| Claim | 22774890 | 255 days ago | IN | 0 ETH | 0.00091025 | ||||
| Claim | 22480229 | 296 days ago | IN | 0 ETH | 0.0001512 | ||||
| Claim | 22352152 | 314 days ago | IN | 0 ETH | 0.00009735 | ||||
| Claim | 22352139 | 314 days ago | IN | 0 ETH | 0.00009438 | ||||
| Claim | 22146288 | 343 days ago | IN | 0 ETH | 0.00016356 | ||||
| Claim | 22145385 | 343 days ago | IN | 0 ETH | 0.00006329 | ||||
| Claim | 22145379 | 343 days ago | IN | 0 ETH | 0.00006603 | ||||
| Claim | 22071163 | 353 days ago | IN | 0 ETH | 0.00006974 | ||||
| Claim | 22071160 | 353 days ago | IN | 0 ETH | 0.00006676 | ||||
| Claim | 22071157 | 353 days ago | IN | 0 ETH | 0.00007038 | ||||
| Claim | 22071150 | 353 days ago | IN | 0 ETH | 0.00004608 | ||||
| Claim | 22071149 | 353 days ago | IN | 0 ETH | 0.00007087 | ||||
| Claim | 22071146 | 353 days ago | IN | 0 ETH | 0.00004451 | ||||
| Claim | 22071145 | 353 days ago | IN | 0 ETH | 0.00007036 | ||||
| Claim | 22055570 | 356 days ago | IN | 0 ETH | 0.00005853 | ||||
| Claim | 22051696 | 356 days ago | IN | 0 ETH | 0.00007012 | ||||
| Claim | 22049791 | 356 days ago | IN | 0 ETH | 0.00007099 | ||||
| Claim | 22049769 | 356 days ago | IN | 0 ETH | 0.00007181 | ||||
| Claim | 22047849 | 357 days ago | IN | 0 ETH | 0.0000778 | ||||
| Claim | 22038745 | 358 days ago | IN | 0 ETH | 0.00014306 |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0xADABa1d9...989C9c68b The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
Presale
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: None
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol";
import {IVRFCoordinatorV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol";
import "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol";
import './interfaces/IDelegateRegistry.sol';
import './interfaces/IDelegationRegistry.sol';
contract Presale is VRFConsumerBaseV2, Ownable {
// Maintains various token balances for users
struct userInfo {
uint256 KOLPurchased;
uint256 superKOLPurchased;
uint256 totalPurchased;
uint256 rafflesWon;
uint256 rafflesPurchased;
uint256 amountClaimed;
}
// Each user's info
mapping(address => userInfo) public usersInfo;
// Purchased per NFT ID
mapping(uint256 => uint256) public phaseOnePurchased;
// Phase 2 whitelists
mapping(address => bool) public KOLWhitelist;
mapping(address => bool) public superKOLWhitelist;
// List of users who have entered the raffle - one entry per ticket purchased
address[] public raffleEntries;
// Total tokens that can be purchased in phase 1
uint256 public phaseOneSupply = 33000000 * 10**18;
uint256 public phaseOnePurchasedTotal;
// Total tokens that can be purchased in phase 2 - rolls over from phase 1
uint256 public phaseTwoSupply = 132000000 * 10**18;
uint256 public KOLPurchasedTotal;
uint256 public superKOLPurchasedTotal;
// Total tokens that can be purchased in phase 3 - rolls over from phase 1 and 2
uint256 public phaseThreeSupply;
uint256 public phaseThreePurchasedTotal;
// Tokens purchased across all phases
uint256 public totalTokensPurchased;
// ETH collected in phase 1 and 2 - allows for withdrawing during phase 3
uint256 public phaseOneTwoETH;
// Used to maintain the contract's current phase
uint256 public launchTime;
bool public claimEnabled;
uint256 public claimTime;
// Limit of number of tokens that can be purchased by each user in each phase
uint256 public phaseOneCap;
uint256 public KOLCap;
uint256 public superKOLCap;
// Cost per entry and winning token amount for raffles
uint256 public rafflePrice;
uint256 public raffleAmount;
uint256 public raffleLimit = 20;
// Tokens per ETH for each phase
uint256 public phaseOneRatio;
uint256 public phaseTwoRatio;
// Used to calculate each user's vested amount when claiming
uint256 public vestingPeriod = 14 days;
uint256 public cliffDuration = 12 hours;
uint256 public initialUnlockPercent = 75;
// Used to rollover tokens between phases
bool public phaseOneEnded;
bool public phaseTwoEnded;
// Used to enable users to refund losing tickets
bool public refundsEnabled;
// Vars required for Chainlink VRF
uint256 public subscriptionId;
IVRFCoordinatorV2Plus public coordinator;
bytes32 public keyHash = 0x3fd2fec10d06ee8f65e7f2e95f5c56511359ece3f33960ad8a866ae24a8ff10b;
uint32 public callbackGasLimit = 15000000;
uint16 public requestConfirmations = 3;
// NFTs required for phase one purchase
IERC721 public nftAddress;
// Tokens being bought in each phase
IERC20 public tokenAddress;
// Delegate registries to support delegating NFTs
IDelegateRegistry public immutable delegateRegistryV2 =
IDelegateRegistry(0x00000000000000447e69651d841bD8D104Bed493);
IDelegationRegistry public immutable delegateRegistryV1 =
IDelegationRegistry(0x00000000000076A84feF008CDAbe6409d2FE638B);
error OutsideTimeWindow();
error ExceedsPurchaseCap();
error NFTOwner();
error Whitelist();
error IncorrectPrice();
error NotEnabled();
error AlreadyLaunched();
// Creates the presale and sets the required values
constructor(address _nftAddress, address _tokenAddress, address _vrfCoordinator, uint256 _subscriptionId) VRFConsumerBaseV2(_vrfCoordinator) Ownable(msg.sender) {
coordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);
subscriptionId = _subscriptionId;
nftAddress = IERC721(_nftAddress);
tokenAddress = IERC20(_tokenAddress);
}
// Begins the presale process and sets prices and caps
function launch(uint256 _phaseOneRatio, uint256 _phaseTwoRatio, uint256 _phaseOneCap, uint256 _KOLCap, uint256 _superKOLCap, uint256 _rafflePrice, uint256 _raffleAmount) external onlyOwner {
if(launchTime != 0) { // 2 hours phase one + 2 hours phase 2 + 24 hours phase 3
revert AlreadyLaunched();
}
launchTime = block.timestamp;
phaseOneRatio = _phaseOneRatio;
phaseTwoRatio = _phaseTwoRatio;
phaseOneCap = _phaseOneCap;
KOLCap = _KOLCap;
superKOLCap = _superKOLCap;
rafflePrice = _rafflePrice;
raffleAmount = _raffleAmount;
}
// Allows users to refund their losing tickets - no draws must happen after
function enableRefunds() external onlyOwner {
refundsEnabled = true;
}
// Allows users to claim
function enableClaims() external onlyOwner {
// Ensures phase three has ended
if(block.timestamp < launchTime + 100800) { // 2 hours phase one + 2 hours phase 2 + 24 hours phase 3
revert OutsideTimeWindow();
}
claimEnabled = true;
claimTime = block.timestamp;
// Transfers the total required tokens to the contract
tokenAddress.transferFrom(msg.sender, address(this), totalTokensPurchased);
}
// Allows an NFT holder to purchase tokens
function phaseOnePurchase(uint256[] calldata nftIds, uint256[] calldata amounts) external payable {
if(block.timestamp > launchTime + 7200) {
// Two hours from launch to purchase in phase one
revert OutsideTimeWindow();
}
uint256 totalAmount;
for(uint256 i = 0; i < amounts.length; i++) {
totalAmount += amounts[i];
}
if(msg.value != totalAmount) {
revert IncorrectPrice();
}
for(uint256 i = 0; i < nftIds.length; i++) {
_phaseOnePurchase(nftIds[i], amounts[i]);
}
phaseOneTwoETH += msg.value;
}
function _phaseOnePurchase(uint256 nftId, uint256 amount) internal {
// User must own the specified NFT or be a delegate
if(!_verifyTokenOwner(nftId)) {
revert NFTOwner();
}
// Convert ETH to tokens
uint256 purchasedAmount = amount * phaseOneRatio;
if(phaseOnePurchased[nftId] + purchasedAmount > phaseOneCap) {
revert ExceedsPurchaseCap();
}
// Check we dont exceed the phase one supply
if(phaseOnePurchasedTotal + purchasedAmount > phaseOneSupply) {
revert ExceedsPurchaseCap();
}
// Increment all associated values
usersInfo[msg.sender].totalPurchased += purchasedAmount;
phaseOnePurchased[nftId] += purchasedAmount;
phaseOnePurchasedTotal += purchasedAmount;
totalTokensPurchased += purchasedAmount;
}
// Allows whitelisted users to purchase tokens after phase one ends
function phaseTwoKOLPurchase() external payable {
if(block.timestamp < launchTime + 7200 || block.timestamp > launchTime + 14400) {
// Phase two starts two hours after launch and lasts another two hours
revert OutsideTimeWindow();
}
// Carries over any not purchased phase one tokens - should only trigger after phase one due to above time constraints
if(!phaseOneEnded) {
phaseTwoSupply += (phaseOneSupply - phaseOnePurchasedTotal);
phaseOneEnded = true;
}
// User must be whitelisted
if(KOLWhitelist[msg.sender] == false) {
revert Whitelist();
}
// Convert ETH to tokens
uint256 purchasedAmount = msg.value * phaseTwoRatio;
if(usersInfo[msg.sender].KOLPurchased + purchasedAmount > KOLCap) {
revert ExceedsPurchaseCap();
}
// Check total phase two purchased tokens dont exceed phase two supply
if(KOLPurchasedTotal + superKOLPurchasedTotal + purchasedAmount > phaseTwoSupply) {
revert ExceedsPurchaseCap();
}
// Increment all associated values
usersInfo[msg.sender].KOLPurchased += purchasedAmount;
usersInfo[msg.sender].totalPurchased += purchasedAmount;
KOLPurchasedTotal += purchasedAmount;
totalTokensPurchased += purchasedAmount;
phaseOneTwoETH += msg.value;
}
// Allows whitelisted users to purchase tokens after phase one ends
function phaseTwoSuperKOLPurchase() external payable {
if(block.timestamp < launchTime + 7200 || block.timestamp > launchTime + 14400) {
// Phase two starts two hours after launch and lasts another two hours
revert OutsideTimeWindow();
}
// Carries over any not purchased phase one tokens - should only trigger after phase one due to above time constraints
if(!phaseOneEnded) {
phaseTwoSupply += (phaseOneSupply - phaseOnePurchasedTotal);
phaseOneEnded = true;
}
// User must be whitelisted
if(superKOLWhitelist[msg.sender] == false) {
revert Whitelist();
}
// Convert ETH to tokens
uint256 purchasedAmount = msg.value * phaseTwoRatio;
if(usersInfo[msg.sender].superKOLPurchased + purchasedAmount > superKOLCap) {
revert ExceedsPurchaseCap();
}
// Check total phase two purchased tokens dont exceed phase two supply
if(KOLPurchasedTotal + superKOLPurchasedTotal + purchasedAmount > phaseTwoSupply) {
revert ExceedsPurchaseCap();
}
// Increment all associated values
usersInfo[msg.sender].superKOLPurchased += purchasedAmount;
usersInfo[msg.sender].totalPurchased += purchasedAmount;
superKOLPurchasedTotal += purchasedAmount;
totalTokensPurchased += purchasedAmount;
phaseOneTwoETH += msg.value;
}
// Allows any users to purchase a raffle ticket after phase two ends
function phaseThreePurchase(uint256 numTickets) external payable {
if(block.timestamp < launchTime + 14400 || block.timestamp > launchTime + 100800) {
// Phase three starts four hours after launch and lasts another 24 hours
revert OutsideTimeWindow();
}
// Carries over any not purchased phase two tokens - should only trigger after phase one due to above time constraints
if(!phaseTwoEnded) {
phaseThreeSupply += (phaseTwoSupply - (KOLPurchasedTotal + superKOLPurchasedTotal));
phaseTwoEnded = true;
}
// Ensure user provided correct amount of ETH
if(msg.value != rafflePrice * numTickets) {
revert IncorrectPrice();
}
if(usersInfo[msg.sender].rafflesPurchased + numTickets > raffleLimit) {
revert ExceedsPurchaseCap();
}
// Credit the user with the number of tickets
usersInfo[msg.sender].rafflesPurchased += numTickets;
for(uint256 i = 0; i < numTickets; i++) {
// Add user to the actual entries
raffleEntries.push(msg.sender);
}
}
// Allows the owner to draw the specified number of winners
function draw(uint256 numDraws) external onlyOwner() {
if(block.timestamp < launchTime + 100800) {
// Raffle can be drawn after phase three ends
revert OutsideTimeWindow();
}
// Check total phase three purchased tokens dont exceed phase three supply
if((numDraws * raffleAmount) + phaseThreePurchasedTotal > phaseThreeSupply) {
revert ExceedsPurchaseCap();
}
// Request random values from Chainlink VRF provider
requestRandomWords(callbackGasLimit, requestConfirmations, uint32(numDraws));
}
// Sends the request for random values to Chainlink VRF provider
function requestRandomWords(
uint32 _callbackGasLimit,
uint16 _requestConfirmations,
uint32 _numWords
) internal {
bytes memory args = VRFV2PlusClient._argsToBytes(
VRFV2PlusClient.ExtraArgsV1({nativePayment: false})
);
VRFV2PlusClient.RandomWordsRequest memory request = VRFV2PlusClient
.RandomWordsRequest({
keyHash: keyHash,
subId: subscriptionId,
requestConfirmations: _requestConfirmations,
callbackGasLimit: _callbackGasLimit,
numWords: _numWords,
extraArgs: args
});
coordinator.requestRandomWords(request);
}
// Called by Chainklink VRF provider to provide requested random values
function fulfillRandomWords(
uint256 _requestId,
uint256[] memory randomWords
) internal override {
selectWinners(randomWords);
}
// Used to select winners based on provided random values
function selectWinners(uint256[] memory randomness) internal {
// Selects the correct number of winners
for (uint256 i; i < randomness.length; i++) {
// Find the right winner from the entries
uint256 winnerIndex = randomness[i] % raffleEntries.length;
address winner = raffleEntries[winnerIndex];
// Credit the user with the amount and the win
usersInfo[winner].totalPurchased += raffleAmount;
totalTokensPurchased += raffleAmount;
phaseThreePurchasedTotal += raffleAmount;
usersInfo[winner].rafflesWon += 1;
// Remove the user from the entries
raffleEntries[winnerIndex] = raffleEntries[raffleEntries.length-1];
raffleEntries.pop();
}
}
// Allows the users to claim tokens once enabled
function claim() external {
if(!claimEnabled) {
revert NotEnabled();
}
// Claimable tokens vest over time
uint256 vested = vestedAmount(usersInfo[msg.sender].totalPurchased);
// Calculate claimable, update claimed amount, send user their tokens
uint256 claimable = vested - usersInfo[msg.sender].amountClaimed;
usersInfo[msg.sender].amountClaimed = vested;
tokenAddress.transfer(msg.sender, claimable);
}
// Calculates the amount of vested tokens from the time claiming was enabled
function vestedAmount(uint256 totalPurchased) public view returns (uint256) {
if(claimTime == 0) {
return 0;
}
uint256 elapsedTime = block.timestamp - claimTime;
uint256 initalUnlockAmount = (totalPurchased * initialUnlockPercent) / 100;
if (elapsedTime < cliffDuration) {
// Before 12 hours, only the initial 75% is available
return initalUnlockAmount;
} else if (elapsedTime >= cliffDuration + vestingPeriod) {
// After the vesting period, 100% is vested
return totalPurchased;
} else { // calculate vested amount
elapsedTime = block.timestamp - (claimTime + cliffDuration); // vesting starts from cliff duration
uint256 nonInitialAmount = (totalPurchased * (100 - initialUnlockPercent)) / 100; // amount that vests after initial unlock
uint256 vestedAmount = (nonInitialAmount * elapsedTime) / vestingPeriod; // amount of non-initial that has vested
return initalUnlockAmount + vestedAmount; // initial unlock + vested amount
}
}
// Allows users to refund raffle entries that were not selected
function refundRaffle() external {
if(!refundsEnabled) {
// Cannot claim until team is done drawing winners
revert NotEnabled();
}
uint256 ticketsRefunded = usersInfo[msg.sender].rafflesPurchased - usersInfo[msg.sender].rafflesWon;
// Users receive a 97.5% refund
uint256 refundAmount = (ticketsRefunded * rafflePrice * 975) / 1000;
usersInfo[msg.sender].rafflesPurchased = 0; // will cause revert if they call this again
msg.sender.call{value: refundAmount}("");
}
// Allows owner to add users to the KOL Whitelist
function setKOLWhitelist(address[] memory users, bool value) external onlyOwner {
for(uint256 i = 0; i < users.length; i++) {
KOLWhitelist[users[i]] = value;
}
}
// Allows owner to add users to the Super KOL Whitelist
function setSuperKOLWhitelist(address[] memory users, bool value) external onlyOwner {
for(uint256 i = 0; i < users.length; i++) {
superKOLWhitelist[users[i]] = value;
}
}
// Allows the owner to set the number of tokens won per raffle
function setRaffleAmount(uint256 amount) external onlyOwner {
raffleAmount = amount;
}
// Allows the owner to set the price of each raffle entry
function setRafflePrice(uint256 amount) external onlyOwner {
if(block.timestamp > launchTime + 14400) {
// Can only change the price before raffles are purchased
revert OutsideTimeWindow();
}
rafflePrice = amount;
}
// Sets the Chainlink VRF gas callback limit
function setGasLimit(uint256 limit) external onlyOwner {
callbackGasLimit = uint32(limit);
}
// Sets the Chainlink VRF gas callback limit
function setSubId(uint256 id) external onlyOwner {
subscriptionId = id;
}
// Sets the Chainlink keyhash
function setKeyHash(bytes32 newHash) external onlyOwner {
keyHash = newHash;
}
// Withdraws all ETH from the contract - should not be used until users are given sufficient time to refund their tickets
function withdrawETH() external onlyOwner {
msg.sender.call{value: address(this).balance}(""); // This will withdraw all ETH including potential ETH for refunds
}
// Withdraws the ETH collected in phases one and two - should only be called after phase 2 and before calling withdrawETHNoRefunds
function withdrawETHNoRaffle() external onlyOwner {
uint256 amount = phaseOneTwoETH;
phaseOneTwoETH = 0;
msg.sender.call{value: amount}("");
}
// Withdraws all ETH not allocated to refunds
function withdrawETHNoRefunds() external onlyOwner {
if(block.timestamp < launchTime + 100800 ) {
revert OutsideTimeWindow();
}
uint256 totalRefunds = raffleEntries.length; // all winners should be popped from the array by now
uint256 refundAmount = (totalRefunds * rafflePrice * 975) / 1000;
msg.sender.call{value: address(this).balance - refundAmount}("");
}
// Withdraws all of a specified token to a contract - should only be used on the presale token in case of emergency
function emergencyWithdrawTokens(address token) external onlyOwner {
IERC20(token).transfer(msg.sender, IERC20(token).balanceOf(address(this)));
}
receive() external payable {}
function _verifyTokenOwner(uint256 NFTId) internal view returns(bool) {
address NFTOwner = nftAddress.ownerOf(NFTId);
// check sender is owner
if (NFTOwner == msg.sender) return true;
// check with delegate registry v2
if (
delegateRegistryV2.checkDelegateForERC721(
msg.sender,
NFTOwner,
address(nftAddress),
NFTId,
''
)
) return true;
// check with delegate registry v1
if (
delegateRegistryV1.checkDelegateForToken(
msg.sender,
NFTOwner,
address(nftAddress),
NFTId
)
) return true;
// false if not owner or delegate
return false;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol";
import {IVRFSubscriptionV2Plus} from "./IVRFSubscriptionV2Plus.sol";
// Interface that enables consumers of VRFCoordinatorV2Plus to be future-proof for upgrades
// This interface is supported by subsequent versions of VRFCoordinatorV2Plus
interface IVRFCoordinatorV2Plus is IVRFSubscriptionV2Plus {
/**
* @notice Request a set of random words.
* @param req - a struct containing following fields for randomness request:
* keyHash - Corresponds to a particular oracle job which uses
* that key for generating the VRF proof. Different keyHash's have different gas price
* ceilings, so you can select a specific one to bound your maximum per request cost.
* subId - The ID of the VRF subscription. Must be funded
* with the minimum subscription balance required for the selected keyHash.
* requestConfirmations - How many blocks you'd like the
* oracle to wait before responding to the request. See SECURITY CONSIDERATIONS
* for why you may want to request more. The acceptable range is
* [minimumRequestBlockConfirmations, 200].
* callbackGasLimit - How much gas you'd like to receive in your
* fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords
* may be slightly less than this amount because of gas used calling the function
* (argument decoding etc.), so you may need to request slightly more than you expect
* to have inside fulfillRandomWords. The acceptable range is
* [0, maxGasLimit]
* numWords - The number of uint256 random values you'd like to receive
* in your fulfillRandomWords callback. Note these numbers are expanded in a
* secure way by the VRFCoordinator from a single random value supplied by the oracle.
* extraArgs - abi-encoded extra args
* @return requestId - A unique identifier of the request. Can be used to match
* a request to a response in fulfillRandomWords.
*/
function requestRandomWords(VRFV2PlusClient.RandomWordsRequest calldata req) external returns (uint256 requestId);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @notice The IVRFSubscriptionV2Plus interface defines the subscription
/// @notice related methods implemented by the V2Plus coordinator.
interface IVRFSubscriptionV2Plus {
/**
* @notice Add a consumer to a VRF subscription.
* @param subId - ID of the subscription
* @param consumer - New consumer which can use the subscription
*/
function addConsumer(uint256 subId, address consumer) external;
/**
* @notice Remove a consumer from a VRF subscription.
* @param subId - ID of the subscription
* @param consumer - Consumer to remove from the subscription
*/
function removeConsumer(uint256 subId, address consumer) external;
/**
* @notice Cancel a subscription
* @param subId - ID of the subscription
* @param to - Where to send the remaining LINK to
*/
function cancelSubscription(uint256 subId, address to) external;
/**
* @notice Accept subscription owner transfer.
* @param subId - ID of the subscription
* @dev will revert if original owner of subId has
* not requested that msg.sender become the new owner.
*/
function acceptSubscriptionOwnerTransfer(uint256 subId) external;
/**
* @notice Request subscription owner transfer.
* @param subId - ID of the subscription
* @param newOwner - proposed new owner of the subscription
*/
function requestSubscriptionOwnerTransfer(uint256 subId, address newOwner) external;
/**
* @notice Create a VRF subscription.
* @return subId - A unique subscription id.
* @dev You can manage the consumer set dynamically with addConsumer/removeConsumer.
* @dev Note to fund the subscription with LINK, use transferAndCall. For example
* @dev LINKTOKEN.transferAndCall(
* @dev address(COORDINATOR),
* @dev amount,
* @dev abi.encode(subId));
* @dev Note to fund the subscription with Native, use fundSubscriptionWithNative. Be sure
* @dev to send Native with the call, for example:
* @dev COORDINATOR.fundSubscriptionWithNative{value: amount}(subId);
*/
function createSubscription() external returns (uint256 subId);
/**
* @notice Get a VRF subscription.
* @param subId - ID of the subscription
* @return balance - LINK balance of the subscription in juels.
* @return nativeBalance - native balance of the subscription in wei.
* @return reqCount - Requests count of subscription.
* @return owner - owner of the subscription.
* @return consumers - list of consumer address which are able to use this subscription.
*/
function getSubscription(
uint256 subId
)
external
view
returns (uint96 balance, uint96 nativeBalance, uint64 reqCount, address owner, address[] memory consumers);
/*
* @notice Check to see if there exists a request commitment consumers
* for all consumers and keyhashes for a given sub.
* @param subId - ID of the subscription
* @return true if there exists at least one unfulfilled request for the subscription, false
* otherwise.
*/
function pendingRequestExists(uint256 subId) external view returns (bool);
/**
* @notice Paginate through all active VRF subscriptions.
* @param startIndex index of the subscription to start from
* @param maxCount maximum number of subscriptions to return, 0 to return all
* @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one
* @dev should consider keeping the blockheight constant to ensure a holistic picture of the contract state
*/
function getActiveSubscriptionIds(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory);
/**
* @notice Fund a subscription with native.
* @param subId - ID of the subscription
* @notice This method expects msg.value to be greater than or equal to 0.
*/
function fundSubscriptionWithNative(uint256 subId) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
// End consumer library.
library VRFV2PlusClient {
// extraArgs will evolve to support new features
bytes4 public constant EXTRA_ARGS_V1_TAG = bytes4(keccak256("VRF ExtraArgsV1"));
struct ExtraArgsV1 {
bool nativePayment;
}
struct RandomWordsRequest {
bytes32 keyHash;
uint256 subId;
uint16 requestConfirmations;
uint32 callbackGasLimit;
uint32 numWords;
bytes extraArgs;
}
function _argsToBytes(ExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) {
return abi.encodeWithSelector(EXTRA_ARGS_V1_TAG, extraArgs);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/** ****************************************************************************
* @notice Interface for contracts using VRF randomness
* *****************************************************************************
* @dev PURPOSE
*
* @dev Reggie the Random Oracle (not his real job) wants to provide randomness
* @dev to Vera the verifier in such a way that Vera can be sure he's not
* @dev making his output up to suit himself. Reggie provides Vera a public key
* @dev to which he knows the secret key. Each time Vera provides a seed to
* @dev Reggie, he gives back a value which is computed completely
* @dev deterministically from the seed and the secret key.
*
* @dev Reggie provides a proof by which Vera can verify that the output was
* @dev correctly computed once Reggie tells it to her, but without that proof,
* @dev the output is indistinguishable to her from a uniform random sample
* @dev from the output space.
*
* @dev The purpose of this contract is to make it easy for unrelated contracts
* @dev to talk to Vera the verifier about the work Reggie is doing, to provide
* @dev simple access to a verifiable source of randomness. It ensures 2 things:
* @dev 1. The fulfillment came from the VRFCoordinator
* @dev 2. The consumer contract implements fulfillRandomWords.
* *****************************************************************************
* @dev USAGE
*
* @dev Calling contracts must inherit from VRFConsumerBase, and can
* @dev initialize VRFConsumerBase's attributes in their constructor as
* @dev shown:
*
* @dev contract VRFConsumer {
* @dev constructor(<other arguments>, address _vrfCoordinator, address _link)
* @dev VRFConsumerBase(_vrfCoordinator) public {
* @dev <initialization with other arguments goes here>
* @dev }
* @dev }
*
* @dev The oracle will have given you an ID for the VRF keypair they have
* @dev committed to (let's call it keyHash). Create subscription, fund it
* @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface
* @dev subscription management functions).
* @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations,
* @dev callbackGasLimit, numWords),
* @dev see (VRFCoordinatorInterface for a description of the arguments).
*
* @dev Once the VRFCoordinator has received and validated the oracle's response
* @dev to your request, it will call your contract's fulfillRandomWords method.
*
* @dev The randomness argument to fulfillRandomWords is a set of random words
* @dev generated from your requestId and the blockHash of the request.
*
* @dev If your contract could have concurrent requests open, you can use the
* @dev requestId returned from requestRandomWords to track which response is associated
* @dev with which randomness request.
* @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind,
* @dev if your contract could have multiple requests in flight simultaneously.
*
* @dev Colliding `requestId`s are cryptographically impossible as long as seeds
* @dev differ.
*
* *****************************************************************************
* @dev SECURITY CONSIDERATIONS
*
* @dev A method with the ability to call your fulfillRandomness method directly
* @dev could spoof a VRF response with any random value, so it's critical that
* @dev it cannot be directly called by anything other than this base contract
* @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method).
*
* @dev For your users to trust that your contract's random behavior is free
* @dev from malicious interference, it's best if you can write it so that all
* @dev behaviors implied by a VRF response are executed *during* your
* @dev fulfillRandomness method. If your contract must store the response (or
* @dev anything derived from it) and use it later, you must ensure that any
* @dev user-significant behavior which depends on that stored value cannot be
* @dev manipulated by a subsequent VRF request.
*
* @dev Similarly, both miners and the VRF oracle itself have some influence
* @dev over the order in which VRF responses appear on the blockchain, so if
* @dev your contract could have multiple VRF requests in flight simultaneously,
* @dev you must ensure that the order in which the VRF responses arrive cannot
* @dev be used to manipulate your contract's user-significant behavior.
*
* @dev Since the block hash of the block which contains the requestRandomness
* @dev call is mixed into the input to the VRF *last*, a sufficiently powerful
* @dev miner could, in principle, fork the blockchain to evict the block
* @dev containing the request, forcing the request to be included in a
* @dev different block with a different hash, and therefore a different input
* @dev to the VRF. However, such an attack would incur a substantial economic
* @dev cost. This cost scales with the number of blocks the VRF oracle waits
* @dev until it calls responds to a request. It is for this reason that
* @dev that you can signal to an oracle you'd like them to wait longer before
* @dev responding to the request (however this is not enforced in the contract
* @dev and so remains effective only in the case of unmodified oracle software).
*/
abstract contract VRFConsumerBaseV2 {
error OnlyCoordinatorCanFulfill(address have, address want);
// solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i
address private immutable vrfCoordinator;
/**
* @param _vrfCoordinator address of VRFCoordinator contract
*/
constructor(address _vrfCoordinator) {
vrfCoordinator = _vrfCoordinator;
}
/**
* @notice fulfillRandomness handles the VRF response. Your contract must
* @notice implement it. See "SECURITY CONSIDERATIONS" above for important
* @notice principles to keep in mind when implementing your fulfillRandomness
* @notice method.
*
* @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this
* @dev signature, and will call it once it has verified the proof
* @dev associated with the randomness. (It is triggered via a call to
* @dev rawFulfillRandomness, below.)
*
* @param requestId The Id initially returned by requestRandomness
* @param randomWords the VRF output expanded to the requested number of words
*/
// solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore
function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual;
// rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF
// proof. rawFulfillRandomness then calls fulfillRandomness, after validating
// the origin of the call
function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external {
if (msg.sender != vrfCoordinator) {
revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator);
}
fulfillRandomWords(requestId, randomWords);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @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 value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` 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 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../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 address zero.
*
* 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 v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @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: CC0-1.0
pragma solidity >=0.8.13;
/**
* @title IDelegateRegistry
* @custom:version 2.0
* @custom:author foobar (0xfoobar)
* @notice A standalone immutable registry storing delegated permissions from one address to another
*/
interface IDelegateRegistry {
/// @notice Delegation type, NONE is used when a delegation does not exist or is revoked
enum DelegationType {
NONE,
ALL,
CONTRACT,
ERC721,
ERC20,
ERC1155
}
/// @notice Struct for returning delegations
struct Delegation {
DelegationType type_;
address to;
address from;
bytes32 rights;
address contract_;
uint256 tokenId;
uint256 amount;
}
/// @notice Emitted when an address delegates or revokes rights for their entire wallet
event DelegateAll(address indexed from, address indexed to, bytes32 rights, bool enable);
/// @notice Emitted when an address delegates or revokes rights for a contract address
event DelegateContract(address indexed from, address indexed to, address indexed contract_, bytes32 rights, bool enable);
/// @notice Emitted when an address delegates or revokes rights for an ERC721 tokenId
event DelegateERC721(address indexed from, address indexed to, address indexed contract_, uint256 tokenId, bytes32 rights, bool enable);
/// @notice Emitted when an address delegates or revokes rights for an amount of ERC20 tokens
event DelegateERC20(address indexed from, address indexed to, address indexed contract_, bytes32 rights, uint256 amount);
/// @notice Emitted when an address delegates or revokes rights for an amount of an ERC1155 tokenId
event DelegateERC1155(address indexed from, address indexed to, address indexed contract_, uint256 tokenId, bytes32 rights, uint256 amount);
/// @notice Thrown if multicall calldata is malformed
error MulticallFailed();
/**
* ----------- WRITE -----------
*/
/**
* @notice Call multiple functions in the current contract and return the data from all of them if they all succeed
* @param data The encoded function data for each of the calls to make to this contract
* @return results The results from each of the calls passed in via data
*/
function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);
/**
* @notice Allow the delegate to act on behalf of `msg.sender` for all contracts
* @param to The address to act as delegate
* @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
* @param enable Whether to enable or disable this delegation, true delegates and false revokes
* @return delegationHash The unique identifier of the delegation
*/
function delegateAll(address to, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash);
/**
* @notice Allow the delegate to act on behalf of `msg.sender` for a specific contract
* @param to The address to act as delegate
* @param contract_ The contract whose rights are being delegated
* @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
* @param enable Whether to enable or disable this delegation, true delegates and false revokes
* @return delegationHash The unique identifier of the delegation
*/
function delegateContract(address to, address contract_, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash);
/**
* @notice Allow the delegate to act on behalf of `msg.sender` for a specific ERC721 token
* @param to The address to act as delegate
* @param contract_ The contract whose rights are being delegated
* @param tokenId The token id to delegate
* @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
* @param enable Whether to enable or disable this delegation, true delegates and false revokes
* @return delegationHash The unique identifier of the delegation
*/
function delegateERC721(address to, address contract_, uint256 tokenId, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash);
/**
* @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC20 tokens
* @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound)
* @param to The address to act as delegate
* @param contract_ The address for the fungible token contract
* @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
* @param amount The amount to delegate, > 0 delegates and 0 revokes
* @return delegationHash The unique identifier of the delegation
*/
function delegateERC20(address to, address contract_, bytes32 rights, uint256 amount) external payable returns (bytes32 delegationHash);
/**
* @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC1155 tokens
* @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound)
* @param to The address to act as delegate
* @param contract_ The address of the contract that holds the token
* @param tokenId The token id to delegate
* @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
* @param amount The amount of that token id to delegate, > 0 delegates and 0 revokes
* @return delegationHash The unique identifier of the delegation
*/
function delegateERC1155(address to, address contract_, uint256 tokenId, bytes32 rights, uint256 amount) external payable returns (bytes32 delegationHash);
/**
* ----------- CHECKS -----------
*/
/**
* @notice Check if `to` is a delegate of `from` for the entire wallet
* @param to The potential delegate address
* @param from The potential address who delegated rights
* @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
* @return valid Whether delegate is granted to act on the from's behalf
*/
function checkDelegateForAll(address to, address from, bytes32 rights) external view returns (bool);
/**
* @notice Check if `to` is a delegate of `from` for the specified `contract_` or the entire wallet
* @param to The delegated address to check
* @param contract_ The specific contract address being checked
* @param from The cold wallet who issued the delegation
* @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
* @return valid Whether delegate is granted to act on from's behalf for entire wallet or that specific contract
*/
function checkDelegateForContract(address to, address from, address contract_, bytes32 rights) external view returns (bool);
/**
* @notice Check if `to` is a delegate of `from` for the specific `contract` and `tokenId`, the entire `contract_`, or the entire wallet
* @param to The delegated address to check
* @param contract_ The specific contract address being checked
* @param tokenId The token id for the token to delegating
* @param from The wallet that issued the delegation
* @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
* @return valid Whether delegate is granted to act on from's behalf for entire wallet, that contract, or that specific tokenId
*/
function checkDelegateForERC721(address to, address from, address contract_, uint256 tokenId, bytes32 rights) external view returns (bool);
/**
* @notice Returns the amount of ERC20 tokens the delegate is granted rights to act on the behalf of
* @param to The delegated address to check
* @param contract_ The address of the token contract
* @param from The cold wallet who issued the delegation
* @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
* @return balance The delegated balance, which will be 0 if the delegation does not exist
*/
function checkDelegateForERC20(address to, address from, address contract_, bytes32 rights) external view returns (uint256);
/**
* @notice Returns the amount of a ERC1155 tokens the delegate is granted rights to act on the behalf of
* @param to The delegated address to check
* @param contract_ The address of the token contract
* @param tokenId The token id to check the delegated amount of
* @param from The cold wallet who issued the delegation
* @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
* @return balance The delegated balance, which will be 0 if the delegation does not exist
*/
function checkDelegateForERC1155(address to, address from, address contract_, uint256 tokenId, bytes32 rights) external view returns (uint256);
/**
* ----------- ENUMERATIONS -----------
*/
/**
* @notice Returns all enabled delegations a given delegate has received
* @param to The address to retrieve delegations for
* @return delegations Array of Delegation structs
*/
function getIncomingDelegations(address to) external view returns (Delegation[] memory delegations);
/**
* @notice Returns all enabled delegations an address has given out
* @param from The address to retrieve delegations for
* @return delegations Array of Delegation structs
*/
function getOutgoingDelegations(address from) external view returns (Delegation[] memory delegations);
/**
* @notice Returns all hashes associated with enabled delegations an address has received
* @param to The address to retrieve incoming delegation hashes for
* @return delegationHashes Array of delegation hashes
*/
function getIncomingDelegationHashes(address to) external view returns (bytes32[] memory delegationHashes);
/**
* @notice Returns all hashes associated with enabled delegations an address has given out
* @param from The address to retrieve outgoing delegation hashes for
* @return delegationHashes Array of delegation hashes
*/
function getOutgoingDelegationHashes(address from) external view returns (bytes32[] memory delegationHashes);
/**
* @notice Returns the delegations for a given array of delegation hashes
* @param delegationHashes is an array of hashes that correspond to delegations
* @return delegations Array of Delegation structs, return empty structs for nonexistent or revoked delegations
*/
function getDelegationsFromHashes(bytes32[] calldata delegationHashes) external view returns (Delegation[] memory delegations);
/**
* ----------- STORAGE ACCESS -----------
*/
/**
* @notice Allows external contracts to read arbitrary storage slots
*/
function readSlot(bytes32 location) external view returns (bytes32);
/**
* @notice Allows external contracts to read an arbitrary array of storage slots
*/
function readSlots(bytes32[] calldata locations) external view returns (bytes32[] memory);
}// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.17;
/**
* @title An immutable registry contract to be deployed as a standalone primitive
* @dev See EIP-5639, new project launches can read previous cold wallet -> hot wallet delegations
* from here and integrate those permissions into their flow
*/
interface IDelegationRegistry {
/// @notice Delegation type
enum DelegationType {
NONE,
ALL,
CONTRACT,
TOKEN
}
/// @notice Info about a single delegation, used for onchain enumeration
struct DelegationInfo {
DelegationType type_;
address vault;
address delegate;
address contract_;
uint256 tokenId;
}
/// @notice Info about a single contract-level delegation
struct ContractDelegation {
address contract_;
address delegate;
}
/// @notice Info about a single token-level delegation
struct TokenDelegation {
address contract_;
uint256 tokenId;
address delegate;
}
/// @notice Emitted when a user delegates their entire wallet
event DelegateForAll(address vault, address delegate, bool value);
/// @notice Emitted when a user delegates a specific contract
event DelegateForContract(address vault, address delegate, address contract_, bool value);
/// @notice Emitted when a user delegates a specific token
event DelegateForToken(address vault, address delegate, address contract_, uint256 tokenId, bool value);
/// @notice Emitted when a user revokes all delegations
event RevokeAllDelegates(address vault);
/// @notice Emitted when a user revoes all delegations for a given delegate
event RevokeDelegate(address vault, address delegate);
/**
* ----------- WRITE -----------
*/
/**
* @notice Allow the delegate to act on your behalf for all contracts
* @param delegate The hotwallet to act on your behalf
* @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
*/
function delegateForAll(address delegate, bool value) external;
/**
* @notice Allow the delegate to act on your behalf for a specific contract
* @param delegate The hotwallet to act on your behalf
* @param contract_ The address for the contract you're delegating
* @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
*/
function delegateForContract(address delegate, address contract_, bool value) external;
/**
* @notice Allow the delegate to act on your behalf for a specific token
* @param delegate The hotwallet to act on your behalf
* @param contract_ The address for the contract you're delegating
* @param tokenId The token id for the token you're delegating
* @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
*/
function delegateForToken(address delegate, address contract_, uint256 tokenId, bool value) external;
/**
* @notice Revoke all delegates
*/
function revokeAllDelegates() external;
/**
* @notice Revoke a specific delegate for all their permissions
* @param delegate The hotwallet to revoke
*/
function revokeDelegate(address delegate) external;
/**
* @notice Remove yourself as a delegate for a specific vault
* @param vault The vault which delegated to the msg.sender, and should be removed
*/
function revokeSelf(address vault) external;
/**
* ----------- READ -----------
*/
/**
* @notice Returns all active delegations a given delegate is able to claim on behalf of
* @param delegate The delegate that you would like to retrieve delegations for
* @return info Array of DelegationInfo structs
*/
function getDelegationsByDelegate(address delegate) external view returns (DelegationInfo[] memory);
/**
* @notice Returns an array of wallet-level delegates for a given vault
* @param vault The cold wallet who issued the delegation
* @return addresses Array of wallet-level delegates for a given vault
*/
function getDelegatesForAll(address vault) external view returns (address[] memory);
/**
* @notice Returns an array of contract-level delegates for a given vault and contract
* @param vault The cold wallet who issued the delegation
* @param contract_ The address for the contract you're delegating
* @return addresses Array of contract-level delegates for a given vault and contract
*/
function getDelegatesForContract(address vault, address contract_) external view returns (address[] memory);
/**
* @notice Returns an array of contract-level delegates for a given vault's token
* @param vault The cold wallet who issued the delegation
* @param contract_ The address for the contract holding the token
* @param tokenId The token id for the token you're delegating
* @return addresses Array of contract-level delegates for a given vault's token
*/
function getDelegatesForToken(address vault, address contract_, uint256 tokenId)
external
view
returns (address[] memory);
/**
* @notice Returns all contract-level delegations for a given vault
* @param vault The cold wallet who issued the delegations
* @return delegations Array of ContractDelegation structs
*/
function getContractLevelDelegations(address vault)
external
view
returns (ContractDelegation[] memory delegations);
/**
* @notice Returns all token-level delegations for a given vault
* @param vault The cold wallet who issued the delegations
* @return delegations Array of TokenDelegation structs
*/
function getTokenLevelDelegations(address vault) external view returns (TokenDelegation[] memory delegations);
/**
* @notice Returns true if the address is delegated to act on the entire vault
* @param delegate The hotwallet to act on your behalf
* @param vault The cold wallet who issued the delegation
*/
function checkDelegateForAll(address delegate, address vault) external view returns (bool);
/**
* @notice Returns true if the address is delegated to act on your behalf for a token contract or an entire vault
* @param delegate The hotwallet to act on your behalf
* @param contract_ The address for the contract you're delegating
* @param vault The cold wallet who issued the delegation
*/
function checkDelegateForContract(address delegate, address vault, address contract_)
external
view
returns (bool);
/**
* @notice Returns true if the address is delegated to act on your behalf for a specific token, the token's contract or an entire vault
* @param delegate The hotwallet to act on your behalf
* @param contract_ The address for the contract you're delegating
* @param tokenId The token id for the token you're delegating
* @param vault The cold wallet who issued the delegation
*/
function checkDelegateForToken(address delegate, address vault, address contract_, uint256 tokenId)
external
view
returns (bool);
}{
"optimizer": {
"enabled": true,
"runs": 200,
"details": {
"yul": true
}
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"address","name":"_vrfCoordinator","type":"address"},{"internalType":"uint256","name":"_subscriptionId","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyLaunched","type":"error"},{"inputs":[],"name":"ExceedsPurchaseCap","type":"error"},{"inputs":[],"name":"IncorrectPrice","type":"error"},{"inputs":[],"name":"NFTOwner","type":"error"},{"inputs":[],"name":"NotEnabled","type":"error"},{"inputs":[{"internalType":"address","name":"have","type":"address"},{"internalType":"address","name":"want","type":"address"}],"name":"OnlyCoordinatorCanFulfill","type":"error"},{"inputs":[],"name":"OutsideTimeWindow","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"Whitelist","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"KOLCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"KOLPurchasedTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"KOLWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"callbackGasLimit","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cliffDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"coordinator","outputs":[{"internalType":"contract IVRFCoordinatorV2Plus","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delegateRegistryV1","outputs":[{"internalType":"contract IDelegationRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delegateRegistryV2","outputs":[{"internalType":"contract IDelegateRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numDraws","type":"uint256"}],"name":"draw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"emergencyWithdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableClaims","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableRefunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialUnlockPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keyHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_phaseOneRatio","type":"uint256"},{"internalType":"uint256","name":"_phaseTwoRatio","type":"uint256"},{"internalType":"uint256","name":"_phaseOneCap","type":"uint256"},{"internalType":"uint256","name":"_KOLCap","type":"uint256"},{"internalType":"uint256","name":"_superKOLCap","type":"uint256"},{"internalType":"uint256","name":"_rafflePrice","type":"uint256"},{"internalType":"uint256","name":"_raffleAmount","type":"uint256"}],"name":"launch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"launchTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nftAddress","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseOneCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseOneEnded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"phaseOnePurchase","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"phaseOnePurchased","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseOnePurchasedTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseOneRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseOneSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseOneTwoETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numTickets","type":"uint256"}],"name":"phaseThreePurchase","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"phaseThreePurchasedTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseThreeSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseTwoEnded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseTwoKOLPurchase","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"phaseTwoRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseTwoSuperKOLPurchase","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"phaseTwoSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"raffleAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"raffleEntries","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"raffleLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rafflePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256[]","name":"randomWords","type":"uint256[]"}],"name":"rawFulfillRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"refundRaffle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"refundsEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requestConfirmations","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"setGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"users","type":"address[]"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setKOLWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"newHash","type":"bytes32"}],"name":"setKeyHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setRaffleAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setRafflePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"setSubId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"users","type":"address[]"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setSuperKOLWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"subscriptionId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"superKOLCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"superKOLPurchasedTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"superKOLWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenAddress","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTokensPurchased","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"usersInfo","outputs":[{"internalType":"uint256","name":"KOLPurchased","type":"uint256"},{"internalType":"uint256","name":"superKOLPurchased","type":"uint256"},{"internalType":"uint256","name":"totalPurchased","type":"uint256"},{"internalType":"uint256","name":"rafflesWon","type":"uint256"},{"internalType":"uint256","name":"rafflesPurchased","type":"uint256"},{"internalType":"uint256","name":"amountClaimed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"totalPurchased","type":"uint256"}],"name":"vestedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vestingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawETHNoRaffle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawETHNoRefunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
0x60e0346101e957601f61206f38819003918201601f19168301916001600160401b038311848410176101ee578084926080946040528339810103126101e95761004781610204565b9061005460208201610204565b90606061006360408301610204565b910151928160805233156101d35760008054336001600160a01b031982168117835560405196640300e4e1c0949390926001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a36a1b4c0595a86aa1c10000006006556a6d301656a1aa8704000000600855601460175562127500601a5561a8c0601b55604b601c557f3fd2fec10d06ee8f65e7f2e95f5c56511359ece3f33960ad8a866ae24a8ff10b602055602180546c447e69651d841bd8d104bed49360a0526d76a84fef008cdabe6409d2fe638b60c052601f80546001600160a01b03199081166001600160a01b0398891617909155601e939093556001600160d01b0319169390931760309290921b600160301b600160d01b0316919091179091556022805490911692909116919091179055611e569081610219823960805181611500015260a0518181816105f10152611cde015260c051818181610aa90152611d490152f35b631e4fbdf760e01b600052600060045260246000fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036101e95756fe6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c8063019948851461190757806303b4a479146118e957806303c669e3146118bd57806303ebbf341461189f57806308ac900a1461188157806309c1ba2e146118635780630a0090971461183a57806318643d371461181c5780631a96ab2b146117fb5780631bfce853146117d55780631cecfaad146116af5780631fe543e31461148e57806324f746971461146a57806327b3bf111461144c5780632866ed211461142957806329687c53146114035780632a29e67a146113a157806332b7ac641461138357806334fccc1d1461136557806336ffc8b0146113475780633b3041471461117557806348a93a0d1461113f5780634c846e46146110fd5780634e71d92d1461105b57806352bca4c31461103d578063532f11791461101757806353d1f59d14610fb557806355a16c2414610f97578063595d221314610f795780635bf8633a14610f4c5780635d0eaaaf14610edb57806361728f3914610ebe578063715018a614610e655780637313ee5a14610e47578063790ca41314610e295780637d7af28014610e0b5780637d7bc63914610dda5780638007634f14610c815780638098004314610c6057806380c028a814610ad8578063856ed8c914610a935780638c52dc4114610a675780638da5cb5b14610a3e5780639755e04e146109ff57806398544710146109de5780639b27349d146108695780639d76ea5814610840578063a277d5b114610822578063a4bfb13014610804578063b0fb162f146107e0578063b2af127c1461071a578063baa39fbe146106db578063bcf257291461067a578063c94028c21461065c578063d1abca7a1461063e578063d85349f714610620578063db584d25146105db578063dbe65f59146105bd578063e086e5ec14610592578063e259f636146104f5578063e365d863146104d7578063ea28edad146103f7578063ec9cd924146103d4578063ee7d72b4146103a2578063f2fde38b146103195763f8d867940361000e5734610314576000366003190112610314576020601554604051908152f35b600080fd5b34610314576020366003190112610314576103326119b3565b61033a611c2c565b6001600160a01b0316801561038c57600080546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b600052600060045260246000fd5b34610314576020366003190112610314576103bb611c2c565b6021805463ffffffff191660043563ffffffff16179055005b3461031457600036600319011261031457602060ff601d54166040519015158152f35b3461031457600036600319011261031457610410611c2c565b600f54620189c081018091116104c15742106104b057600160ff196010541617601055426011556000602060018060a01b03602254166064600d5460405194859384926323b872dd60e01b845233600485015230602485015260448401525af180156104a45761047c57005b6100199060203d60201161049d575b6104958183611979565b810190611bf5565b503d61048b565b6040513d6000823e3d90fd5b63ae20f3a560e01b60005260046000fd5b634e487b7160e01b600052601160045260246000fd5b34610314576000366003190112610314576020600e54604051908152f35b346103145760003660031901126103145760ff601d5460101c16156105815733600090815260016020526040902060048101546003909101546105459161053c9190611ae8565b60155490611ad5565b6103cf8102908082046103cf14901517156104c157600080806103e88194338352600160205282600460408220015504335af150610019611af5565b633f54562b60e11b60005260046000fd5b34610314576000366003190112610314576105ab611c2c565b600080808047335af150610019611af5565b34610314576000366003190112610314576020601354604051908152f35b34610314576000366003190112610314576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610314576000366003190112610314576020601b54604051908152f35b34610314576000366003190112610314576020600c54604051908152f35b34610314576000366003190112610314576020601654604051908152f35b346103145760e036600319011261031457610693611c2c565b600f546106ca5742600f5560043560185560243560195560443560125560643560135560843560145560a43560155560c435601655005b6319f4db0f60e31b60005260046000fd5b34610314576020366003190112610314576001600160a01b036106fc6119b3565b166000526004602052602060ff604060002054166040519015158152f35b34610314576020366003190112610314576107336119b3565b61073b611c2c565b6040516370a0823160e01b8152306004820152906001600160a01b0316602082602481845afa9182156104a4576000926107aa575b5060405163a9059cbb60e01b81523360048201526024810192909252602090829081600081604481015b03925af180156104a45761047c57005b91506020823d6020116107d8575b816107c560209383611979565b810103126103145790519061079a610770565b3d91506107b8565b3461031457600036600319011261031457602061ffff602154821c16604051908152f35b34610314576000366003190112610314576020600954604051908152f35b34610314576000366003190112610314576020600d54604051908152f35b34610314576000366003190112610314576022546040516001600160a01b039091168152602090f35b602036600319011261031457600435600f5461384081018082116104c15742109081156109c7575b506104b057601d5460ff8160081c161561098b575b506108b381601554611ad5565b340361097a573360005260016020526108d481600460406000200154611ac8565b601754106109695733600052600160205260046040600020016108f8828254611ac8565b905560005b81811061090657005b60055490680100000000000000008210156109535761094d61092f836001809501600555611a66565b81546001600160a01b0360039290921b91821b19163390911b179055565b016108fd565b634e487b7160e01b600052604160045260246000fd5b63b1c0823160e01b60005260046000fd5b6399b5cb1d60e01b60005260046000fd5b610100906109b56109ad6008546109a7600954600a5490611ac8565b90611ae8565b600b54611ac8565b600b5561ff00191617601d55816108a6565b9050620189c081018091116104c157421182610891565b34610314576020366003190112610314576109f7611c2c565b600435602055005b34610314576020366003190112610314576001600160a01b03610a206119b3565b166000526003602052602060ff604060002054166040519015158152f35b34610314576000366003190112610314576000546040516001600160a01b039091168152602090f35b3461031457600036600319011261031457610a80611c2c565b601d805462ff0000191662010000179055005b34610314576000366003190112610314576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b60403660031901126103145760043567ffffffffffffffff811161031457610b04903690600401611a97565b60243567ffffffffffffffff811161031457610b24903690600401611a97565b919092600f54611c2081018091116104c15742116104b0576000805b848110610c405750340361097a5760005b828110610b6957610b6434600e54611ac8565b600e55005b610b74818484611c0d565b3590610b81818688611c0d565b35610b8b83611c55565b15610c2f57601854610b9c91611ad5565b91806000526002602052610bb583604060002054611ac8565b6012541061096957610bc983600754611ac8565b6006541061096957600192610c269133600052846020526002604060002001610bf3838254611ac8565b905560005260026020526040600020610c0d828254611ac8565b9055610c1b81600754611ac8565b600755600d54611ac8565b600d5501610b51565b635f68eddf60e11b60005260046000fd5b90610c59600191610c5284888a611c0d565b3590611ac8565b9101610b40565b3461031457602036600319011261031457610c79611c2c565b600435601e55005b600036600319011261031457600f54611c2081018082116104c1574210908115610dc4575b506104b057601d5460ff811615610d96575b5033600052600460205260ff6040600020541615610d8557610cdc60195434611ad5565b336000526001602052610cf781600160406000200154611ac8565b6014541061096957610d1781610d12600954600a5490611ac8565b611ac8565b6008541061096957610d76903360005260016020526001604060002001610d3f828254611ac8565b90553360005260016020526002604060002001610d5d828254611ac8565b9055610d6b81600a54611ac8565b600a55600d54611ac8565b600d55610b6434600e54611ac8565b634f5fb6c960e11b60005260046000fd5b600190610db3610dab60065460075490611ae8565b600854611ac8565b60085560ff191617601d5580610cb8565b905061384081018091116104c157421181610ca6565b3461031457600036600319011261031457610df3611c2c565b6000808080600e5481600e55335af150610019611af5565b34610314576000366003190112610314576020601854604051908152f35b34610314576000366003190112610314576020600f54604051908152f35b34610314576000366003190112610314576020601a54604051908152f35b3461031457600036600319011261031457610e7e611c2c565b600080546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346103145760003660031901126103145760208054604051908152f35b34610314576020366003190112610314576001600160a01b03610efc6119b3565b16600052600160205260c0604060002080549060018101549060028101546003820154906005600484015493015493604051958652602086015260408501526060840152608083015260a0820152f35b346103145760003660031901126103145760215460405160309190911c6001600160a01b03168152602090f35b34610314576000366003190112610314576020600854604051908152f35b34610314576000366003190112610314576020600654604051908152f35b3461031457610fc3366119c9565b90610fcc611c2c565b60005b8151811015610019576001906001600160a01b03610fed8285611be1565b511660005260046020526110118460406000209060ff801983541691151516179055565b01610fcf565b3461031457600036600319011261031457602060ff601d5460101c166040519015158152f35b34610314576000366003190112610314576020601254604051908152f35b346103145760003660031901126103145760ff6010541615610581573360005260016020526000602061079a6110976002604085200154611b35565b338452600183526110af600560408620015482611ae8565b3380865260018552604080872060050193909355602254925163a9059cbb60e01b8152600481019190915260248101919091529384926001600160a01b039092169183919082906044820190565b346103145760203660031901126103145760043560055481101561031457611126602091611a66565b905460405160039290921b1c6001600160a01b03168152f35b3461031457602036600319011261031457611158611c2c565b600f5461384081018091116104c15742116104b057600435601555005b3461031457602036600319011261031457600435611191611c2c565b600f54620189c081018091116104c15742106104b0576111bf6111b660165483611ad5565b600c5490611ac8565b600b541061096957602154906040516020810181811067ffffffffffffffff82111761095357604052600081526040519063125fa26760e31b6020830152511515602482015260248152611214604482611979565b602054601e54926040519460c086019086821067ffffffffffffffff831117610953579391869363ffffffff9260405284526020840195865281604085019561ffff8160201c16875281606087019116815281608087019316835260a0860194855261ffff60018060a01b03601f541697604051998a98634d8e1c2f60e11b8a52602060048b01525160248a01525160448901525116606487015251166084850152511660a48301525160c060c48301528051908160e484015260005b82811061132e575050918160006101048286838360209984010152601f801991011681010301925af180156104a45761130657005b6100199060203d602011611327575b61131f8183611979565b810190611c1d565b503d611315565b60208282018101516101048884010152869450016112d1565b34610314576000366003190112610314576020600754604051908152f35b34610314576000366003190112610314576020601c54604051908152f35b34610314576000366003190112610314576020601454604051908152f35b34610314576113af366119c9565b906113b8611c2c565b60005b8151811015610019576001906001600160a01b036113d98285611be1565b511660005260036020526113fd8460406000209060ff801983541691151516179055565b016113bb565b3461031457600036600319011261031457602060ff601d5460081c166040519015158152f35b3461031457600036600319011261031457602060ff601054166040519015158152f35b34610314576000366003190112610314576020601154604051908152f35b3461031457600036600319011261031457602063ffffffff60215416604051908152f35b346103145760403660031901126103145760243567ffffffffffffffff81116103145736602382011215610314578060040135906114cb8261199b565b916114d96040519384611979565b8083526024602084019160051b8301019136831161031457602401905b82821061169f57837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633819003611687575060005b8151811015610019576115478183611be1565b51600554908115611671570661155c81611a66565b60018060a01b0391549060031b1c1660165481600052600160205261158a6002604060002001918254611ac8565b90556115a960165461159e81600d54611ac8565b600d55600c54611ac8565b600c5560005260016020526003604060002001805490600182018092116104c157556005546000198101919082116104c1576116026115ea61162693611a66565b905460039190911b1c6001600160a01b031691611a66565b81546001600160a01b0393841660039290921b91821b9390911b1916919091179055565b60055490811561165b576001916000190161164081611a66565b815490858060a01b039060031b1b1916905560055501611534565b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b63073e64fd60e21b6000523360045260245260446000fd5b81358152602091820191016114f6565b600036600319011261031457600f54611c2081018082116104c15742109081156117bf575b506104b057601d5460ff811615611799575b5033600052600360205260ff6040600020541615610d855761170a60195434611ad5565b33600052600160205261172281604060002054611ac8565b601354106109695761173d81610d12600954600a5490611ac8565b6008541061096957610d76903360005260016020526040600020611762828254611ac8565b90553360005260016020526002604060002001611780828254611ac8565b905561178e81600954611ac8565b600955600d54611ac8565b6001906117ae610dab60065460075490611ae8565b60085560ff191617601d55806116e6565b905061384081018091116104c1574211816116d4565b346103145760203660031901126103145760206117f3600435611b35565b604051908152f35b3461031457602036600319011261031457611814611c2c565b600435601655005b34610314576000366003190112610314576020601754604051908152f35b3461031457600036600319011261031457601f546040516001600160a01b039091168152602090f35b34610314576000366003190112610314576020601e54604051908152f35b34610314576000366003190112610314576020601954604051908152f35b34610314576000366003190112610314576020600a54604051908152f35b346103145760203660031901126103145760043560005260026020526020604060002054604051908152f35b34610314576000366003190112610314576020600b54604051908152f35b3461031457600036600319011261031457611920611c2c565b600f54620189c081018091116104c15742106104b05761194560055460155490611ad5565b6103cf8102908082046103cf14901517156104c1576000808061196d6103e882950447611ae8565b335af150610019611af5565b90601f8019910116810190811067ffffffffffffffff82111761095357604052565b67ffffffffffffffff81116109535760051b60200190565b600435906001600160a01b038216820361031457565b6040600319820112610314576004359067ffffffffffffffff8211610314578060238301121561031457816004013590611a028261199b565b92611a106040519485611979565b8284526024602085019360051b82010191821161031457602401915b818310611a46575050509060243580151581036103145790565b82356001600160a01b038116810361031457815260209283019201611a2c565b600554811015611a8157600560005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b9181601f840112156103145782359167ffffffffffffffff8311610314576020808501948460051b01011161031457565b919082018092116104c157565b818102929181159184041417156104c157565b919082039182116104c157565b3d15611b30573d9067ffffffffffffffff82116109535760405191611b24601f8201601f191660200184611979565b82523d6000602084013e565b606090565b601154908115611bda57611b498242611ae8565b601c546064611b588285611ad5565b0493601b5490818410600014611b7057505050505090565b601a54949593611b808684611ac8565b11611b8d57505050505090565b611ba491611b9e9196949596611ac8565b42611ae8565b90606403606481116104c157611bbf606491611bc594611ad5565b04611ad5565b91801561167157611bd7920490611ac8565b90565b5050600090565b8051821015611a815760209160051b010190565b90816020910312610314575180151581036103145790565b9190811015611a815760051b0190565b90816020910312610314575190565b6000546001600160a01b03163303611c4057565b63118cdaa760e01b6000523360045260246000fd5b6021546040516331a9108f60e11b81526004810183905260309190911c6001600160a01b03169190602081602481865afa9081156104a457600091611dd7575b506001600160a01b031691338314611db057604051632e7cda1d60e21b81523360048201526024810184905260448101829052606481018390526000608482015260208160a4817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104a457600091611db8575b50611db057604051631574d39f60e31b81523360048201526024810193909352604483015260648201526020816084817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104a457600091611d91575b50611d8c57600090565b600190565b611daa915060203d60201161049d576104958183611979565b38611d82565b505050600190565b611dd1915060203d60201161049d576104958183611979565b38611d17565b6020813d602011611e18575b81611df060209383611979565b81010312611e145751906001600160a01b0382168203611e11575038611c95565b80fd5b5080fd5b3d9150611de356fea2646970667358221220750f3b635c6a5b231aad4a74db8a5d18531a18fbffe87b6ca0007cb9a2a6374064736f6c634300081a0033000000000000000000000000ee03aecbf056865d1365cad76aeef305238bd1dc00000000000000000000000057926998725cbcf319373550307c67830abf6187000000000000000000000000d7f86b4b8cae7d942340ff628f82735b7a20893a0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c8063019948851461190757806303b4a479146118e957806303c669e3146118bd57806303ebbf341461189f57806308ac900a1461188157806309c1ba2e146118635780630a0090971461183a57806318643d371461181c5780631a96ab2b146117fb5780631bfce853146117d55780631cecfaad146116af5780631fe543e31461148e57806324f746971461146a57806327b3bf111461144c5780632866ed211461142957806329687c53146114035780632a29e67a146113a157806332b7ac641461138357806334fccc1d1461136557806336ffc8b0146113475780633b3041471461117557806348a93a0d1461113f5780634c846e46146110fd5780634e71d92d1461105b57806352bca4c31461103d578063532f11791461101757806353d1f59d14610fb557806355a16c2414610f97578063595d221314610f795780635bf8633a14610f4c5780635d0eaaaf14610edb57806361728f3914610ebe578063715018a614610e655780637313ee5a14610e47578063790ca41314610e295780637d7af28014610e0b5780637d7bc63914610dda5780638007634f14610c815780638098004314610c6057806380c028a814610ad8578063856ed8c914610a935780638c52dc4114610a675780638da5cb5b14610a3e5780639755e04e146109ff57806398544710146109de5780639b27349d146108695780639d76ea5814610840578063a277d5b114610822578063a4bfb13014610804578063b0fb162f146107e0578063b2af127c1461071a578063baa39fbe146106db578063bcf257291461067a578063c94028c21461065c578063d1abca7a1461063e578063d85349f714610620578063db584d25146105db578063dbe65f59146105bd578063e086e5ec14610592578063e259f636146104f5578063e365d863146104d7578063ea28edad146103f7578063ec9cd924146103d4578063ee7d72b4146103a2578063f2fde38b146103195763f8d867940361000e5734610314576000366003190112610314576020601554604051908152f35b600080fd5b34610314576020366003190112610314576103326119b3565b61033a611c2c565b6001600160a01b0316801561038c57600080546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b600052600060045260246000fd5b34610314576020366003190112610314576103bb611c2c565b6021805463ffffffff191660043563ffffffff16179055005b3461031457600036600319011261031457602060ff601d54166040519015158152f35b3461031457600036600319011261031457610410611c2c565b600f54620189c081018091116104c15742106104b057600160ff196010541617601055426011556000602060018060a01b03602254166064600d5460405194859384926323b872dd60e01b845233600485015230602485015260448401525af180156104a45761047c57005b6100199060203d60201161049d575b6104958183611979565b810190611bf5565b503d61048b565b6040513d6000823e3d90fd5b63ae20f3a560e01b60005260046000fd5b634e487b7160e01b600052601160045260246000fd5b34610314576000366003190112610314576020600e54604051908152f35b346103145760003660031901126103145760ff601d5460101c16156105815733600090815260016020526040902060048101546003909101546105459161053c9190611ae8565b60155490611ad5565b6103cf8102908082046103cf14901517156104c157600080806103e88194338352600160205282600460408220015504335af150610019611af5565b633f54562b60e11b60005260046000fd5b34610314576000366003190112610314576105ab611c2c565b600080808047335af150610019611af5565b34610314576000366003190112610314576020601354604051908152f35b34610314576000366003190112610314576040517f00000000000000000000000000000000000000447e69651d841bd8d104bed4936001600160a01b03168152602090f35b34610314576000366003190112610314576020601b54604051908152f35b34610314576000366003190112610314576020600c54604051908152f35b34610314576000366003190112610314576020601654604051908152f35b346103145760e036600319011261031457610693611c2c565b600f546106ca5742600f5560043560185560243560195560443560125560643560135560843560145560a43560155560c435601655005b6319f4db0f60e31b60005260046000fd5b34610314576020366003190112610314576001600160a01b036106fc6119b3565b166000526004602052602060ff604060002054166040519015158152f35b34610314576020366003190112610314576107336119b3565b61073b611c2c565b6040516370a0823160e01b8152306004820152906001600160a01b0316602082602481845afa9182156104a4576000926107aa575b5060405163a9059cbb60e01b81523360048201526024810192909252602090829081600081604481015b03925af180156104a45761047c57005b91506020823d6020116107d8575b816107c560209383611979565b810103126103145790519061079a610770565b3d91506107b8565b3461031457600036600319011261031457602061ffff602154821c16604051908152f35b34610314576000366003190112610314576020600954604051908152f35b34610314576000366003190112610314576020600d54604051908152f35b34610314576000366003190112610314576022546040516001600160a01b039091168152602090f35b602036600319011261031457600435600f5461384081018082116104c15742109081156109c7575b506104b057601d5460ff8160081c161561098b575b506108b381601554611ad5565b340361097a573360005260016020526108d481600460406000200154611ac8565b601754106109695733600052600160205260046040600020016108f8828254611ac8565b905560005b81811061090657005b60055490680100000000000000008210156109535761094d61092f836001809501600555611a66565b81546001600160a01b0360039290921b91821b19163390911b179055565b016108fd565b634e487b7160e01b600052604160045260246000fd5b63b1c0823160e01b60005260046000fd5b6399b5cb1d60e01b60005260046000fd5b610100906109b56109ad6008546109a7600954600a5490611ac8565b90611ae8565b600b54611ac8565b600b5561ff00191617601d55816108a6565b9050620189c081018091116104c157421182610891565b34610314576020366003190112610314576109f7611c2c565b600435602055005b34610314576020366003190112610314576001600160a01b03610a206119b3565b166000526003602052602060ff604060002054166040519015158152f35b34610314576000366003190112610314576000546040516001600160a01b039091168152602090f35b3461031457600036600319011261031457610a80611c2c565b601d805462ff0000191662010000179055005b34610314576000366003190112610314576040517f00000000000000000000000000000000000076a84fef008cdabe6409d2fe638b6001600160a01b03168152602090f35b60403660031901126103145760043567ffffffffffffffff811161031457610b04903690600401611a97565b60243567ffffffffffffffff811161031457610b24903690600401611a97565b919092600f54611c2081018091116104c15742116104b0576000805b848110610c405750340361097a5760005b828110610b6957610b6434600e54611ac8565b600e55005b610b74818484611c0d565b3590610b81818688611c0d565b35610b8b83611c55565b15610c2f57601854610b9c91611ad5565b91806000526002602052610bb583604060002054611ac8565b6012541061096957610bc983600754611ac8565b6006541061096957600192610c269133600052846020526002604060002001610bf3838254611ac8565b905560005260026020526040600020610c0d828254611ac8565b9055610c1b81600754611ac8565b600755600d54611ac8565b600d5501610b51565b635f68eddf60e11b60005260046000fd5b90610c59600191610c5284888a611c0d565b3590611ac8565b9101610b40565b3461031457602036600319011261031457610c79611c2c565b600435601e55005b600036600319011261031457600f54611c2081018082116104c1574210908115610dc4575b506104b057601d5460ff811615610d96575b5033600052600460205260ff6040600020541615610d8557610cdc60195434611ad5565b336000526001602052610cf781600160406000200154611ac8565b6014541061096957610d1781610d12600954600a5490611ac8565b611ac8565b6008541061096957610d76903360005260016020526001604060002001610d3f828254611ac8565b90553360005260016020526002604060002001610d5d828254611ac8565b9055610d6b81600a54611ac8565b600a55600d54611ac8565b600d55610b6434600e54611ac8565b634f5fb6c960e11b60005260046000fd5b600190610db3610dab60065460075490611ae8565b600854611ac8565b60085560ff191617601d5580610cb8565b905061384081018091116104c157421181610ca6565b3461031457600036600319011261031457610df3611c2c565b6000808080600e5481600e55335af150610019611af5565b34610314576000366003190112610314576020601854604051908152f35b34610314576000366003190112610314576020600f54604051908152f35b34610314576000366003190112610314576020601a54604051908152f35b3461031457600036600319011261031457610e7e611c2c565b600080546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346103145760003660031901126103145760208054604051908152f35b34610314576020366003190112610314576001600160a01b03610efc6119b3565b16600052600160205260c0604060002080549060018101549060028101546003820154906005600484015493015493604051958652602086015260408501526060840152608083015260a0820152f35b346103145760003660031901126103145760215460405160309190911c6001600160a01b03168152602090f35b34610314576000366003190112610314576020600854604051908152f35b34610314576000366003190112610314576020600654604051908152f35b3461031457610fc3366119c9565b90610fcc611c2c565b60005b8151811015610019576001906001600160a01b03610fed8285611be1565b511660005260046020526110118460406000209060ff801983541691151516179055565b01610fcf565b3461031457600036600319011261031457602060ff601d5460101c166040519015158152f35b34610314576000366003190112610314576020601254604051908152f35b346103145760003660031901126103145760ff6010541615610581573360005260016020526000602061079a6110976002604085200154611b35565b338452600183526110af600560408620015482611ae8565b3380865260018552604080872060050193909355602254925163a9059cbb60e01b8152600481019190915260248101919091529384926001600160a01b039092169183919082906044820190565b346103145760203660031901126103145760043560055481101561031457611126602091611a66565b905460405160039290921b1c6001600160a01b03168152f35b3461031457602036600319011261031457611158611c2c565b600f5461384081018091116104c15742116104b057600435601555005b3461031457602036600319011261031457600435611191611c2c565b600f54620189c081018091116104c15742106104b0576111bf6111b660165483611ad5565b600c5490611ac8565b600b541061096957602154906040516020810181811067ffffffffffffffff82111761095357604052600081526040519063125fa26760e31b6020830152511515602482015260248152611214604482611979565b602054601e54926040519460c086019086821067ffffffffffffffff831117610953579391869363ffffffff9260405284526020840195865281604085019561ffff8160201c16875281606087019116815281608087019316835260a0860194855261ffff60018060a01b03601f541697604051998a98634d8e1c2f60e11b8a52602060048b01525160248a01525160448901525116606487015251166084850152511660a48301525160c060c48301528051908160e484015260005b82811061132e575050918160006101048286838360209984010152601f801991011681010301925af180156104a45761130657005b6100199060203d602011611327575b61131f8183611979565b810190611c1d565b503d611315565b60208282018101516101048884010152869450016112d1565b34610314576000366003190112610314576020600754604051908152f35b34610314576000366003190112610314576020601c54604051908152f35b34610314576000366003190112610314576020601454604051908152f35b34610314576113af366119c9565b906113b8611c2c565b60005b8151811015610019576001906001600160a01b036113d98285611be1565b511660005260036020526113fd8460406000209060ff801983541691151516179055565b016113bb565b3461031457600036600319011261031457602060ff601d5460081c166040519015158152f35b3461031457600036600319011261031457602060ff601054166040519015158152f35b34610314576000366003190112610314576020601154604051908152f35b3461031457600036600319011261031457602063ffffffff60215416604051908152f35b346103145760403660031901126103145760243567ffffffffffffffff81116103145736602382011215610314578060040135906114cb8261199b565b916114d96040519384611979565b8083526024602084019160051b8301019136831161031457602401905b82821061169f57837f000000000000000000000000d7f86b4b8cae7d942340ff628f82735b7a20893a6001600160a01b031633819003611687575060005b8151811015610019576115478183611be1565b51600554908115611671570661155c81611a66565b60018060a01b0391549060031b1c1660165481600052600160205261158a6002604060002001918254611ac8565b90556115a960165461159e81600d54611ac8565b600d55600c54611ac8565b600c5560005260016020526003604060002001805490600182018092116104c157556005546000198101919082116104c1576116026115ea61162693611a66565b905460039190911b1c6001600160a01b031691611a66565b81546001600160a01b0393841660039290921b91821b9390911b1916919091179055565b60055490811561165b576001916000190161164081611a66565b815490858060a01b039060031b1b1916905560055501611534565b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b63073e64fd60e21b6000523360045260245260446000fd5b81358152602091820191016114f6565b600036600319011261031457600f54611c2081018082116104c15742109081156117bf575b506104b057601d5460ff811615611799575b5033600052600360205260ff6040600020541615610d855761170a60195434611ad5565b33600052600160205261172281604060002054611ac8565b601354106109695761173d81610d12600954600a5490611ac8565b6008541061096957610d76903360005260016020526040600020611762828254611ac8565b90553360005260016020526002604060002001611780828254611ac8565b905561178e81600954611ac8565b600955600d54611ac8565b6001906117ae610dab60065460075490611ae8565b60085560ff191617601d55806116e6565b905061384081018091116104c1574211816116d4565b346103145760203660031901126103145760206117f3600435611b35565b604051908152f35b3461031457602036600319011261031457611814611c2c565b600435601655005b34610314576000366003190112610314576020601754604051908152f35b3461031457600036600319011261031457601f546040516001600160a01b039091168152602090f35b34610314576000366003190112610314576020601e54604051908152f35b34610314576000366003190112610314576020601954604051908152f35b34610314576000366003190112610314576020600a54604051908152f35b346103145760203660031901126103145760043560005260026020526020604060002054604051908152f35b34610314576000366003190112610314576020600b54604051908152f35b3461031457600036600319011261031457611920611c2c565b600f54620189c081018091116104c15742106104b05761194560055460155490611ad5565b6103cf8102908082046103cf14901517156104c1576000808061196d6103e882950447611ae8565b335af150610019611af5565b90601f8019910116810190811067ffffffffffffffff82111761095357604052565b67ffffffffffffffff81116109535760051b60200190565b600435906001600160a01b038216820361031457565b6040600319820112610314576004359067ffffffffffffffff8211610314578060238301121561031457816004013590611a028261199b565b92611a106040519485611979565b8284526024602085019360051b82010191821161031457602401915b818310611a46575050509060243580151581036103145790565b82356001600160a01b038116810361031457815260209283019201611a2c565b600554811015611a8157600560005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b9181601f840112156103145782359167ffffffffffffffff8311610314576020808501948460051b01011161031457565b919082018092116104c157565b818102929181159184041417156104c157565b919082039182116104c157565b3d15611b30573d9067ffffffffffffffff82116109535760405191611b24601f8201601f191660200184611979565b82523d6000602084013e565b606090565b601154908115611bda57611b498242611ae8565b601c546064611b588285611ad5565b0493601b5490818410600014611b7057505050505090565b601a54949593611b808684611ac8565b11611b8d57505050505090565b611ba491611b9e9196949596611ac8565b42611ae8565b90606403606481116104c157611bbf606491611bc594611ad5565b04611ad5565b91801561167157611bd7920490611ac8565b90565b5050600090565b8051821015611a815760209160051b010190565b90816020910312610314575180151581036103145790565b9190811015611a815760051b0190565b90816020910312610314575190565b6000546001600160a01b03163303611c4057565b63118cdaa760e01b6000523360045260246000fd5b6021546040516331a9108f60e11b81526004810183905260309190911c6001600160a01b03169190602081602481865afa9081156104a457600091611dd7575b506001600160a01b031691338314611db057604051632e7cda1d60e21b81523360048201526024810184905260448101829052606481018390526000608482015260208160a4817f00000000000000000000000000000000000000447e69651d841bd8d104bed4936001600160a01b03165afa9081156104a457600091611db8575b50611db057604051631574d39f60e31b81523360048201526024810193909352604483015260648201526020816084817f00000000000000000000000000000000000076a84fef008cdabe6409d2fe638b6001600160a01b03165afa9081156104a457600091611d91575b50611d8c57600090565b600190565b611daa915060203d60201161049d576104958183611979565b38611d82565b505050600190565b611dd1915060203d60201161049d576104958183611979565b38611d17565b6020813d602011611e18575b81611df060209383611979565b81010312611e145751906001600160a01b0382168203611e11575038611c95565b80fd5b5080fd5b3d9150611de356fea2646970667358221220750f3b635c6a5b231aad4a74db8a5d18531a18fbffe87b6ca0007cb9a2a6374064736f6c634300081a0033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.