Feature Tip: Add private address tag to any address under My Name Tag !
ERC-20
Overview
Max Total Supply
432,605,435.633053966618854454 claimRISE
Holders
14
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 18 Decimals)
Balance
0 claimRISEValue
$0.00Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
claimRise
Compiler Version
v0.8.13+commit.abaa5c0e
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2022-04-04 */ // Copyright (c) 2022 EverRise Pte Ltd. All rights reserved. // EverRise licenses this file to you under the MIT license. /* Virtual token that allows unclaimed rewards from EverRise Staking NFTs and its Vote Escrowed (ve) EverRise to display in wallet balances. ________ _______ __ / | / \ / | $$$$$$$$/__ __ ______ ______ $$$$$$$ |$$/ _______ ______ v3.14159265 $$ |__ / \ / |/ \ / \ $$ |__$$ |/ | / | / \ ______ _____ $$ | $$ \ /$$//$$$$$$ |/$$$$$$ |$$ $$< $$ |/$$$$$$$/ /$$$$$$ | _________ /_____ ___(_)______ ___ $$$$$/ $$ /$$/ $$ $$ |$$ | $$/ $$$$$$$ |$$ |$$ \ $$ $$ | _ ___/_ /_ __ `/_ /__ __ `__ \$$ |_____ $$ $$/ $$$$$$$$/ $$ | $$ | $$ |$$ | $$$$$$ |$$$$$$$$/ / /__ _ / / /_/ /_ / _ / / / / /$$ | $$$/ $$ |$$ | $$ | $$ |$$ |/ $$/ $$ | \___/ /_/ \__,_/ /_/ /_/ /_/ /_/ $$$$$$$$/ $/ $$$$$$$/ $$/ $$/ $$/ $$/ $$$$$$$/ $$$$$$$/ Learn more about EverRise and the EverRise Ecosystem of dApps and how our utilities and partners can help protect your investors and help your project grow: https://www.everrise.com */ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; error NotZeroAddress(); // 0x66385fa3 error CallerNotApproved(); // 0x4014f1a5 error InvalidAddress(); // 0xe6c4247b error CallerNotOwner(); error WalletLocked(); // 0xd550ed24 error DoesNotExist(); // 0xb0ce7591 error AmountMustBeGreaterThanZero(); // 0x5e85ae73 error AmountOutOfRange(); // 0xc64200e9 error StakeStillLocked(); // 0x7f6699f6 error NotStakerAddress(); // 0x2a310a0c error AmountLargerThanAvailable(); // 0xbb296109 error StakeCanOnlyBeExtended(); // 0x73f7040a error ArrayLengthsMismatch(); // 0x3b800a46 error NotSetup(); // 0xb09c99c0 error NotAllowedToCreateRewards(); // 0xfdc42f29 error NotAllowedToDeliverRewards(); // 0x69a3e246 error ERC721ReceiverReject(); // 0xfa34343f error ERC721ReceiverNotImplemented(); // 0xa89c6c0d error NotEnoughToCoverStakeFee(); // 0x627554ed error AmountLargerThanAllowance(); // 0x9b144c57 error AchievementNotClaimed(); // 0x3834dd9c error AchievementAlreadyClaimed(); // 0x2d5345f4 error AmountMustBeAnInteger(); // 0x743aec61 error BrokenStatusesDiffer(); // 0x097b027d error AchievementClaimStatusesDiffer(); // 0x6524e8b0 error UnlockedStakesMustBeSametimePeriod();// 0x42e227b0 error CannotMergeLockedAndUnlockedStakes();// 0x9efeef2c error StakeUnlocked(); // 0x6717a455 error NoRewardsToClaim(); // 0x73380d99 error NotTransferrable(); // 0x54ee5151 error Overflow(); // 0x35278d12 error MergeNotEnabled(); // 0x // File: EverRise-v3/Interfaces/IERC173-Ownable.sol interface IOwnable { event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); function owner() external view returns (address); function transferOwnership(address newOwner) external; } // File: EverRise-v3/Abstract/Context.sol abstract contract Context { function _msgSender() internal view virtual returns (address payable) { return payable(msg.sender); } } // File: EverRise-v3/Abstract/ERC173-Ownable.sol contract Ownable is IOwnable, Context { address public owner; function _onlyOwner() private view { if (owner != _msgSender()) revert CallerNotOwner(); } modifier onlyOwner() { _onlyOwner(); _; } constructor() { address msgSender = _msgSender(); owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } // Allow contract ownership and access to contract onlyOwner functions // to be locked using EverOwn with control gated by community vote. // // EverRise ($RISE) stakers become voting members of the // decentralized autonomous organization (DAO) that controls access // to the token contract via the EverRise Ecosystem dApp EverOwn function transferOwnership(address newOwner) external virtual onlyOwner { if (newOwner == address(0)) revert NotZeroAddress(); emit OwnershipTransferred(owner, newOwner); owner = newOwner; } } struct ApprovalChecks { // Prevent permits being reused (IERC2612) uint64 nonce; // Allow revoke all spenders/operators approvals in single txn uint32 nftCheck; uint32 tokenCheck; // Allow auto timeout on approvals uint16 autoRevokeNftHours; uint16 autoRevokeTokenHours; // Allow full wallet locking of all transfers uint48 unlockTimestamp; } struct Allowance { uint128 tokenAmount; uint32 nftCheck; uint32 tokenCheck; uint48 timestamp; uint8 nftApproval; uint8 tokenApproval; } interface IEverRiseWallet { event RevokeAllApprovals(address indexed account, bool tokens, bool nfts); event SetApprovalAutoTimeout(address indexed account, uint16 tokensHrs, uint16 nftsHrs); event LockWallet(address indexed account, address altAccount, uint256 length); event LockWalletExtend(address indexed account, uint256 length); } // File: EverRise-v3/Interfaces/IERC20-Token.sol interface IERC20 { event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); function increaseAllowance(address spender, uint256 addedValue) external returns (bool); function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); function transferFromWithPermit(address sender, address recipient, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external returns (bool); } interface IERC20Metadata is IERC20 { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); } // File: EverRise-v3/Interfaces/IEverRise.sol interface IEverRise is IERC20Metadata { function totalBuyVolume() external view returns (uint256); function totalSellVolume() external view returns (uint256); function holders() external view returns (uint256); function uniswapV2Pair() external view returns (address); function transferStake(address fromAddress, address toAddress, uint96 amountToTransfer) external; function isWalletLocked(address fromAddress) external view returns (bool); function setApprovalForAll(address fromAddress, address operator, bool approved) external; function isApprovedForAll(address account, address operator) external view returns (bool); function isExcludedFromFee(address account) external view returns (bool); function approvals(address operator) external view returns (ApprovalChecks memory); } // File: EverRise-v3/Interfaces/IERC721-Nft.sol interface IERC721 /* is ERC165 */ { event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); function balanceOf(address _owner) external view returns (uint256); function ownerOf(uint256 _tokenId) external view returns (address); function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable; function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable; function transferFrom(address _from, address _to, uint256 _tokenId) external payable; function approve(address _approved, uint256 _tokenId) external payable; function setApprovalForAll(address _operator, bool _approved) external; function getApproved(uint256 _tokenId) external view returns (address); function isApprovedForAll(address _owner, address _operator) external view returns (bool); } // File: EverRise-v3/Interfaces/InftEverRise.sol struct StakingDetails { uint96 initialTokenAmount; // Max 79 Bn tokens uint96 withdrawnAmount; // Max 79 Bn tokens uint48 depositTime; // 8 M years uint8 numOfMonths; // Max 256 month period uint8 achievementClaimed; // 256 bits, 20000 gwei gas address stakerAddress; // 160 bits (96 bits remaining) uint32 nftId; // Max 4 Bn nfts issued uint32 lookupIndex; // Max 4 Bn active stakes uint24 stakerIndex; // Max 16 M active stakes per wallet uint8 isActive; // 256 bits, 20000 gwei gas } // Total 768 bits, 40000 gwei gas interface InftEverRise is IERC721 { function voteEscrowedBalance(address account) external view returns (uint256); function unclaimedRewardsBalance(address account) external view returns (uint256); function totalAmountEscrowed() external view returns (uint256); function totalAmountVoteEscrowed() external view returns (uint256); function totalRewardsDistributed() external view returns (uint256); function totalRewardsUnclaimed() external view returns (uint256); function createRewards(uint256 tAmount) external; function getNftData(uint256 id) external view returns (StakingDetails memory); function enterStaking(address fromAddress, uint96 amount, uint8 numOfMonths) external returns (uint32 nftId); function leaveStaking(address fromAddress, uint256 id, bool overrideNotClaimed) external returns (uint96 amount); function earlyWithdraw(address fromAddress, uint256 id, uint96 amount) external returns (uint32 newNftId, uint96 penaltyAmount); function withdraw(address fromAddress, uint256 id, uint96 amount, bool overrideNotClaimed) external returns (uint32 newNftId); function bridgeStakeNftOut(address fromAddress, uint256 id) external returns (uint96 amount); function bridgeOrAirdropStakeNftIn(address toAddress, uint96 depositAmount, uint8 numOfMonths, uint48 depositTime, uint96 withdrawnAmount, uint96 rewards, bool achievementClaimed) external returns (uint32 nftId); function addStaker(address staker, uint256 nftId) external; function removeStaker(address staker, uint256 nftId) external; function reissueStakeNft(address staker, uint256 oldNftId, uint256 newNftId) external; function increaseStake(address staker, uint256 nftId, uint96 amount) external returns (uint32 newNftId, uint96 original, uint8 numOfMonths); function splitStake(uint256 id, uint96 amount) external payable returns (uint32 newNftId0, uint32 newNftId1); function claimAchievement(address staker, uint256 nftId) external returns (uint32 newNftId); function stakeCreateCost() external view returns (uint256); function approve(address owner, address _operator, uint256 nftId) external; } // File: EverRise-v3/Abstract/virtualToken.sol abstract contract virtualToken is Ownable, IERC20, IERC20Metadata { InftEverRise public veEverRise; uint8 public constant decimals = 18; string public name; string public symbol; constructor(string memory _name, string memory _symbol ) { name = _name; symbol = _symbol; veEverRise = InftEverRise(owner); } function transferFrom(address sender, address recipient, uint256 amount) external returns (bool) { if (_msgSender() != owner) { notTransferrable(); } emit Transfer(sender, recipient, amount); return true; } function transfer(address, uint256) pure external returns (bool) { notTransferrable(); } function allowance(address, address) pure external returns (uint256) { return 0; } function approve(address, uint256) pure external returns (bool) { notTransferrable(); } function increaseAllowance(address, uint256) pure external returns (bool) { notTransferrable(); } function decreaseAllowance(address, uint256) pure external returns (bool) { notTransferrable(); } function transferFromWithPermit(address, address, uint256, uint256, uint8, bytes32, bytes32) pure external returns (bool) { notTransferrable(); } function notTransferrable() pure private { revert NotTransferrable(); } } // File: EverRise-v3/claimRISE.sol // Copyright (c) 2022 EverRise Pte Ltd. All rights reserved. // EverRise licenses this file to you under the MIT license. /* Virtual token that allows unclaimed rewards from EverRise Staking NFTs and its Vote Escrowed (ve) EverRise to display in wallet balances. ________ _______ __ / | / \ / | $$$$$$$$/__ __ ______ ______ $$$$$$$ |$$/ _______ ______ v3.14159265 $$ |__ / \ / |/ \ / \ $$ |__$$ |/ | / | / \ ______ _____ $$ | $$ \ /$$//$$$$$$ |/$$$$$$ |$$ $$< $$ |/$$$$$$$/ /$$$$$$ | _________ /_____ ___(_)______ ___ $$$$$/ $$ /$$/ $$ $$ |$$ | $$/ $$$$$$$ |$$ |$$ \ $$ $$ | _ ___/_ /_ __ `/_ /__ __ `__ \$$ |_____ $$ $$/ $$$$$$$$/ $$ | $$ | $$ |$$ | $$$$$$ |$$$$$$$$/ / /__ _ / / /_/ /_ / _ / / / / /$$ | $$$/ $$ |$$ | $$ | $$ |$$ |/ $$/ $$ | \___/ /_/ \__,_/ /_/ /_/ /_/ /_/ $$$$$$$$/ $/ $$$$$$$/ $$/ $$/ $$/ $$/ $$$$$$$/ $$$$$$$/ Learn more about EverRise and the EverRise Ecosystem of dApps and how our utilities and partners can help protect your investors and help your project grow: https://www.everrise.com */ contract claimRise is virtualToken("EverRise Rewards", "claimRISE") { function totalSupply() override external view returns (uint256) { return veEverRise.totalRewardsUnclaimed(); } function balanceOf(address account) override external view returns (uint256) { if (account == owner) return 0; return veEverRise.unclaimedRewardsBalance(account); } } // File: EverRise-v3/veRISE.sol // Copyright (c) 2022 EverRise Pte Ltd. All rights reserved. // EverRise licenses this file to you under the MIT license. /* Virtual token that allows the Vote Escrowed (ve) EverRise weigthed governance tokens from EverRise Staking NFTs to display in wallet balances. ________ _______ __ / | / \ / | $$$$$$$$/__ __ ______ ______ $$$$$$$ |$$/ _______ ______ v3.14159265 $$ |__ / \ / |/ \ / \ $$ |__$$ |/ | / | / \ $$ | $$ \ /$$//$$$$$$ |/$$$$$$ |$$ $$< $$ |/$$$$$$$/ /$$$$$$ | __ _____ $$$$$/ $$ /$$/ $$ $$ |$$ | $$/ $$$$$$$ |$$ |$$ \ $$ $$ | \ \ / / _ \ $$ |_____ $$ $$/ $$$$$$$$/ $$ | $$ | $$ |$$ | $$$$$$ |$$$$$$$$/ \ V / __/ $$ | $$$/ $$ |$$ | $$ | $$ |$$ |/ $$/ $$ | \_/ \___| $$$$$$$$/ $/ $$$$$$$/ $$/ $$/ $$/ $$/ $$$$$$$/ $$$$$$$/ Learn more about EverRise and the EverRise Ecosystem of dApps and how our utilities and partners can help protect your investors and help your project grow: https://www.everrise.com */ contract veRise is virtualToken("Vote-escrowed EverRise", "veRISE") { function totalSupply() override external view returns (uint256) { return veEverRise.totalAmountVoteEscrowed(); } function balanceOf(address account) override external view returns (uint256) { if (account == owner) return 0; return veEverRise.voteEscrowedBalance(account); } } // File: EverRise-v3/Interfaces/IEverRoyaltySplitter.sol interface IEverRoyaltySplitter { event RoyaltiesSplit(uint256 value); event SplitUpdated(uint256 previous, uint256 current); event UniswapV2RouterSet(address indexed previous, address indexed current); event EverRiseEcosystemSet(address indexed previous, address indexed current); event EverRiseTokenSet(address indexed previous, address indexed current); event StableCoinSet(address indexed previous, address indexed current); function distribute() external; } /// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02. interface IERC721TokenReceiver { function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) external view returns(bytes4); } interface IERC721Metadata /* is ERC721 */ { function name() external view returns (string memory _name); function symbol() external view returns (string memory _symbol); function tokenURI(uint256 _tokenId) external view returns (string memory); } interface IERC721Enumerable /* is ERC721 */ { function totalSupply() external view returns (uint256); function tokenByIndex(uint256 _index) external view returns (uint256); function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256); } // File: EverRise-v3/Interfaces/IEverRiseRenderer.sol interface IOpenSeaCollectible { function contractURI() external view returns (string memory); } interface IEverRiseRenderer is IOpenSeaCollectible { event SetEverRiseNftStakes(address indexed addressStakes); event SetEverRiseRendererGlyph(address indexed addressGlyphs); function tokenURI(uint256 _tokenId) external view returns (string memory); function everRiseNftStakes() external view returns (InftEverRise); function setEverRiseNftStakes(address contractAddress) external; } // File: EverRise-v3/Interfaces/IERC165-SupportsInterface.sol interface IERC165 { function supportsInterface(bytes4 interfaceId) external view returns (bool); } // File: EverRise-v3/Abstract/ERC165-SupportsInterface.sol abstract contract ERC165 is IERC165 { function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } } // File: EverRise-v3/Interfaces/IERC2981-Royalty.sol interface IERC2981 is IERC165 { function royaltyInfo(uint256 _tokenId, uint256 _salePrice) external view returns ( address receiver, uint256 royaltyAmount ); } // File: EverRise-v3/nftEverRise.sol // Copyright (c) 2022 EverRise Pte Ltd. All rights reserved. // EverRise licenses this file to you under the MIT license. /* EverRise Staking NFTs are Vote Escrowed (ve) EverRise weigthed governance tokens which generate rewards with a market driven yield curve, based of the transaction volume of EverRise trades and veEverRise sales. On sales of veEverRise Staking NFTs a 10% royalty fee is collected * 6% for token Buyback from the market, with bought back tokens directly distributed as ve-staking rewards * 4% for Business Development (Development, Sustainability and Marketing) ________ _______ __ / | / \ / | $$$$$$$$/__ __ ______ ______ $$$$$$$ |$$/ _______ ______ v3.14159265 $$ |__ / \ / |/ \ / \ $$ |__$$ |/ | / | / \ $$ | $$ \ /$$//$$$$$$ |/$$$$$$ |$$ $$< $$ |/$$$$$$$/ /$$$$$$ | _______ _______ _______ $$$$$/ $$ /$$/ $$ $$ |$$ | $$/ $$$$$$$ |$$ |$$ \ $$ $$ | | | | ___|_ _| $$ |_____ $$ $$/ $$$$$$$$/ $$ | $$ | $$ |$$ | $$$$$$ |$$$$$$$$/ | | ___| | | $$ | $$$/ $$ |$$ | $$ | $$ |$$ |/ $$/ $$ | |__|____|___| |___| $$$$$$$$/ $/ $$$$$$$/ $$/ $$/ $$/ $$/ $$$$$$$/ $$$$$$$/ Learn more about EverRise and the EverRise Ecosystem of dApps and how our utilities and partners can help protect your investors and help your project grow: https://www.everrise.com */ contract EverRiseTokenOwned is Ownable { IEverRise public everRiseToken; event EverRiseTokenSet(address indexed tokenAddress); function _onlyEverRiseToken(address senderAddress) private view { if (address(everRiseToken) == address(0)) revert NotSetup(); if (address(everRiseToken) != senderAddress) revert CallerNotApproved(); } modifier onlyEverRiseToken() { _onlyEverRiseToken(_msgSender()); _; } } struct IndividualAllowance { address operator; uint48 timestamp; uint32 nftCheck; } abstract contract nftEverRiseConfigurable is EverRiseTokenOwned, InftEverRise, ERC165, IERC2981, IERC721Metadata, IOpenSeaCollectible { event AddRewardCreator(address indexed _address); event RemoveRewardCreator(address indexed _address); event SetAchievementNfts(address indexed _address); event RoyaltyFeeUpdated(uint256 newValue); event RoyaltyAddressUpdated(address indexed contractAddress); event RendererAddressUpdated(address indexed contractAddress); event StakeCreateCostUpdated(uint256 newValue); event StakingParametersSet(uint256 withdrawPct, uint256 firstHalfPenality, uint256 secondHalfPenality, uint256 maxStakeMonths, bool mergeEnabled); IEverRiseRenderer public renderer; IEverRoyaltySplitter public royaltySplitter; uint256 public nftRoyaltySplit = 10; address public currentAchievementNfts; uint8 public maxEarlyWithdrawalPercent = 60; uint8 public firstHalfPenality = 25; uint8 public secondHalfPenality = 10; uint8 public maxStakeMonths = 36; uint256 public stakeCreateCost = 1 * 10**18 / (10**2); uint256 public mergeEnabled = _FALSE; // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. uint256 constant _FALSE = 1; uint256 constant _TRUE = 2; mapping (address => bool) internal _canCreateRewards; function setEverRiseToken(address tokenAddress) external onlyOwner { if (tokenAddress == address(0)) revert NotZeroAddress(); _removeAddressToCreate(address(everRiseToken)); addAddressToCreate(tokenAddress); everRiseToken = IEverRise(tokenAddress); emit EverRiseTokenSet(tokenAddress); } function setStakeCreateCost(uint256 _stakeCreateCost, uint256 numOfDecimals) external onlyOwner { // Catch typos, if decimals are pre-added if (_stakeCreateCost > 1_000) revert AmountOutOfRange(); stakeCreateCost = _stakeCreateCost * (10**18) / (10**numOfDecimals); emit StakeCreateCostUpdated(_stakeCreateCost); } function setAchievementNfts(address contractAddress) external onlyOwner() { if (contractAddress == address(0)) revert NotZeroAddress(); currentAchievementNfts = contractAddress; emit SetAchievementNfts(contractAddress); } function addAddressToCreate(address account) public onlyOwner { if (account == address(0)) revert NotZeroAddress(); _canCreateRewards[account] = true; emit AddRewardCreator(account); } function removeAddressToCreate(address account) external onlyOwner { if (account == address(0)) revert NotZeroAddress(); _removeAddressToCreate(account); } function _removeAddressToCreate(address account) private { if (account != address(0)){ _canCreateRewards[account] = false; emit RemoveRewardCreator(account); } } function setNftRoyaltyFeePercent(uint256 royaltySplitRate) external onlyOwner { if (royaltySplitRate > 10) revert AmountOutOfRange(); nftRoyaltySplit = royaltySplitRate; emit RoyaltyFeeUpdated(royaltySplitRate); } function setRoyaltyAddress(address newAddress) external onlyOwner { if (newAddress == address(0)) revert NotZeroAddress(); royaltySplitter = IEverRoyaltySplitter(newAddress); emit RoyaltyAddressUpdated(newAddress); } function setRendererAddress(address newAddress) external onlyOwner { if (newAddress == address(0)) revert NotZeroAddress(); renderer = IEverRiseRenderer(newAddress); emit RendererAddressUpdated(newAddress); } function setStakingParameters(uint8 _withdrawPercent, uint8 _firstHalfPenality, uint8 _secondHalfPenality, uint8 _maxStakeMonths, bool _mergEnabled) external onlyOwner { if (_maxStakeMonths == 0 || _maxStakeMonths > 120) { revert AmountOutOfRange(); } maxEarlyWithdrawalPercent = _withdrawPercent; firstHalfPenality = _firstHalfPenality; secondHalfPenality = _secondHalfPenality; maxStakeMonths = _maxStakeMonths; mergeEnabled = _mergEnabled ? _TRUE : _FALSE; emit StakingParametersSet(_withdrawPercent, _firstHalfPenality, _secondHalfPenality, _maxStakeMonths, _mergEnabled); } } contract nftEverRise is nftEverRiseConfigurable { string public constant name = "EverRise NFT Stakes"; string public constant symbol = "nftRISE"; uint256 public constant month = 30 days; uint256 private constant MAX = ~uint256(0); uint8 public constant decimals = 0; uint256 private constant totalStakeTokensSupply = 120_000_000 * 10**6 * 10**18; uint8 constant _FALSE8 = 1; uint8 constant _TRUE8 = 2; event RewardsWithdrawn(address indexed from, uint256 amount); event ExcludedFromRewards(address indexed _address); event IncludedToRewards(address indexed _address); mapping (address => bool) private _isExcludedFromReward; mapping (address => uint256) private _rOwned; mapping (address => uint256) private _tOwned; mapping (address => uint256) private _withdrawnRewards; mapping (uint256 => IndividualAllowance) private _individualApproval; address[] private _excludedList; uint256 private _rTotal = (MAX - (MAX % totalStakeTokensSupply)); StakingDetails[] private _allStakeDetails; mapping (address => uint256[]) private _individualStakes; mapping (uint256 => uint256) private _stakeById; uint256[] private _freeStakes; mapping (address => uint256) public voteEscrowedBalance; uint256 public totalAmountEscrowed; uint256 public totalAmountVoteEscrowed; uint256 public totalRewardsDistributed; uint32 private nextNftId = 1; veRise public immutable veRiseToken; claimRise public immutable claimRiseToken; constructor() { veRiseToken = new veRise(); claimRiseToken = new claimRise(); _rOwned[address(this)] = _rTotal; excludeFromReward(address(this)); _allStakeDetails.push(StakingDetails({ initialTokenAmount: 0, withdrawnAmount: 0, depositTime: 0, numOfMonths: 1, achievementClaimed: 0, stakerAddress: address(0), nftId: 0, lookupIndex: 0, stakerIndex: 0, isActive: _FALSE8 })); } function _walletLock(address fromAddress) private view { if (everRiseToken.isWalletLocked(fromAddress)) revert WalletLocked(); } modifier walletLock(address fromAddress) { _walletLock(fromAddress); _; } function totalSupply() external view returns (uint256) { return _allStakeDetails.length - _freeStakes.length - 1; } function _onlyRewardCreator(address senderAddress) private view { if (!_canCreateRewards[senderAddress]) revert CallerNotApproved(); } modifier onlyRewardCreator() { _onlyRewardCreator(_msgSender()); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override (ERC165, IERC165) returns (bool) { return interfaceId == type(IERC2981).interfaceId || interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } function contractURI() external view returns (string memory) { return renderer.contractURI(); } function tokenURI(uint256 nftId) external view returns (string memory) { return renderer.tokenURI(nftId); } function createRewards(uint256 amount) external onlyRewardCreator() { address sender = _msgSender(); if (_isExcludedFromReward[sender]) revert NotAllowedToDeliverRewards(); _transferFromExcluded(address(this), sender, amount); totalRewardsDistributed += amount; uint256 rAmount = amount * _getRate(); _rOwned[sender] -= rAmount; _rTotal -= rAmount; claimRiseToken.transferFrom(address(0), address(this), amount); } function voteEscrowedAndRewards(address account) private view returns (uint256) { if (account == address(0)) revert NotZeroAddress(); if (_isExcludedFromReward[account]) return _tOwned[account]; return tokenFromRewards(_rOwned[account]); } function totalRewardsUnclaimed() external view returns (uint256) { return everRiseToken.balanceOf(address(this)); } function isExcludedFromReward(address account) external view returns (bool) { if (account == address(0)) revert NotZeroAddress(); return _isExcludedFromReward[account]; } function rewardsFromToken(uint256 tAmount) external view returns(uint256) { if (tAmount > totalStakeTokensSupply) revert AmountOutOfRange(); return tAmount * _getRate(); } function tokenFromRewards(uint256 rAmount) public view returns(uint256) { if (rAmount > _rTotal) revert AmountOutOfRange(); uint256 currentRate = _getRate(); return rAmount / currentRate; } function excludeFromReward(address account) public onlyOwner() { if (account == address(0)) revert NotZeroAddress(); if (_isExcludedFromReward[account]) revert InvalidAddress(); if(_rOwned[account] > 0) { _tOwned[account] = tokenFromRewards(_rOwned[account]); } _isExcludedFromReward[account] = true; _excludedList.push(account); emit ExcludedFromRewards(account); } function includeInReward(address account) external onlyOwner() { if (account == address(0)) revert NotZeroAddress(); if (!_isExcludedFromReward[account]) revert InvalidAddress(); uint256 length = _excludedList.length; for (uint256 i = 0; i < length;) { if (_excludedList[i] == account) { _excludedList[i] = _excludedList[_excludedList.length - 1]; _tOwned[account] = 0; _isExcludedFromReward[account] = false; _excludedList.pop(); break; } unchecked { ++i; } } emit IncludedToRewards(account); } function _transfer( address sender, address recipient, uint256 amount, bool emitEvent ) private { if (sender == address(0)) revert NotZeroAddress(); if (recipient == address(0)) revert NotZeroAddress(); if (amount == 0) revert AmountMustBeGreaterThanZero(); // One of the addresses has to be this contract if (sender != address(this) && recipient != address(this)) revert InvalidAddress(); if (_isExcludedFromReward[sender]) { if (!_isExcludedFromReward[recipient]) { _transferFromExcluded(sender, recipient, amount); } else { _transferBothExcluded(sender, recipient, amount); } } else if (_isExcludedFromReward[recipient]) { _transferToExcluded(sender, recipient, amount); } else { _transferStandard(sender, recipient, amount); } if (emitEvent) { if (sender == address(this)) { veRiseToken.transferFrom(address(0), recipient, amount); } else if (recipient == address(this)) { veRiseToken.transferFrom(sender, address(0), amount); } } } function _transferStandard(address sender, address recipient, uint256 tAmount) private { uint256 rAmount = tAmount * _getRate(); _rOwned[sender] -= rAmount; _rOwned[recipient] += rAmount; } function _transferToExcluded(address sender, address recipient, uint256 tAmount) private { uint256 rAmount = tAmount * _getRate(); _rOwned[sender] -= rAmount; _tOwned[recipient] += tAmount; _rOwned[recipient] += rAmount; } function _transferFromExcluded(address sender, address recipient, uint256 tAmount) private { uint256 rAmount = tAmount * _getRate(); _tOwned[sender] -= tAmount; _rOwned[sender] -= rAmount; _rOwned[recipient] += rAmount; } function _transferBothExcluded(address sender, address recipient, uint256 tAmount) private { uint256 rAmount = tAmount * _getRate(); _tOwned[sender] -= tAmount; _rOwned[sender] -= rAmount; _tOwned[recipient] += tAmount; _rOwned[recipient] += rAmount; } function _getRate() private view returns(uint256) { (uint256 rSupply, uint256 tSupply) = _getCurrentSupply(); return rSupply / tSupply; } function _getCurrentSupply() private view returns(uint256, uint256) { uint256 rSupply = _rTotal; uint256 tSupply = totalStakeTokensSupply; uint256 length = _excludedList.length; for (uint256 i = 0; i < length;) { if (_rOwned[_excludedList[i]] > rSupply || _tOwned[_excludedList[i]] > tSupply) { return (_rTotal, totalStakeTokensSupply); } rSupply -= _rOwned[_excludedList[i]]; tSupply -= _tOwned[_excludedList[i]]; unchecked { ++i; } } if (rSupply < (_rTotal / totalStakeTokensSupply)) return (_rTotal, totalStakeTokensSupply); return (rSupply, tSupply); } function getStakeIndex(uint256 nftId) private view returns (uint256 lookupIndex) { if (nftId == 0) revert DoesNotExist(); lookupIndex = _stakeById[nftId]; if (lookupIndex >= _allStakeDetails.length) revert DoesNotExist(); if (_allStakeDetails[lookupIndex].isActive != _TRUE8) revert DoesNotExist(); } function ownerOf(uint256 nftId) public view returns (address) { uint256 lookupIndex = getStakeIndex(nftId); StakingDetails storage stakeDetails = _allStakeDetails[lookupIndex]; return stakeDetails.stakerAddress; } function _getStake(uint256 nftId, address staker) private view returns (uint256 lookupIndex, StakingDetails storage stakeDetails) { lookupIndex = getStakeIndex(nftId); stakeDetails = _allStakeDetails[lookupIndex]; if (stakeDetails.stakerAddress != staker) revert NotStakerAddress(); assert(nftId == stakeDetails.nftId); } function getStake(uint256 nftId, address staker) external view returns (StakingDetails memory stakeDetails) { (, stakeDetails) = _getStake(nftId, staker); } function getNftData(uint256 nftId) external view returns (StakingDetails memory) { uint256 lookupIndex = getStakeIndex(nftId); return _allStakeDetails[lookupIndex]; } function balanceOf(address account) external view returns (uint256) { return _individualStakes[account].length; } function unclaimedRewardsBalance(address account) public view returns (uint256) { return voteEscrowedAndRewards(account) - voteEscrowedBalance[account]; } function getTotalRewards(address account) external view returns (uint256) { return unclaimedRewardsBalance(account) + _withdrawnRewards[account]; } function tokenOfOwnerByIndex(address _owner, uint256 index) external view returns (uint32) { uint256[] storage stakes = _individualStakes[_owner]; if (index > stakes.length) revert AmountOutOfRange(); uint256 lookupIndex = stakes[index]; return _allStakeDetails[lookupIndex].nftId; } function enterStaking(address staker, uint96 amount, uint8 numOfMonths) external onlyEverRiseToken returns (uint32 nftId) { // Stake time period must be in valid range if (numOfMonths == 0 || numOfMonths > maxStakeMonths || (numOfMonths > 12 && (numOfMonths % 12) > 0) ) { revert AmountOutOfRange(); } roundingCheck(amount, false); nftId = _createStake(staker, amount, 0, numOfMonths, uint48(block.timestamp), false); } // Rewards withdrawal doesn't need token lock check as is adding to locked wallet not removing function withdrawRewards() external { address staker = _msgSender(); uint256 rewards = unclaimedRewardsBalance(staker); if (rewards == 0) revert NoRewardsToClaim(); // Something to withdraw _withdrawnRewards[staker] += rewards; // Remove the veTokens for the rewards _transfer(staker, address(this), rewards, false); // Emit transfer claimRiseToken.transferFrom(staker, address(0), rewards); // Send RISE rewards require(everRiseToken.transfer(staker, rewards)); emit RewardsWithdrawn(staker, rewards); } function checkNotLocked(uint256 depositTime, uint256 numOfMonths) private view { if (depositTime + (numOfMonths * month) > block.timestamp) { revert StakeStillLocked(); } } function leaveStaking(address staker, uint256 nftId, bool overrideNotClaimed) external onlyEverRiseToken returns (uint96 amount) { (uint256 lookupIndex, StakingDetails storage stakeDetails) = _getStake(nftId, staker); checkNotLocked(stakeDetails.depositTime, stakeDetails.numOfMonths); if (!overrideNotClaimed && stakeDetails.achievementClaimed != _TRUE8) { revert AchievementNotClaimed(); } amount = _removeStake(staker, nftId, lookupIndex, stakeDetails); } function withdraw(address staker, uint256 nftId, uint96 amount, bool overrideNotClaimed) external onlyEverRiseToken returns (uint32 newNftId) { (uint256 lookupIndex, StakingDetails storage stakeDetails) = _getStake(nftId, staker); checkNotLocked(stakeDetails.depositTime, stakeDetails.numOfMonths); if (!overrideNotClaimed && stakeDetails.achievementClaimed != _TRUE8) { revert AchievementNotClaimed(); } uint96 remaining = stakeDetails.initialTokenAmount - stakeDetails.withdrawnAmount; if (amount > remaining) revert AmountLargerThanAvailable(); roundingCheck(amount, true); bool reissueNft = false; if (amount > 0) { decreaseVeAmount(staker, amount, stakeDetails.numOfMonths, true); // Out of period, inital now becomes remaining remaining -= amount; reissueNft = true; } if (stakeDetails.initialTokenAmount != remaining) { // Out of period, zero out the withdrawal amount stakeDetails.initialTokenAmount = remaining; stakeDetails.withdrawnAmount = 0; reissueNft = true; } if (reissueNft) { if (remaining == 0) { _burnStake(staker, nftId, lookupIndex, stakeDetails); newNftId = 0; } else { newNftId = _reissueStakeNftId(nftId, lookupIndex); stakeDetails.nftId = newNftId; } } else { // Nothing changed, keep the same nft newNftId = uint32(nftId); } } function claimAchievement(address staker, uint256 nftId) external returns (uint32 newNftId) { if (_msgSender() != currentAchievementNfts) revert CallerNotApproved(); (uint256 lookupIndex, StakingDetails storage stakeDetails) = _getStake(nftId, staker); checkNotLocked(stakeDetails.depositTime, stakeDetails.numOfMonths); // Can only claim once if (stakeDetails.achievementClaimed == _TRUE8) { revert AchievementAlreadyClaimed(); } // Reset broken status if unlocked if (stakeDetails.withdrawnAmount > 0) { stakeDetails.initialTokenAmount -= stakeDetails.withdrawnAmount; stakeDetails.withdrawnAmount = 0; } // Mark claimed stakeDetails.achievementClaimed = _TRUE8; // Get new id newNftId = _reissueStakeNftId(nftId, lookupIndex); // Set new id stakeDetails.nftId = newNftId; // Emit burn and mint events _reissueStakeNft(staker, nftId, newNftId); } function getTime() external view returns (uint256) { // Used to workout UI time drift from blockchain return block.timestamp; } function checkLocked(uint48 depositTime, uint8 numOfMonths) private view { if (depositTime + (numOfMonths * month) < block.timestamp) { revert StakeUnlocked(); } } function earlyWithdraw(address staker, uint256 nftId, uint96 amount) external onlyEverRiseToken returns (uint32 newNftId, uint96 penaltyAmount) { (uint256 lookupIndex, StakingDetails storage stakeDetails) = _getStake(nftId, staker); checkLocked(stakeDetails.depositTime, stakeDetails.numOfMonths); uint256 remaingEarlyWithdrawal = (stakeDetails.initialTokenAmount * maxEarlyWithdrawalPercent) / 100 - stakeDetails.withdrawnAmount; if (amount > remaingEarlyWithdrawal) { revert AmountLargerThanAvailable(); } roundingCheck(amount, false); decreaseVeAmount(staker, amount, stakeDetails.numOfMonths, true); penaltyAmount = calculateTax(amount, stakeDetails.depositTime, stakeDetails.numOfMonths); // calculate early penalty tax stakeDetails.withdrawnAmount += uint96(amount); // update the withdrawl amount newNftId = _reissueStakeNftId(nftId, lookupIndex); stakeDetails.nftId = newNftId; } function increaseStake(address staker, uint256 nftId, uint96 amount) external onlyEverRiseToken returns (uint32 newNftId, uint96 original, uint8 numOfMonths) { (uint256 lookupIndex, StakingDetails storage stakeDetails) = _getStake(nftId, staker); checkLocked(stakeDetails.depositTime, stakeDetails.numOfMonths); roundingCheck(amount, false); numOfMonths = stakeDetails.numOfMonths; increaseVeAmount(staker, amount, numOfMonths, true); // Get current amount for main contract change event original = stakeDetails.initialTokenAmount - stakeDetails.withdrawnAmount; // Take amount off the withdrawnAmount, "repairing" the stake if (amount > stakeDetails.withdrawnAmount) { // Take withdrawn off amount amount -= stakeDetails.withdrawnAmount; // Clear withdrawn stakeDetails.withdrawnAmount = 0; // Add remaining to initial stakeDetails.initialTokenAmount += amount; } else { // Just reduce amount withdrawn stakeDetails.withdrawnAmount -= amount; } // Relock stakeDetails.depositTime = uint48(block.timestamp); newNftId = _reissueStakeNftId(nftId, lookupIndex); stakeDetails.nftId = newNftId; _reissueStakeNft(staker, nftId, newNftId); } function extendStake(uint256 nftId, uint8 numOfMonths) external walletLock(_msgSender()) returns (uint32 newNftId) { address staker = _msgSender(); (uint256 lookupIndex, StakingDetails storage stakeDetails) = _getStake(nftId, staker); checkLocked(stakeDetails.depositTime, stakeDetails.numOfMonths); if (stakeDetails.numOfMonths >= numOfMonths) revert StakeCanOnlyBeExtended(); // Stake time period must be in valid range if (numOfMonths > maxStakeMonths || (numOfMonths > 12 && (numOfMonths % 12) > 0) ) { revert AmountOutOfRange(); } uint8 extraMonths = numOfMonths - stakeDetails.numOfMonths; uint96 amount = (stakeDetails.initialTokenAmount - stakeDetails.withdrawnAmount); increaseVeAmount(staker, amount, extraMonths, true); stakeDetails.numOfMonths = numOfMonths; // Relock stakeDetails.depositTime = uint48(block.timestamp); newNftId = _reissueStakeNftId(nftId, lookupIndex); stakeDetails.nftId = newNftId; _reissueStakeNft(staker, nftId, newNftId); } function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) revert Overflow(); return uint96(value); } function splitStake(uint256 nftId, uint96 amount) external payable walletLock(_msgSender()) returns (uint32 newNftId0, uint32 newNftId1) { address staker = _msgSender(); if (msg.value < stakeCreateCost) revert NotEnoughToCoverStakeFee(); roundingCheck(amount, false); // Transfer everything, easier than transferring extras later payable(address(everRiseToken)).transfer(address(this).balance); (uint256 lookupIndex, StakingDetails storage stakeDetails) = _getStake(nftId, staker); uint256 remainingAmount = stakeDetails.initialTokenAmount - stakeDetails.withdrawnAmount; if (amount >= remainingAmount) revert AmountLargerThanAvailable(); newNftId0 = _reissueStakeNftId(nftId, lookupIndex); // Update the existing stake uint96 transferredWithdrawnAmount = toUint96(stakeDetails.withdrawnAmount * uint256(amount) / stakeDetails.initialTokenAmount); stakeDetails.initialTokenAmount -= amount; stakeDetails.withdrawnAmount -= transferredWithdrawnAmount; stakeDetails.nftId = newNftId0; // Create new stake newNftId1 = _addSplitStake( staker, amount, // initialTokenAmount transferredWithdrawnAmount, // withdrawnAmount stakeDetails.depositTime, // depositTime stakeDetails.numOfMonths, stakeDetails.achievementClaimed == _TRUE8 // achievementClaimed ); _reissueStakeNft(staker, nftId, newNftId0); emit Transfer(address(0), staker, newNftId1); } function roundingCheck(uint96 amount, bool allowZero) private pure { // Round to nearest unit uint96 roundedAmount = amount - (amount % uint96(10**18)); if (amount != roundedAmount || (!allowZero && amount == 0)) revert AmountMustBeAnInteger(); } function mergeStakes(uint256 nftId0, uint256 nftId1, bool overrideStatuses) external walletLock(_msgSender()) returns (uint32 newNftId) { if (mergeEnabled != _TRUE) revert MergeNotEnabled(); address staker = _msgSender(); (uint256 lookupIndex0, StakingDetails storage stakeDetails0) = _getStake(nftId0, staker); (uint256 lookupIndex1, StakingDetails storage stakeDetails1) = _getStake(nftId1, staker); bool unlocked0 = stakeDetails0.depositTime + (stakeDetails0.numOfMonths * month) < block.timestamp; bool unlocked1 = stakeDetails1.depositTime + (stakeDetails1.numOfMonths * month) < block.timestamp; if (unlocked0 == unlocked1) { if (stakeDetails0.numOfMonths != stakeDetails1.numOfMonths) { revert UnlockedStakesMustBeSametimePeriod(); } if (!overrideStatuses && stakeDetails0.achievementClaimed != stakeDetails1.achievementClaimed) { revert AchievementClaimStatusesDiffer(); } // Reset broken status if unlocked if (stakeDetails0.withdrawnAmount > 0) { stakeDetails0.initialTokenAmount -= stakeDetails0.withdrawnAmount; stakeDetails0.withdrawnAmount = 0; } if (stakeDetails1.withdrawnAmount > 0) { stakeDetails1.initialTokenAmount -= stakeDetails1.withdrawnAmount; stakeDetails1.withdrawnAmount = 0; } } else if (unlocked0 != unlocked1) { revert CannotMergeLockedAndUnlockedStakes(); } else { // Both locked if (!overrideStatuses && (stakeDetails0.withdrawnAmount > 0) != (stakeDetails1.withdrawnAmount > 0)) { revert BrokenStatusesDiffer(); } } uint8 numOfMonths0 = stakeDetails0.numOfMonths; if (!unlocked0) { uint8 extraMonths = 0; uint96 amount = 0; // Must both be locked uint8 numOfMonths1 = stakeDetails1.numOfMonths; if (numOfMonths0 > numOfMonths1) { extraMonths = numOfMonths0 - numOfMonths1; amount = (stakeDetails1.initialTokenAmount - stakeDetails1.withdrawnAmount); } else if (numOfMonths0 < numOfMonths1) { extraMonths = numOfMonths1 - numOfMonths0; amount = (stakeDetails0.initialTokenAmount - stakeDetails0.withdrawnAmount); numOfMonths0 = numOfMonths1; } if (extraMonths > 0 && amount > 0) { // Give new tokens for time period increaseVeAmount(staker, amount, extraMonths, true); } } stakeDetails0.initialTokenAmount += stakeDetails1.initialTokenAmount; stakeDetails0.withdrawnAmount += stakeDetails1.withdrawnAmount; if (unlocked0) { // For unlocked, use higher of two deposit times // Can't "age" and nft by merging an older one in stakeDetails0.depositTime = stakeDetails0.depositTime > stakeDetails1.depositTime ? stakeDetails0.depositTime : stakeDetails1.depositTime; } else { // Re-lock starting now stakeDetails0.depositTime = uint48(block.timestamp); } stakeDetails0.numOfMonths = numOfMonths0; if (stakeDetails1.achievementClaimed == _TRUE8) { stakeDetails0.achievementClaimed = _TRUE8; } // Drop the second stake stakeDetails1.isActive = _FALSE8; uint24 stakerIndex = stakeDetails1.stakerIndex; _removeIndividualStake(staker, stakerIndex); // Clear the lookup for second _stakeById[nftId1] = 0; // Add to available data items _freeStakes.push(lookupIndex1); // Burn the second stake completely emit Transfer(staker, address(0), nftId1); // Renumber first stake newNftId = _reissueStakeNftId(nftId0, lookupIndex0); stakeDetails0.nftId = newNftId; _reissueStakeNft(staker, nftId0, newNftId); } function _addSplitStake( address staker, uint96 initialTokenAmount, uint96 withdrawnAmount, uint48 depositTime, uint8 numOfMonths, bool achievementClaimed ) private returns (uint32 nftId) { uint256[] storage stakes = _individualStakes[staker]; // Create new stake StakingDetails storage splitStakeDetails = _createStakeDetails( initialTokenAmount, // initialTokenAmount withdrawnAmount, // withdrawnAmount depositTime, // depositTime numOfMonths, achievementClaimed, // achievementClaimed staker, uint24(stakes.length) // New staker's stake index ); // Add new stake to individual's list stakes.push(splitStakeDetails.lookupIndex); nftId = splitStakeDetails.nftId; } function bridgeStakeNftOut(address fromAddress, uint256 nftId) external onlyEverRiseToken returns (uint96 amount) { (uint256 lookupIndex, StakingDetails storage stakeDetails) = _getStake(nftId, fromAddress); return _removeStake(fromAddress, nftId, lookupIndex, stakeDetails); } function bridgeOrAirdropStakeNftIn(address toAddress, uint96 depositAmount, uint8 numOfMonths, uint48 depositTime, uint96 withdrawnAmount, uint96 rewards, bool achievementClaimed) external onlyEverRiseToken returns (uint32 nftId) { nftId = _createStake(toAddress, depositAmount, withdrawnAmount, numOfMonths, depositTime, achievementClaimed); if (rewards > 0) { _transfer(address(this), toAddress, rewards, false); // Emit event claimRiseToken.transferFrom(address(0), toAddress, rewards); } } function _createStakeDetails( uint96 initialTokenAmount, uint96 withdrawnAmount, uint48 depositTime, uint8 numOfMonths, bool achievementClaimed, address stakerAddress, uint24 stakerIndex ) private returns (StakingDetails storage stakeDetails) { uint256 index = _freeStakes.length; if (index > 0) { // Is an existing allocated StakingDetails // that we can reuse for cheaper gas index = _freeStakes[index - 1]; _freeStakes.pop(); stakeDetails = _allStakeDetails[index]; } else { // None free, allocate a new StakingDetails index = _allStakeDetails.length; stakeDetails = _allStakeDetails.push(); } // Set stake details stakeDetails.initialTokenAmount = initialTokenAmount; stakeDetails.withdrawnAmount = withdrawnAmount; stakeDetails.depositTime = depositTime; stakeDetails.numOfMonths = numOfMonths; stakeDetails.achievementClaimed = achievementClaimed ? _TRUE8 : _FALSE8; stakeDetails.stakerAddress = stakerAddress; stakeDetails.nftId = nextNftId; stakeDetails.lookupIndex = uint32(index); stakeDetails.stakerIndex = stakerIndex; stakeDetails.isActive = _TRUE8; // Set lookup _stakeById[nextNftId] = index; // Increase the next nft id ++nextNftId; } function _transferStake(address fromAddress, address toAddress, uint256 nftId) private { (uint256 lookupIndex, StakingDetails storage stakeDetails) = _getStake(nftId, fromAddress); require(stakeDetails.withdrawnAmount == 0, "Broken, non-transferable"); stakeDetails.stakerAddress = toAddress; // Full initial as withdrawn must be zero (above) uint96 amountToTransfer = stakeDetails.initialTokenAmount; uint8 numOfMonths = stakeDetails.numOfMonths; // Remove veTokens from sender (don't emit ve transfer event) decreaseVeAmount(fromAddress, amountToTransfer, numOfMonths, false); // Give veTokens to receiver (don't emit ve transfer event) increaseVeAmount(toAddress, amountToTransfer, numOfMonths, false); // Emit the ve transfer event veRiseToken.transferFrom(fromAddress, toAddress, amountToTransfer * numOfMonths); // Remove from previous owners list _removeIndividualStake(fromAddress, stakeDetails.stakerIndex); // Add to new owners list stakeDetails.stakerIndex = uint24(_individualStakes[toAddress].length); _individualStakes[toAddress].push(lookupIndex); everRiseToken.transferStake(fromAddress, toAddress, amountToTransfer); } function _removeIndividualStake(address staker, uint24 stakerIndex) private { uint256[] storage stakes = _individualStakes[staker]; uint24 stakerLength = uint24(stakes.length); if (stakerLength >= stakerIndex + 1) { // Not last item, overwrite with last item from account stakes uint256 lastStakeIndex = stakes[stakerLength - 1]; _allStakeDetails[lastStakeIndex].stakerIndex = stakerIndex; stakes[stakerIndex] = lastStakeIndex; } // Remove last item stakes.pop(); } function _reissueStakeNftId(uint256 nftId, uint256 stakeIndex) private returns (uint32 newNftId) { // Burn the Stake NFT id _stakeById[nftId] = 0; // Reissue new Stake NFT id newNftId = nextNftId; _stakeById[newNftId] = stakeIndex; // Increase the next nft id ++nextNftId; } function increaseVeAmount(address staker, uint96 amount, uint8 numOfMonths, bool emitEvent) private { // Transfer vote escrowed tokens from contract to staker uint256 veTokens = amount * numOfMonths; totalAmountEscrowed += amount; totalAmountVoteEscrowed += veTokens; voteEscrowedBalance[staker] += veTokens; // increase the ve tokens amount _transfer(address(this), staker, veTokens, emitEvent); } function decreaseVeAmount(address staker, uint96 amount, uint8 numOfMonths, bool emitEvent) private { // Transfer vote escrowed tokens back to the contract uint256 veTokens = amount * numOfMonths; totalAmountEscrowed -= amount; totalAmountVoteEscrowed -= veTokens; voteEscrowedBalance[staker] -= veTokens; // decrease the ve tokens amount _transfer(staker, address(this), veTokens, emitEvent); } function _removeStake(address staker, uint256 nftId, uint256 lookupIndex, StakingDetails storage stakeDetails) private returns (uint96 amount) { uint96 remainingAmount = stakeDetails.initialTokenAmount - stakeDetails.withdrawnAmount; decreaseVeAmount(staker, remainingAmount, stakeDetails.numOfMonths, true); _burnStake(staker, nftId, lookupIndex, stakeDetails); return remainingAmount; } function _burnStake(address staker, uint256 nftId, uint256 lookupIndex, StakingDetails storage stakeDetails) private { stakeDetails.isActive = _FALSE8; uint24 stakerIndex = stakeDetails.stakerIndex; _removeIndividualStake(staker, stakerIndex); // Clear the lookup _stakeById[nftId] = 0; // Add to available data items _freeStakes.push(lookupIndex); } function _createStake(address staker, uint96 depositAmount, uint96 withdrawnAmount, uint8 numOfMonths, uint48 depositTime, bool achievementClaimed) private returns (uint32 nftId) { if (withdrawnAmount >= depositAmount) revert AmountOutOfRange(); uint256[] storage stakes = _individualStakes[staker]; // Create new stake StakingDetails storage stakeDetails = _createStakeDetails( depositAmount, // initialTokenAmount withdrawnAmount, // withdrawnAmount depositTime, // depositTime numOfMonths, achievementClaimed, // achievementClaimed staker, uint24(stakes.length) // New staker's stake index ); // Add new stake to individual's list stakes.push(stakeDetails.lookupIndex); uint96 remaining = depositAmount - withdrawnAmount; increaseVeAmount(staker, remaining, numOfMonths, true); // Mint new Stake NFT to staker nftId = stakeDetails.nftId; } function calculateTax(uint96 amount, uint256 depositTime, uint256 numOfMonths) public view returns (uint96) { return calculateTaxAt(amount, depositTime, numOfMonths, block.timestamp); } function calculateTaxAt(uint96 amount, uint256 depositTime, uint256 numOfMonths, uint256 timestamp) public view returns (uint96) { uint256 lockTime = depositTime + (numOfMonths * month); uint96 taxAmount = 0; if (timestamp < depositTime + (numOfMonths * month / 2)) { taxAmount = (amount * firstHalfPenality) / 100; } else if (timestamp < lockTime) { taxAmount = (amount * secondHalfPenality) / 100; } return taxAmount; } function royaltyInfo(uint256 _tokenId, uint256 _salePrice) external view returns ( address receiver, uint256 royaltyAmount ) { if (_tokenId == 0) revert AmountMustBeGreaterThanZero(); return (address(royaltySplitter), _salePrice / nftRoyaltySplit); } /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external { if (address(everRiseToken) == address(0)) revert NotSetup(); address _owner = _msgSender(); everRiseToken.setApprovalForAll(_owner, operator, approved); emit ApprovalForAll(_owner, operator, approved); } /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) public view returns (bool) { return everRiseToken.isApprovedForAll(account, operator); } function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external payable walletLock(_msgSender()) { address operator = _msgSender(); _transferFrom(operator, from, to, tokenId); _doSafeERC721TransferAcceptanceCheck(operator, from, to, tokenId, data); } function safeTransferFrom(address from, address to, uint256 tokenId) external payable walletLock(_msgSender()) { address operator = _msgSender(); _transferFrom(operator, from, to, tokenId); _doSafeERC721TransferAcceptanceCheck(operator, from, to, tokenId, new bytes(0)); } function transferFrom(address from, address to, uint256 tokenId) external payable walletLock(_msgSender()) { address operator = _msgSender(); _transferFrom(operator, from, to, tokenId); } function approve(address account, address _operator, uint256 nftId) external onlyEverRiseToken { _approve(account, _operator, nftId); } function approve(address _operator, uint256 nftId) external payable { _approve(_msgSender(), _operator, nftId); } function _approve(address account, address _operator, uint256 nftId) private { if (ownerOf(nftId) != account) revert NotStakerAddress(); ApprovalChecks memory approvals = everRiseToken.approvals(account); _individualApproval[nftId] = IndividualAllowance({ operator: _operator, timestamp: approvals.autoRevokeNftHours == 0 ? type(uint48).max : // Don't timeout approval uint48(block.timestamp) + approvals.autoRevokeNftHours * 1 hours, // Timeout after user chosen period, nftCheck: approvals.nftCheck }); } function getApproved(uint256 nftId) external view returns (address) { getStakeIndex(nftId); // Reverts on not exist IndividualAllowance storage _allowance = _individualApproval[nftId]; ApprovalChecks memory approvals = everRiseToken.approvals(ownerOf(nftId)); if (block.timestamp > _allowance.timestamp || approvals.nftCheck != _allowance.nftCheck) { return address(0); } return _allowance.operator; } function _isAddressApproved(address operator, uint256 nftId) private view returns (bool) { IndividualAllowance storage _allowance = _individualApproval[nftId]; ApprovalChecks memory approvals = everRiseToken.approvals(ownerOf(nftId)); if (_allowance.operator != operator || block.timestamp > _allowance.timestamp || approvals.nftCheck != _allowance.nftCheck) { return false; } return true; } function _transferFrom( address operator, address from, address to, uint256 nftId ) private { if (address(everRiseToken) == address(0)) revert NotSetup(); if (from == address(0)) revert NotZeroAddress(); if (to == address(0)) revert NotZeroAddress(); if (operator != from && !isApprovedForAll(from, operator) && !_isAddressApproved(from, nftId) ) revert AmountLargerThanAllowance(); // Clear any individual approvals delete _individualApproval[nftId]; _transferStake(from, to, nftId); // Signal transfer complete emit Transfer(from, to, nftId); } function addStaker(address staker, uint256 nftId) external onlyEverRiseToken { // Send event for new staking emit Transfer(address(0), staker, nftId); } function _doSafeERC721TransferAcceptanceCheck( address operator, address from, address to, uint256 id, bytes memory data ) private view { if (isContract(to)) { try IERC721TokenReceiver(to).onERC721Received(operator, from, id, data) returns (bytes4 response) { if (response != IERC721TokenReceiver.onERC721Received.selector) { revert ERC721ReceiverReject(); } } catch Error(string memory reason) { revert(reason); } catch { revert ERC721ReceiverNotImplemented(); } } } function isContract(address account) private view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } function removeStaker(address staker, uint256 nftId) external onlyEverRiseToken { // Send event for left staking emit Transfer(staker, address(0), nftId); } function reissueStakeNft(address staker, uint256 oldNftId, uint256 newNftId) external onlyEverRiseToken { _reissueStakeNft(staker, oldNftId, newNftId); } function _reissueStakeNft(address staker, uint256 oldNftId, uint256 newNftId) private { // Burn old Stake NFT emit Transfer(staker, address(0), oldNftId); // Reissue new Stake NFT emit Transfer(address(0), staker, newNftId); } // Admin for trapped tokens function transferExternalTokens(address tokenAddress, address toAddress) external onlyOwner { if (tokenAddress == address(0)) revert NotZeroAddress(); if (toAddress == address(0)) revert NotZeroAddress(); if (IERC20(tokenAddress).balanceOf(address(this)) == 0) revert AmountLargerThanAvailable(); require(IERC20(tokenAddress).transfer(toAddress, IERC20(tokenAddress).balanceOf(address(this)))); } function transferToAddressETH(address payable receipient) external onlyOwner { if (receipient == address(0)) revert NotZeroAddress(); receipient.transfer(address(this).balance); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"CallerNotOwner","type":"error"},{"inputs":[],"name":"NotTransferrable","type":"error"},{"inputs":[],"name":"NotZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"transferFromWithPermit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"veEverRise","outputs":[{"internalType":"contract InftEverRise","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b506040518060400160405280601081526020016f4576657252697365205265776172647360801b81525060405180604001604052806009815260200168636c61696d5249534560b81b815250600061006c61010760201b60201c565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35081516100c990600290602085019061010b565b5080516100dd90600390602084019061010b565b5050600054600180546001600160a01b0319166001600160a01b03909216919091179055506101de565b3390565b828054610117906101a4565b90600052602060002090601f016020900481019282610139576000855561017f565b82601f1061015257805160ff191683800117855561017f565b8280016001018555821561017f579182015b8281111561017f578251825591602001919060010190610164565b5061018b92915061018f565b5090565b5b8082111561018b5760008155600101610190565b600181811c908216806101b857607f821691505b6020821081036101d857634e487b7160e01b600052602260045260246000fd5b50919050565b610748806101ed6000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80638da5cb5b11610097578063b038f20d11610066578063b038f20d146101c4578063d6e03cd4146101d7578063dd62ed3e146101ea578063f2fde38b1461020057600080fd5b80638da5cb5b1461019157806395d89b41146101bc578063a457c2d714610118578063a9059cbb1461011857600080fd5b806323b872dd116100d357806323b872dd14610151578063313ce56714610164578063395093511461011857806370a082311461017e57600080fd5b806306fdde03146100fa578063095ea7b31461011857806318160ddd1461013b575b600080fd5b610102610215565b60405161010f9190610520565b60405180910390f35b61012b610126366004610591565b6102a3565b604051901515815260200161010f565b6101436102b3565b60405190815260200161010f565b61012b61015f3660046105bb565b610326565b61016c601281565b60405160ff909116815260200161010f565b61014361018c3660046105f7565b6103a1565b6000546101a4906001600160a01b031681565b6040516001600160a01b03909116815260200161010f565b61010261042e565b6001546101a4906001600160a01b031681565b61012b6101e5366004610619565b61043b565b6101436101f836600461068c565b600092915050565b61021361020e3660046105f7565b610450565b005b60028054610222906106bf565b80601f016020809104026020016040519081016040528092919081815260200182805461024e906106bf565b801561029b5780601f106102705761010080835404028352916020019161029b565b820191906000526020600020905b81548152906001019060200180831161027e57829003601f168201915b505050505081565b60006102ad6104da565b92915050565b600154604080516306dd29e560e01b815290516000926001600160a01b0316916306dd29e59160048083019260209291908290030181865afa1580156102fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061032191906106f9565b905090565b600080546001600160a01b0316336001600160a01b03161461034a5761034a6104da565b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161038f91815260200190565b60405180910390a35060019392505050565b600080546001600160a01b03908116908316036103c057506000919050565b6001546040516304cbc2fb60e11b81526001600160a01b0384811660048301529091169063099785f690602401602060405180830381865afa15801561040a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ad91906106f9565b60038054610222906106bf565b60006104456104da565b979650505050505050565b6104586104f3565b6001600160a01b03811661047f576040516366385fa360e01b815260040160405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6040516354ee515160e01b815260040160405180910390fd5b6000546001600160a01b0316331461051e57604051632e6c18c960e11b815260040160405180910390fd5b565b600060208083528351808285015260005b8181101561054d57858101830151858201604001528201610531565b8181111561055f576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461058c57600080fd5b919050565b600080604083850312156105a457600080fd5b6105ad83610575565b946020939093013593505050565b6000806000606084860312156105d057600080fd5b6105d984610575565b92506105e760208501610575565b9150604084013590509250925092565b60006020828403121561060957600080fd5b61061282610575565b9392505050565b600080600080600080600060e0888a03121561063457600080fd5b61063d88610575565b965061064b60208901610575565b95506040880135945060608801359350608088013560ff8116811461066f57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561069f57600080fd5b6106a883610575565b91506106b660208401610575565b90509250929050565b600181811c908216806106d357607f821691505b6020821081036106f357634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561070b57600080fd5b505191905056fea2646970667358221220f35afae76adc4b92710eb555fc201d0373faf6a7430815869d3d45f9c99a850e64736f6c634300080d0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100f55760003560e01c80638da5cb5b11610097578063b038f20d11610066578063b038f20d146101c4578063d6e03cd4146101d7578063dd62ed3e146101ea578063f2fde38b1461020057600080fd5b80638da5cb5b1461019157806395d89b41146101bc578063a457c2d714610118578063a9059cbb1461011857600080fd5b806323b872dd116100d357806323b872dd14610151578063313ce56714610164578063395093511461011857806370a082311461017e57600080fd5b806306fdde03146100fa578063095ea7b31461011857806318160ddd1461013b575b600080fd5b610102610215565b60405161010f9190610520565b60405180910390f35b61012b610126366004610591565b6102a3565b604051901515815260200161010f565b6101436102b3565b60405190815260200161010f565b61012b61015f3660046105bb565b610326565b61016c601281565b60405160ff909116815260200161010f565b61014361018c3660046105f7565b6103a1565b6000546101a4906001600160a01b031681565b6040516001600160a01b03909116815260200161010f565b61010261042e565b6001546101a4906001600160a01b031681565b61012b6101e5366004610619565b61043b565b6101436101f836600461068c565b600092915050565b61021361020e3660046105f7565b610450565b005b60028054610222906106bf565b80601f016020809104026020016040519081016040528092919081815260200182805461024e906106bf565b801561029b5780601f106102705761010080835404028352916020019161029b565b820191906000526020600020905b81548152906001019060200180831161027e57829003601f168201915b505050505081565b60006102ad6104da565b92915050565b600154604080516306dd29e560e01b815290516000926001600160a01b0316916306dd29e59160048083019260209291908290030181865afa1580156102fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061032191906106f9565b905090565b600080546001600160a01b0316336001600160a01b03161461034a5761034a6104da565b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161038f91815260200190565b60405180910390a35060019392505050565b600080546001600160a01b03908116908316036103c057506000919050565b6001546040516304cbc2fb60e11b81526001600160a01b0384811660048301529091169063099785f690602401602060405180830381865afa15801561040a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ad91906106f9565b60038054610222906106bf565b60006104456104da565b979650505050505050565b6104586104f3565b6001600160a01b03811661047f576040516366385fa360e01b815260040160405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6040516354ee515160e01b815260040160405180910390fd5b6000546001600160a01b0316331461051e57604051632e6c18c960e11b815260040160405180910390fd5b565b600060208083528351808285015260005b8181101561054d57858101830151858201604001528201610531565b8181111561055f576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461058c57600080fd5b919050565b600080604083850312156105a457600080fd5b6105ad83610575565b946020939093013593505050565b6000806000606084860312156105d057600080fd5b6105d984610575565b92506105e760208501610575565b9150604084013590509250925092565b60006020828403121561060957600080fd5b61061282610575565b9392505050565b600080600080600080600060e0888a03121561063457600080fd5b61063d88610575565b965061064b60208901610575565b95506040880135945060608801359350608088013560ff8116811461066f57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561069f57600080fd5b6106a883610575565b91506106b660208401610575565b90509250929050565b600181811c908216806106d357607f821691505b6020821081036106f357634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561070b57600080fd5b505191905056fea2646970667358221220f35afae76adc4b92710eb555fc201d0373faf6a7430815869d3d45f9c99a850e64736f6c634300080d0033
Deployed Bytecode Sourcemap
14989:407:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12220:18;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;12942:101;;;;;;:::i;:::-;;:::i;:::-;;;1218:14:1;;1211:22;1193:41;;1181:2;1166:18;12942:101:0;1053:187:1;15064:124:0;;;:::i;:::-;;;1391:25:1;;;1379:2;1364:18;15064:124:0;1245:177:1;12442:282:0;;;;;;:::i;:::-;;:::i;12178:35::-;;12211:2;12178:35;;;;;1932:4:1;1920:17;;;1902:36;;1890:2;1875:18;12178:35:0;1760:184:1;15196:197:0;;;;;;:::i;:::-;;:::i;3874:20::-;;;;;-1:-1:-1;;;;;3874:20:0;;;;;;-1:-1:-1;;;;;2304:32:1;;;2286:51;;2274:2;2259:18;3874:20:0;2140:203:1;12245:20:0;;;:::i;12139:30::-;;;;;-1:-1:-1;;;;;12139:30:0;;;13283:159;;;;;;:::i;:::-;;:::i;12840:96::-;;;;;;:::i;:::-;12900:7;12840:96;;;;;4609:224;;;;;;:::i;:::-;;:::i;:::-;;12220:18;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;12942:101::-;13000:4;13017:18;:16;:18::i;:::-;12942:101;;;;:::o;15064:124::-;15146:10;;:34;;;-1:-1:-1;;;15146:34:0;;;;15119:7;;-1:-1:-1;;;;;15146:10:0;;:32;;:34;;;;;;;;;;;;;;:10;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;15139:41;;15064:124;:::o;12442:282::-;12542:4;12589:5;;-1:-1:-1;;;;;12589:5:0;3751:10;-1:-1:-1;;;;;12573:21:0;;12569:73;;12612:18;:16;:18::i;:::-;12676:9;-1:-1:-1;;;;;12659:35:0;12668:6;-1:-1:-1;;;;;12659:35:0;;12687:6;12659:35;;;;1391:25:1;;1379:2;1364:18;;1245:177;12659:35:0;;;;;;;;-1:-1:-1;12712:4:0;12442:282;;;;;:::o;15196:197::-;15264:7;15299:5;;-1:-1:-1;;;;;15299:5:0;;;15288:16;;;;15284:30;;-1:-1:-1;15313:1:0;;15196:197;-1:-1:-1;15196:197:0:o;15284:30::-;15342:10;;:43;;-1:-1:-1;;;15342:43:0;;-1:-1:-1;;;;;2304:32:1;;;15342:43:0;;;2286:51:1;15342:10:0;;;;:34;;2259:18:1;;15342:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;12245:20::-;;;;;;;:::i;13283:159::-;13399:4;13416:18;:16;:18::i;:::-;13283:159;;;;;;;;;:::o;4609:224::-;4047:12;:10;:12::i;:::-;-1:-1:-1;;;;;4696:22:0;::::1;4692:51;;4727:16;;-1:-1:-1::0;;;4727:16:0::1;;;;;;;;;;;4692:51;4782:5;::::0;;4761:37:::1;::::0;-1:-1:-1;;;;;4761:37:0;;::::1;::::0;4782:5;::::1;::::0;4761:37:::1;::::0;::::1;4809:5;:16:::0;;-1:-1:-1;;;;;;4809:16:0::1;-1:-1:-1::0;;;;;4809:16:0;;;::::1;::::0;;;::::1;::::0;;4609:224::o;13450:85::-;13509:18;;-1:-1:-1;;;13509:18:0;;;;;;;;;;;3903:104;3953:5;;-1:-1:-1;;;;;3953:5:0;3751:10;3953:21;3949:50;;3983:16;;-1:-1:-1;;;3983:16:0;;;;;;;;;;;3949:50;3903:104::o;14:597:1:-;126:4;155:2;184;173:9;166:21;216:6;210:13;259:6;254:2;243:9;239:18;232:34;284:1;294:140;308:6;305:1;302:13;294:140;;;403:14;;;399:23;;393:30;369:17;;;388:2;365:26;358:66;323:10;;294:140;;;452:6;449:1;446:13;443:91;;;522:1;517:2;508:6;497:9;493:22;489:31;482:42;443:91;-1:-1:-1;595:2:1;574:15;-1:-1:-1;;570:29:1;555:45;;;;602:2;551:54;;14:597;-1:-1:-1;;;14:597:1:o;616:173::-;684:20;;-1:-1:-1;;;;;733:31:1;;723:42;;713:70;;779:1;776;769:12;713:70;616:173;;;:::o;794:254::-;862:6;870;923:2;911:9;902:7;898:23;894:32;891:52;;;939:1;936;929:12;891:52;962:29;981:9;962:29;:::i;:::-;952:39;1038:2;1023:18;;;;1010:32;;-1:-1:-1;;;794:254:1:o;1427:328::-;1504:6;1512;1520;1573:2;1561:9;1552:7;1548:23;1544:32;1541:52;;;1589:1;1586;1579:12;1541:52;1612:29;1631:9;1612:29;:::i;:::-;1602:39;;1660:38;1694:2;1683:9;1679:18;1660:38;:::i;:::-;1650:48;;1745:2;1734:9;1730:18;1717:32;1707:42;;1427:328;;;;;:::o;1949:186::-;2008:6;2061:2;2049:9;2040:7;2036:23;2032:32;2029:52;;;2077:1;2074;2067:12;2029:52;2100:29;2119:9;2100:29;:::i;:::-;2090:39;1949:186;-1:-1:-1;;;1949:186:1:o;2576:693::-;2687:6;2695;2703;2711;2719;2727;2735;2788:3;2776:9;2767:7;2763:23;2759:33;2756:53;;;2805:1;2802;2795:12;2756:53;2828:29;2847:9;2828:29;:::i;:::-;2818:39;;2876:38;2910:2;2899:9;2895:18;2876:38;:::i;:::-;2866:48;;2961:2;2950:9;2946:18;2933:32;2923:42;;3012:2;3001:9;2997:18;2984:32;2974:42;;3066:3;3055:9;3051:19;3038:33;3111:4;3104:5;3100:16;3093:5;3090:27;3080:55;;3131:1;3128;3121:12;3080:55;2576:693;;;;-1:-1:-1;2576:693:1;;;;3154:5;3206:3;3191:19;;3178:33;;-1:-1:-1;3258:3:1;3243:19;;;3230:33;;2576:693;-1:-1:-1;;2576:693:1:o;3274:260::-;3342:6;3350;3403:2;3391:9;3382:7;3378:23;3374:32;3371:52;;;3419:1;3416;3409:12;3371:52;3442:29;3461:9;3442:29;:::i;:::-;3432:39;;3490:38;3524:2;3513:9;3509:18;3490:38;:::i;:::-;3480:48;;3274:260;;;;;:::o;3539:380::-;3618:1;3614:12;;;;3661;;;3682:61;;3736:4;3728:6;3724:17;3714:27;;3682:61;3789:2;3781:6;3778:14;3758:18;3755:38;3752:161;;3835:10;3830:3;3826:20;3823:1;3816:31;3870:4;3867:1;3860:15;3898:4;3895:1;3888:15;3752:161;;3539:380;;;:::o;3924:184::-;3994:6;4047:2;4035:9;4026:7;4022:23;4018:32;4015:52;;;4063:1;4060;4053:12;4015:52;-1:-1:-1;4086:16:1;;3924:184;-1:-1:-1;3924:184:1:o
Swarm Source
ipfs://f35afae76adc4b92710eb555fc201d0373faf6a7430815869d3d45f9c99a850e
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.