Source Code
Overview
S Balance
More Info
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Loading...
Loading
Contract Name:
DisposablePooledStaking
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.18; import "../../interfaces/ITokenController.sol"; import "../../modules/legacy/LegacyPooledStaking.sol"; contract DisposablePooledStaking is LegacyPooledStaking { function initialize( address payable _tokenControllerAddress, uint minStake, uint minUnstake, uint maxExposure, uint unstakeLockTime ) external { internalContracts[uint(ID.TC)] = _tokenControllerAddress; ITokenController(_tokenControllerAddress).addToWhitelist(address(this)); MIN_STAKE = minStake; MIN_UNSTAKE = minUnstake; MAX_EXPOSURE = maxExposure; UNSTAKE_LOCK_TIME = unstakeLockTime; REWARD_ROUND_DURATION = 7 days; REWARD_ROUNDS_START = block.timestamp; } constructor(address _tokenAddress) LegacyPooledStaking( 0x0000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000, _tokenAddress ) { // noop } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.18; import "../interfaces/ISAFURAMaster.sol"; import "../interfaces/IMasterAwareV2.sol"; import "../interfaces/IMemberRoles.sol"; abstract contract MasterAwareV2 is IMasterAwareV2 { ISAFURAMaster public master; mapping(uint => address payable) public internalContracts; modifier onlyMember { require( IMemberRoles(internalContracts[uint(ID.MR)]).checkRole( msg.sender, uint(IMemberRoles.Role.Member) ), "Caller is not a member" ); _; } modifier onlyAdvisoryBoard { require( IMemberRoles(internalContracts[uint(ID.MR)]).checkRole( msg.sender, uint(IMemberRoles.Role.AdvisoryBoard) ), "Caller is not an advisory board member" ); _; } modifier onlyInternal { require(master.isInternal(msg.sender), "Caller is not an internal contract"); _; } modifier onlyMaster { if (address(master) != address(0)) { require(address(master) == msg.sender, "Not master"); } _; } modifier onlyGovernance { require( master.checkIsAuthToGoverned(msg.sender), "Caller is not authorized to govern" ); _; } modifier onlyEmergencyAdmin { require( msg.sender == master.emergencyAdmin(), "Caller is not emergency admin" ); _; } modifier whenPaused { require(master.isPause(), "System is not paused"); _; } modifier whenNotPaused { require(!master.isPause(), "System is paused"); _; } function getInternalContractAddress(ID id) internal view returns (address payable) { return internalContracts[uint(id)]; } function changeMasterAddress(address masterAddress) public onlyMaster { master = ISAFURAMaster(masterAddress); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; import "./IStakingPoolFactory.sol"; /** * @dev IStakingPoolFactory is missing the changeOperator() and operator() functions. * @dev Any change to the original interface will affect staking pool addresses * @dev This interface is created to add the missing functions so it can be used in other contracts. */ interface ICompleteStakingPoolFactory is IStakingPoolFactory { function operator() external view returns (address); function changeOperator(address newOperator) external; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; import "./ICoverNFT.sol"; import "./IStakingNFT.sol"; import "./IStakingPool.sol"; import "./ICompleteStakingPoolFactory.sol"; /* io structs */ enum ClaimMethod { IndividualClaims, YieldTokenIncidents } struct PoolAllocationRequest { uint40 poolId; bool skip; uint coverAmountInAsset; } struct BuyCoverParams { uint coverId; address owner; uint24 productId; uint8 coverAsset; uint96 amount; uint32 period; uint maxPremiumInAsset; uint8 paymentAsset; uint16 commissionRatio; address commissionDestination; string ipfsData; } /* storage structs */ struct PoolAllocation { uint40 poolId; uint96 coverAmountInNXM; uint96 premiumInNXM; uint24 allocationId; } struct CoverData { uint24 productId; uint8 coverAsset; uint96 amountPaidOut; } struct CoverSegment { uint96 amount; uint32 start; uint32 period; // seconds uint32 gracePeriod; // seconds uint24 globalRewardsRatio; uint24 globalCapacityRatio; } interface ICover { /* ========== DATA STRUCTURES ========== */ /* internal structs */ struct RequestAllocationVariables { uint previousPoolAllocationsLength; uint previousPremiumInNXM; uint refund; uint coverAmountInNXM; } /* storage structs */ struct ActiveCover { // Global active cover amount per asset. uint192 totalActiveCoverInAsset; // The last time activeCoverExpirationBuckets was updated uint64 lastBucketUpdateId; } /* ========== VIEWS ========== */ function coverData(uint coverId) external view returns (CoverData memory); function coverDataCount() external view returns (uint); function coverSegmentsCount(uint coverId) external view returns (uint); function coverSegments(uint coverId) external view returns (CoverSegment[] memory); function coverSegmentWithRemainingAmount( uint coverId, uint segmentId ) external view returns (CoverSegment memory); function recalculateActiveCoverInAsset(uint coverAsset) external; function totalActiveCoverInAsset(uint coverAsset) external view returns (uint); function getGlobalCapacityRatio() external view returns (uint); function getGlobalRewardsRatio() external view returns (uint); function getGlobalMinPriceRatio() external pure returns (uint); function getGlobalCapacityAndPriceRatios() external view returns ( uint _globalCapacityRatio, uint _globalMinPriceRatio ); function GLOBAL_MIN_PRICE_RATIO() external view returns (uint); /* === MUTATIVE FUNCTIONS ==== */ function buyCover( BuyCoverParams calldata params, PoolAllocationRequest[] calldata coverChunkRequests ) external payable returns (uint coverId); function burnStake( uint coverId, uint segmentId, uint amount ) external returns (address coverOwner); function changeStakingPoolFactoryOperator() external; function coverNFT() external returns (ICoverNFT); function stakingNFT() external returns (IStakingNFT); function stakingPoolFactory() external returns (ICompleteStakingPoolFactory); /* ========== EVENTS ========== */ event CoverEdited(uint indexed coverId, uint indexed productId, uint indexed segmentId, address buyer, string ipfsMetadata); // Auth error OnlyOwnerOrApproved(); // Cover details error CoverPeriodTooShort(); error CoverPeriodTooLong(); error CoverOutsideOfTheGracePeriod(); error CoverAmountIsZero(); // Products error ProductNotFound(); error ProductDeprecated(); error UnexpectedProductId(); // Cover and payment assets error CoverAssetNotSupported(); error InvalidPaymentAsset(); error UnexpectedCoverAsset(); error UnexpectedEthSent(); error EditNotSupported(); // Price & Commission error PriceExceedsMaxPremiumInAsset(); error CommissionRateTooHigh(); // ETH transfers error InsufficientEthSent(); error SendingEthToPoolFailed(); error SendingEthToCommissionDestinationFailed(); error ReturningEthRemainderToSenderFailed(); // Misc error ExpiredCoversCannotBeEdited(); error CoverNotYetExpired(uint coverId); error InsufficientCoverAmountAllocated(); error UnexpectedPoolId(); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; import "@openzeppelin/contracts-v4/token/ERC721/IERC721.sol"; interface ICoverNFT is IERC721 { function isApprovedOrOwner(address spender, uint tokenId) external returns (bool); function mint(address to) external returns (uint tokenId); function changeOperator(address newOperator) external; function changeNFTDescriptor(address newNFTDescriptor) external; function totalSupply() external view returns (uint); function name() external view returns (string memory); error NotOperator(); error NotMinted(); error WrongFrom(); error InvalidRecipient(); error InvalidNewOperatorAddress(); error InvalidNewNFTDescriptorAddress(); error NotAuthorized(); error UnsafeRecipient(); error AlreadyMinted(); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface IMasterAwareV2 { // TODO: if you update this enum, update lib/constants.js as well enum ID { TC, // TokenController.sol P1, // Pool.sol MR, // MemberRoles.sol MC, // MCR.sol CO, // Cover.sol SP, // StakingProducts.sol PS, // LegacyPooledStaking.sol GV, // Governance.sol GW, // LegacyGateway.sol - removed CL, // CoverMigrator.sol - removed AS, // Assessment.sol CI, // IndividualClaims.sol - Claims for Individuals CG, // YieldTokenIncidents.sol - Claims for Groups RA, // Ramm.sol ST, // SafeTracker.sol CP // CoverProducts.sol } function changeMasterAddress(address masterAddress) external; function changeDependentContractAddress() external; function internalContracts(uint) external view returns (address payable); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface IMemberRoles { enum Role {Unassigned, AdvisoryBoard, Member, Owner, Auditor} function join(address _userAddress, uint nonce, bytes calldata signature) external payable; function switchMembership(address _newAddress) external; function switchMembershipAndAssets( address newAddress, uint[] calldata coverIds, uint[] calldata stakingTokenIds ) external; function switchMembershipOf(address member, address _newAddress) external; function totalRoles() external view returns (uint256); function changeAuthorized(uint _roleId, address _newAuthorized) external; function setKycAuthAddress(address _add) external; function members(uint _memberRoleId) external view returns (uint, address[] memory memberArray); function numberOfMembers(uint _memberRoleId) external view returns (uint); function authorized(uint _memberRoleId) external view returns (address); function roles(address _memberAddress) external view returns (uint[] memory); function checkRole(address _memberAddress, uint _roleId) external view returns (bool); function getMemberLengthForAllRoles() external view returns (uint[] memory totalMembers); function memberAtIndex(uint _memberRoleId, uint index) external view returns (address, bool); function membersLength(uint _memberRoleId) external view returns (uint); event MemberRole(uint256 indexed roleId, bytes32 roleName, string roleDescription); event MemberJoined(address indexed newMember, uint indexed nonce); event switchedMembership(address indexed previousMember, address indexed newMember, uint timeStamp); event MembershipWithdrawn(address indexed member, uint timestamp); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface IPooledStaking { struct Staker { uint deposit; // total amount of deposit nxm uint reward; // total amount that is ready to be claimed address[] contracts; // list of contracts the staker has staked on // staked amounts for each contract mapping(address => uint) stakes; // amount pending to be subtracted after all unstake requests will be processed mapping(address => uint) pendingUnstakeRequestsTotal; // flag to indicate the presence of this staker in the array of stakers of each contract mapping(address => bool) isInContractStakers; } struct Burn { uint amount; uint burnedAt; address contractAddress; } struct Reward { uint amount; uint rewardedAt; address contractAddress; } struct UnstakeRequest { uint amount; uint unstakeAt; address contractAddress; address stakerAddress; uint next; // id of the next unstake request in the linked list } struct ContractReward { uint amount; uint lastDistributionRound; } function accumulateReward(address contractAddress, uint amount) external; function pushBurn(address contractAddress, uint amount) external; function hasPendingActions() external view returns (bool); function processPendingActions(uint maxIterations) external returns (bool finished); function contractStake(address contractAddress) external view returns (uint); function stakerReward(address staker) external view returns (uint); function stakerDeposit(address staker) external view returns (uint); function stakerContractStake(address staker, address contractAddress) external view returns (uint); function withdraw(uint amount) external; function withdrawForUser(address user) external; function stakerMaxWithdrawable(address stakerAddress) external view returns (uint); function withdrawReward(address stakerAddress) external; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface ISAFURAMaster { function tokenAddress() external view returns (address); function owner() external view returns (address); function emergencyAdmin() external view returns (address); function masterInitialized() external view returns (bool); function isInternal(address _add) external view returns (bool); function isPause() external view returns (bool check); function isMember(address _add) external view returns (bool); function checkIsAuthToGoverned(address _add) external view returns (bool); function getLatestAddress(bytes2 _contractName) external view returns (address payable contractAddress); function contractAddresses(bytes2 code) external view returns (address payable); function upgradeMultipleContracts( bytes2[] calldata _contractCodes, address payable[] calldata newAddresses ) external; function removeContracts(bytes2[] calldata contractCodesToRemove) external; function addNewInternalContracts( bytes2[] calldata _contractCodes, address payable[] calldata newAddresses, uint[] calldata _types ) external; function updateOwnerParameters(bytes8 code, address payable val) external; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface ISAFURAToken { function burn(uint256 amount) external returns (bool); function burnFrom(address from, uint256 value) external returns (bool); function operatorTransfer(address from, uint256 value) external returns (bool); function mint(address account, uint256 amount) external; function isLockedForMV(address member) external view returns (uint); function whiteListed(address member) external view returns (bool); function addToWhiteList(address _member) external returns (bool); function removeFromWhiteList(address _member) external returns (bool); function changeOperator(address _newOperator) external returns (bool); function lockForMemberVote(address _of, uint _days) external; /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @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); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; import "@openzeppelin/contracts-v4/token/ERC721/IERC721.sol"; interface IStakingNFT is IERC721 { function isApprovedOrOwner(address spender, uint tokenId) external returns (bool); function mint(uint poolId, address to) external returns (uint tokenId); function changeOperator(address newOperator) external; function changeNFTDescriptor(address newNFTDescriptor) external; function totalSupply() external returns (uint); function tokenInfo(uint tokenId) external view returns (uint poolId, address owner); function stakingPoolOf(uint tokenId) external view returns (uint poolId); function stakingPoolFactory() external view returns (address); function name() external view returns (string memory); error NotOperator(); error NotMinted(); error WrongFrom(); error InvalidRecipient(); error InvalidNewOperatorAddress(); error InvalidNewNFTDescriptorAddress(); error NotAuthorized(); error UnsafeRecipient(); error AlreadyMinted(); error NotStakingPool(); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; /* structs for io */ struct AllocationRequest { uint productId; uint coverId; uint allocationId; uint period; uint gracePeriod; bool useFixedPrice; uint previousStart; uint previousExpiration; uint previousRewardsRatio; uint globalCapacityRatio; uint capacityReductionRatio; uint rewardRatio; uint globalMinPrice; } struct BurnStakeParams { uint allocationId; uint productId; uint start; uint period; uint deallocationAmount; } interface IStakingPool { /* structs for storage */ // stakers are grouped in tranches based on the timelock expiration // tranche index is calculated based on the expiration date // the initial proposal is to have 4 tranches per year (1 tranche per quarter) struct Tranche { uint128 stakeShares; uint128 rewardsShares; } struct ExpiredTranche { uint96 accNxmPerRewardShareAtExpiry; uint96 stakeAmountAtExpiry; // nxm total supply is 6.7e24 and uint96.max is 7.9e28 uint128 stakeSharesSupplyAtExpiry; } struct Deposit { uint96 lastAccNxmPerRewardShare; uint96 pendingRewards; uint128 stakeShares; uint128 rewardsShares; } function initialize( bool isPrivatePool, uint initialPoolFee, uint maxPoolFee, uint _poolId, string memory ipfsDescriptionHash ) external; function processExpirations(bool updateUntilCurrentTimestamp) external; function requestAllocation( uint amount, uint previousPremium, AllocationRequest calldata request ) external returns (uint premium, uint allocationId); function burnStake(uint amount, BurnStakeParams calldata params) external; function depositTo( uint amount, uint trancheId, uint requestTokenId, address destination ) external returns (uint tokenId); function withdraw( uint tokenId, bool withdrawStake, bool withdrawRewards, uint[] memory trancheIds ) external returns (uint withdrawnStake, uint withdrawnRewards); function isPrivatePool() external view returns (bool); function isHalted() external view returns (bool); function manager() external view returns (address); function getPoolId() external view returns (uint); function getPoolFee() external view returns (uint); function getMaxPoolFee() external view returns (uint); function getActiveStake() external view returns (uint); function getStakeSharesSupply() external view returns (uint); function getRewardsSharesSupply() external view returns (uint); function getRewardPerSecond() external view returns (uint); function getAccNxmPerRewardsShare() external view returns (uint); function getLastAccNxmUpdate() external view returns (uint); function getFirstActiveTrancheId() external view returns (uint); function getFirstActiveBucketId() external view returns (uint); function getNextAllocationId() external view returns (uint); function getDeposit(uint tokenId, uint trancheId) external view returns ( uint lastAccNxmPerRewardShare, uint pendingRewards, uint stakeShares, uint rewardsShares ); function getTranche(uint trancheId) external view returns ( uint stakeShares, uint rewardsShares ); function getExpiredTranche(uint trancheId) external view returns ( uint accNxmPerRewardShareAtExpiry, uint stakeAmountAtExpiry, uint stakeShareSupplyAtExpiry ); function setPoolFee(uint newFee) external; function setPoolPrivacy(bool isPrivatePool) external; function getActiveAllocations( uint productId ) external view returns (uint[] memory trancheAllocations); function getTrancheCapacities( uint productId, uint firstTrancheId, uint trancheCount, uint capacityRatio, uint reductionRatio ) external view returns (uint[] memory trancheCapacities); /* ========== EVENTS ========== */ event StakeDeposited(address indexed user, uint256 amount, uint256 trancheId, uint256 tokenId); event DepositExtended(address indexed user, uint256 tokenId, uint256 initialTrancheId, uint256 newTrancheId, uint256 topUpAmount); event PoolPrivacyChanged(address indexed manager, bool isPrivate); event PoolFeeChanged(address indexed manager, uint newFee); event PoolDescriptionSet(string ipfsDescriptionHash); event Withdraw(address indexed user, uint indexed tokenId, uint tranche, uint amountStakeWithdrawn, uint amountRewardsWithdrawn); event StakeBurned(uint amount); event Deallocated(uint productId); event BucketExpired(uint bucketId); event TrancheExpired(uint trancheId); // Auth error OnlyCoverContract(); error OnlyStakingProductsContract(); error OnlyManager(); error PrivatePool(); error SystemPaused(); error PoolHalted(); // Fees error PoolFeeExceedsMax(); error MaxPoolFeeAbove100(); // Voting error NxmIsLockedForGovernanceVote(); error ManagerNxmIsLockedForGovernanceVote(); // Deposit error InsufficientDepositAmount(); error RewardRatioTooHigh(); // Staking NFTs error InvalidTokenId(); error NotTokenOwnerOrApproved(); error InvalidStakingPoolForToken(); // Tranche & capacity error NewTrancheEndsBeforeInitialTranche(); error RequestedTrancheIsNotYetActive(); error RequestedTrancheIsExpired(); error InsufficientCapacity(); // Allocation error AlreadyDeallocated(uint allocationId); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface IStakingPoolFactory { function stakingPoolCount() external view returns (uint); function beacon() external view returns (address); function create(address beacon) external returns (uint poolId, address stakingPoolAddress); event StakingPoolCreated(uint indexed poolId, address indexed stakingPoolAddress); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; import "./ISAFURAToken.sol"; interface ITokenController { struct StakingPoolNXMBalances { uint128 rewards; uint128 deposits; } struct CoverInfo { uint16 claimCount; bool hasOpenClaim; bool hasAcceptedClaim; uint96 requestedPayoutAmount; // note: still 128 bits available here, can be used later } struct StakingPoolOwnershipOffer { address proposedManager; uint96 deadline; } function coverInfo(uint id) external view returns ( uint16 claimCount, bool hasOpenClaim, bool hasAcceptedClaim, uint96 requestedPayoutAmount ); function withdrawCoverNote( address _of, uint[] calldata _coverIds, uint[] calldata _indexes ) external; function changeOperator(address _newOperator) external; function operatorTransfer(address _from, address _to, uint _value) external returns (bool); function burnFrom(address _of, uint amount) external returns (bool); function addToWhitelist(address _member) external; function removeFromWhitelist(address _member) external; function mint(address _member, uint _amount) external; function lockForMemberVote(address _of, uint _days) external; function withdrawClaimAssessmentTokens(address[] calldata users) external; function getLockReasons(address _of) external view returns (bytes32[] memory reasons); function totalSupply() external view returns (uint); function totalBalanceOf(address _of) external view returns (uint amount); function totalBalanceOfWithoutDelegations(address _of) external view returns (uint amount); function getTokenPrice() external view returns (uint tokenPrice); function token() external view returns (ISAFURAToken); function getStakingPoolManager(uint poolId) external view returns (address manager); function getManagerStakingPools(address manager) external view returns (uint[] memory poolIds); function isStakingPoolManager(address member) external view returns (bool); function getStakingPoolOwnershipOffer(uint poolId) external view returns (address proposedManager, uint deadline); function transferStakingPoolsOwnership(address from, address to) external; function assignStakingPoolManager(uint poolId, address manager) external; function createStakingPoolOwnershipOffer(uint poolId, address proposedManager, uint deadline) external; function acceptStakingPoolOwnershipOffer(uint poolId) external; function cancelStakingPoolOwnershipOffer(uint poolId) external; function mintStakingPoolNXMRewards(uint amount, uint poolId) external; function burnStakingPoolNXMRewards(uint amount, uint poolId) external; function depositStakedNXM(address from, uint amount, uint poolId) external; function withdrawNXMStakeAndRewards(address to, uint stakeToWithdraw, uint rewardsToWithdraw, uint poolId) external; function burnStakedNXM(uint amount, uint poolId) external; function stakingPoolNXMBalances(uint poolId) external view returns(uint128 rewards, uint128 deposits); function tokensLocked(address _of, bytes32 _reason) external view returns (uint256 amount); function getWithdrawableCoverNotes( address coverOwner ) external view returns ( uint[] memory coverIds, bytes32[] memory lockReasons, uint withdrawableAmount ); function getPendingRewards(address member) external view returns (uint); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.18; import "../../abstract/MasterAwareV2.sol"; import "../../interfaces/ISAFURAToken.sol"; import "../../interfaces/IPooledStaking.sol"; import "../../interfaces/ITokenController.sol"; import "../../interfaces/ICover.sol"; import "../../interfaces/IStakingPool.sol"; import "../../interfaces/IStakingNFT.sol"; contract LegacyPooledStaking is IPooledStaking, MasterAwareV2 { /* Constants */ address constant ARMOR_STAKER = 0x1337DEF1FC06783D4b03CB8C1Bf3EBf7D0593FC4; address constant ARMOR_MANAGER = 0xFa760444A229e78A50Ca9b3779f4ce4CcE10E170; address constant HUGH = 0x87B2a7559d85f4653f13E6546A14189cd5455d45; address constant NM_FOUNDATION = 0x963Df0066ff8345922dF88eebeb1095BE4e4e12E; uint constant MAX_ACTIVE_TRANCHES = 8; ICover public immutable cover; IStakingNFT public immutable stakingNFT; /* Structs */ struct StakingPoolMigrationData { address stakerAddress; address managerAddress; string ipfsDescriptionHash; bool isPrivatePool; uint initialPoolFee; uint maxPoolFee; uint deposit; uint[MAX_ACTIVE_TRANCHES] trancheStakeRatio; } /* Events */ // deposits event Deposited(address indexed staker, uint amount); event Withdrawn(address indexed staker, uint amount); // stakes event Staked(address indexed contractAddress, address indexed staker, uint amount); event UnstakeRequested(address indexed contractAddress, address indexed staker, uint amount, uint unstakeAt); event Unstaked(address indexed contractAddress, address indexed staker, uint amount); // burns event BurnRequested(address indexed contractAddress, uint amount); event Burned(address indexed contractAddress, uint amount, uint contractStakeBeforeBurn); // rewards event RewardAdded(address indexed contractAddress, uint amount); event RewardRequested(address indexed contractAddress, uint amount); event Rewarded(address indexed contractAddress, uint amount, uint contractStake); event RewardWithdrawn(address indexed staker, uint amount); // pending actions processing event PendingActionsProcessed(bool finished); /* Storage variables */ /* Deleted storage variables bool public initialized; ISAFURAToken public token; These 2 variables occupied 1 slot. The MasterAwareV2 interface has 1 extra slot more compared to MasterAware. MasterAware.master storage variable is now overwriting initialized and token. */ // was tokenController address internal _unused0; uint public MIN_STAKE; // Minimum allowed stake per contract uint public MAX_EXPOSURE; // Stakes sum must be less than the deposit amount times this uint public MIN_UNSTAKE; // Forbid unstake of small amounts to prevent spam uint public UNSTAKE_LOCK_TIME; // Lock period in seconds before unstaking takes place mapping(address => Staker) public stakers; // stakerAddress => Staker // temporary variables uint public contractStaked; // used when processing burns and rewards uint public contractBurned; // used when processing burns uint public contractRewarded; // used when processing rewards // list of stakers for all contracts mapping(address => address[]) public contractStakers; // there can be only one pending burn Burn public burn; mapping(uint => Reward) public rewards; // reward id => Reward uint public firstReward; uint public lastRewardId; mapping(uint => UnstakeRequest) public unstakeRequests; // unstake id => UnstakeRequest // firstUnstakeRequest is stored at unstakeRequests[0].next uint public lastUnstakeRequestId; uint public processedToStakerIndex; // we processed the action up this staker bool public isContractStakeCalculated; // flag to indicate whether staked amount is up to date or not /* state vars for rewards groupping upgrade */ // rewards to be distributed at the end of the current round // contract address => ContractRewards mapping(address => ContractReward) public accumulatedRewards; uint public REWARD_ROUND_DURATION; uint public REWARD_ROUNDS_START; ISAFURAToken internal immutable token; /* Modifiers */ modifier noPendingActions { require(!hasPendingActions(), "Unable to execute request with unprocessed actions"); _; } modifier noPendingBurns { require(!hasPendingBurns(), "Unable to execute request with unprocessed burns"); _; } modifier noPendingUnstakeRequests { require(!hasPendingUnstakeRequests(), "Unable to execute request with unprocessed unstake requests"); _; } modifier noPendingRewards { require(!hasPendingRewards(), "Unable to execute request with unprocessed rewards"); _; } constructor(address coverAddress, address stakingNFTAddress, address _tokenAddress) { cover = ICover(coverAddress); stakingNFT = IStakingNFT(stakingNFTAddress); token = ISAFURAToken(_tokenAddress); } function min(uint x, uint y) pure internal returns (uint) { return x < y ? x : y; } /* Getters and view functions */ function contractStakerCount(address contractAddress) external view returns (uint) { return contractStakers[contractAddress].length; } function contractStakerAtIndex(address contractAddress, uint stakerIndex) external view returns (address) { return contractStakers[contractAddress][stakerIndex]; } function contractStakersArray(address contractAddress) external view returns (address[] memory _stakers) { return contractStakers[contractAddress]; } function contractStake(address contractAddress) public override view returns (uint) { address[] storage _stakers = contractStakers[contractAddress]; uint stakerCount = _stakers.length; uint stakedOnContract; for (uint i = 0; i < stakerCount; i++) { Staker storage staker = stakers[_stakers[i]]; uint deposit = staker.deposit; uint stake = staker.stakes[contractAddress]; // add the minimum of the two stake = deposit < stake ? deposit : stake; stakedOnContract = stakedOnContract + stake; } return stakedOnContract; } function stakerContractCount(address staker) external view returns (uint) { return stakers[staker].contracts.length; } function stakerContractAtIndex(address staker, uint contractIndex) external view returns (address) { return stakers[staker].contracts[contractIndex]; } function stakerContractsArray(address staker) external view returns (address[] memory) { return stakers[staker].contracts; } function stakerContractStake(address staker, address contractAddress) public override view returns (uint) { uint stake = stakers[staker].stakes[contractAddress]; uint deposit = stakers[staker].deposit; return stake < deposit ? stake : deposit; } function stakerContractPendingUnstakeTotal(address staker, address contractAddress) external view returns (uint) { return stakers[staker].pendingUnstakeRequestsTotal[contractAddress]; } function stakerReward(address staker) external override view returns (uint) { return stakers[staker].reward; } function stakerDeposit(address staker) external override view returns (uint) { return stakers[staker].deposit; } function stakerMaxWithdrawable(address stakerAddress) public override view returns (uint) { Staker storage staker = stakers[stakerAddress]; uint deposit = staker.deposit; uint totalStaked; uint maxStake; for (uint i = 0; i < staker.contracts.length; i++) { address contractAddress = staker.contracts[i]; uint initialStake = staker.stakes[contractAddress]; uint stake = deposit < initialStake ? deposit : initialStake; totalStaked = totalStaked + stake; if (stake > maxStake) { maxStake = stake; } } uint minRequired = totalStaked / MAX_EXPOSURE; uint locked = maxStake > minRequired ? maxStake : minRequired; return deposit - locked; } function unstakeRequestAtIndex(uint unstakeRequestId) external view returns ( uint amount, uint unstakeAt, address contractAddress, address stakerAddress, uint next ) { UnstakeRequest storage unstakeRequest = unstakeRequests[unstakeRequestId]; amount = unstakeRequest.amount; unstakeAt = unstakeRequest.unstakeAt; contractAddress = unstakeRequest.contractAddress; stakerAddress = unstakeRequest.stakerAddress; next = unstakeRequest.next; } function hasPendingActions() public override view returns (bool) { return hasPendingBurns() || hasPendingUnstakeRequests() || hasPendingRewards(); } function hasPendingBurns() public view returns (bool) { return burn.burnedAt != 0; } function hasPendingUnstakeRequests() public view returns (bool){ uint nextRequestIndex = unstakeRequests[0].next; if (nextRequestIndex == 0) { return false; } return unstakeRequests[nextRequestIndex].unstakeAt <= block.timestamp; } function hasPendingRewards() public view returns (bool){ return rewards[firstReward].rewardedAt != 0; } /* State-changing functions */ function depositAndStake( uint /*amount*/, address[] calldata /*_contracts*/, uint[] calldata /*_stakes*/ ) external pure { revert("Migrate to v2"); } function withdraw(uint /*ignoredParam*/) external override whenNotPaused onlyMember noPendingBurns { _withdrawForUser(msg.sender); } function withdrawForUser(address user) external override whenNotPaused onlyMember noPendingBurns { _withdrawForUser(user); } function _withdrawForUser(address user) internal { // Stakers scheduled for automatic migration are not allowed to withdraw require( user != ARMOR_STAKER && user != HUGH && user != NM_FOUNDATION, "Not allowed to withdraw" ); uint amount = stakers[user].deposit; stakers[user].deposit = 0; token.transfer(user, amount); emit Withdrawn(user, amount); } function requestUnstake( address[] calldata /*_contracts*/, uint[] calldata /*_amounts*/, uint /*_insertAfter*/ // unstake request id after which the new unstake request will be inserted ) external pure { revert("Migrate to v2"); } function withdrawReward(address stakerAddress) external override whenNotPaused { uint amount = stakers[stakerAddress].reward; stakers[stakerAddress].reward = 0; token.transfer(stakerAddress, amount); emit RewardWithdrawn(stakerAddress, amount); } function pushBurn(address /*contractAddress*/, uint /*amount*/) external pure override { revert("Migrate to v2"); } function _getCurrentRewardsRound() internal view returns (uint) { uint roundDuration = REWARD_ROUND_DURATION; uint startTime = REWARD_ROUNDS_START; require(startTime != 0, "REWARD_ROUNDS_START is not initialized"); return block.timestamp <= startTime ? 0 : (block.timestamp - startTime) / roundDuration; } function getCurrentRewardsRound() external view returns (uint) { return _getCurrentRewardsRound(); } /** * @dev Pushes accumulated rewards to the processing queue. */ function _pushRewards(address[] memory contractAddresses, bool skipRoundCheck) internal { uint currentRound = _getCurrentRewardsRound(); uint lastRewardIdCounter = lastRewardId; uint pushedRewards = 0; for (uint i = 0; i < contractAddresses.length; i++) { address contractAddress = contractAddresses[i]; ContractReward storage contractRewards = accumulatedRewards[contractAddress]; uint lastRound = contractRewards.lastDistributionRound; uint amount = contractRewards.amount; bool shouldPush = amount > 0 && (skipRoundCheck || currentRound > lastRound); if (!shouldPush) { // prevent unintended distribution of the first reward in round if (lastRound != currentRound) { contractRewards.lastDistributionRound = currentRound; } continue; } rewards[++lastRewardIdCounter] = Reward(amount, block.timestamp, contractAddress); emit RewardRequested(contractAddress, amount); contractRewards.amount = 0; contractRewards.lastDistributionRound = currentRound; ++pushedRewards; if (pushedRewards == 1 && firstReward == 0) { firstReward = lastRewardIdCounter; } } if (pushedRewards != 0) { lastRewardId = lastRewardIdCounter; } } /** * @dev External function for pushing accumulated rewards in the processing queue. * @dev `_pushRewards` checks the current round and will only push if rewards can be distributed. */ function pushRewards(address[] calldata contractAddresses) external whenNotPaused { _pushRewards(contractAddresses, true); } /** * @dev Add reward for contract. Automatically triggers distribution if enough time has passed. */ function accumulateReward(address /*contractAddress*/, uint /*amount*/) external override pure { revert("Migrate to v2"); } function processPendingActions(uint maxIterations) public override whenNotPaused returns (bool finished) { (finished,) = _processPendingActions(maxIterations); } function processPendingActionsReturnLeft(uint maxIterations) public whenNotPaused returns (bool finished, uint iterationsLeft) { (finished, iterationsLeft) = _processPendingActions(maxIterations); } function _processPendingActions(uint maxIterations) public whenNotPaused returns (bool finished, uint iterationsLeft) { iterationsLeft = maxIterations; while (true) { uint firstUnstakeRequestIndex = unstakeRequests[0].next; UnstakeRequest storage unstakeRequest = unstakeRequests[firstUnstakeRequestIndex]; Reward storage reward = rewards[firstReward]; // read storage and cache in memory uint burnedAt = burn.burnedAt; uint rewardedAt = reward.rewardedAt; uint unstakeAt = unstakeRequest.unstakeAt; bool canUnstake = firstUnstakeRequestIndex > 0 && unstakeAt <= block.timestamp; bool canBurn = burnedAt != 0; bool canReward = firstReward != 0; if (!canBurn && !canUnstake && !canReward) { // everything is processed break; } if ( canBurn && (!canUnstake || burnedAt < unstakeAt) && (!canReward || burnedAt < rewardedAt) ) { (finished, iterationsLeft) = _processBurn(iterationsLeft); if (!finished) { emit PendingActionsProcessed(false); return (false, iterationsLeft); } continue; } if ( canUnstake && (!canReward || unstakeAt < rewardedAt) ) { // _processFirstUnstakeRequest is O(1) so we'll handle the iteration checks here if (iterationsLeft == 0) { emit PendingActionsProcessed(false); return (false, iterationsLeft); } _processFirstUnstakeRequest(); --iterationsLeft; continue; } (finished, iterationsLeft) = _processFirstReward(iterationsLeft); if (!finished) { emit PendingActionsProcessed(false); return (false, iterationsLeft); } } // everything is processed! emit PendingActionsProcessed(true); return (true, iterationsLeft); } function _processBurn(uint maxIterations) internal returns (bool finished, uint iterationsLeft) { iterationsLeft = maxIterations; address _contractAddress = burn.contractAddress; uint _stakedOnContract; (_stakedOnContract, finished, iterationsLeft) = _calculateContractStake(_contractAddress, iterationsLeft); if (!finished) { return (false, iterationsLeft); } address[] storage _contractStakers = contractStakers[_contractAddress]; uint _stakerCount = _contractStakers.length; uint _totalBurnAmount = burn.amount; uint _actualBurnAmount = contractBurned; if (_totalBurnAmount > _stakedOnContract) { _totalBurnAmount = _stakedOnContract; } for (uint i = processedToStakerIndex; i < _stakerCount; ) { if (iterationsLeft == 0) { contractBurned = _actualBurnAmount; processedToStakerIndex = i; return (false, iterationsLeft); } --iterationsLeft; Staker storage staker = stakers[_contractStakers[i]]; uint _stakerBurnAmount; uint _newStake; (_stakerBurnAmount, _newStake) = _burnStaker(staker, _contractAddress, _stakedOnContract, _totalBurnAmount); _actualBurnAmount = _actualBurnAmount + _stakerBurnAmount; if (_newStake != 0) { i++; continue; } // if we got here, the stake is explicitly set to 0 // the staker is removed from the contract stakers array // and we will add the staker back if he stakes again staker.isInContractStakers[_contractAddress] = false; _contractStakers[i] = _contractStakers[_stakerCount - 1]; _contractStakers.pop(); _stakerCount--; } delete burn; contractBurned = 0; processedToStakerIndex = 0; isContractStakeCalculated = false; token.burn(_actualBurnAmount); emit Burned(_contractAddress, _actualBurnAmount, _stakedOnContract); return (true, iterationsLeft); } function _burnStaker( Staker storage staker, address _contractAddress, uint _stakedOnContract, uint _totalBurnAmount ) internal returns ( uint _stakerBurnAmount, uint _newStake ) { uint _currentDeposit; uint _currentStake; // silence compiler warning _newStake = 0; // do we need a storage read? if (_stakedOnContract != 0) { _currentDeposit = staker.deposit; _currentStake = staker.stakes[_contractAddress]; if (_currentStake > _currentDeposit) { _currentStake = _currentDeposit; } } if (_stakedOnContract != _totalBurnAmount) { // formula: staker_burn = staker_stake / total_contract_stake * contract_burn // reordered for precision loss prevention _stakerBurnAmount = _currentStake * _totalBurnAmount / _stakedOnContract; _newStake = _currentStake - _stakerBurnAmount; } else { // it's the whole stake _stakerBurnAmount = _currentStake; } if (_stakerBurnAmount != 0) { staker.deposit = _currentDeposit - _stakerBurnAmount; } staker.stakes[_contractAddress] = _newStake; } function _calculateContractStake( address _contractAddress, uint maxIterations ) internal returns ( uint _stakedOnContract, bool finished, uint iterationsLeft ) { iterationsLeft = maxIterations; if (isContractStakeCalculated) { // use previously calculated staked amount return (contractStaked, true, iterationsLeft); } address[] storage _contractStakers = contractStakers[_contractAddress]; uint _stakerCount = _contractStakers.length; uint startIndex = processedToStakerIndex; if (startIndex != 0) { _stakedOnContract = contractStaked; } // calculate amount staked on contract for (uint i = startIndex; i < _stakerCount; i++) { if (iterationsLeft == 0) { processedToStakerIndex = i; contractStaked = _stakedOnContract; return (_stakedOnContract, false, iterationsLeft); } --iterationsLeft; Staker storage staker = stakers[_contractStakers[i]]; uint deposit = staker.deposit; uint stake = staker.stakes[_contractAddress]; stake = deposit < stake ? deposit : stake; _stakedOnContract = _stakedOnContract + stake; } contractStaked = _stakedOnContract; isContractStakeCalculated = true; processedToStakerIndex = 0; return (_stakedOnContract, true, iterationsLeft); } function _processFirstUnstakeRequest() internal { uint firstRequest = unstakeRequests[0].next; UnstakeRequest storage unstakeRequest = unstakeRequests[firstRequest]; address stakerAddress = unstakeRequest.stakerAddress; Staker storage staker = stakers[stakerAddress]; address contractAddress = unstakeRequest.contractAddress; uint deposit = staker.deposit; uint initialStake = staker.stakes[contractAddress]; uint stake = deposit < initialStake ? deposit : initialStake; uint requestedAmount = unstakeRequest.amount; uint actualUnstakedAmount = stake < requestedAmount ? stake : requestedAmount; staker.stakes[contractAddress] = stake - actualUnstakedAmount; uint pendingUnstakeRequestsTotal = staker.pendingUnstakeRequestsTotal[contractAddress]; staker.pendingUnstakeRequestsTotal[contractAddress] = pendingUnstakeRequestsTotal - requestedAmount; // update pointer to first unstake request unstakeRequests[0].next = unstakeRequest.next; delete unstakeRequests[firstRequest]; emit Unstaked(contractAddress, stakerAddress, requestedAmount); } function _processFirstReward(uint maxIterations) internal returns (bool finished, uint iterationsLeft) { iterationsLeft = maxIterations; Reward storage reward = rewards[firstReward]; address _contractAddress = reward.contractAddress; uint _totalRewardAmount = reward.amount; uint _stakedOnContract; (_stakedOnContract, finished, iterationsLeft) = _calculateContractStake(_contractAddress, iterationsLeft); if (!finished) { return (false, iterationsLeft); } address[] storage _contractStakers = contractStakers[_contractAddress]; uint _stakerCount = _contractStakers.length; uint _actualRewardAmount = contractRewarded; for (uint i = processedToStakerIndex; i < _stakerCount;) { if (iterationsLeft == 0) { contractRewarded = _actualRewardAmount; processedToStakerIndex = i; return (false, iterationsLeft); } --iterationsLeft; address _stakerAddress = _contractStakers[i]; (uint _stakerRewardAmount, uint _stake) = _rewardStaker( _stakerAddress, _contractAddress, _totalRewardAmount, _stakedOnContract ); // remove 0-amount stakers, similar to what we're doing when processing burns if (_stake == 0) { // mark the user as not present in contract stakers array Staker storage staker = stakers[_stakerAddress]; staker.isInContractStakers[_contractAddress] = false; // remove the staker from the contract stakers array _contractStakers[i] = _contractStakers[_stakerCount - 1]; _contractStakers.pop(); _stakerCount--; // since the stake is 0, there's no reward to give continue; } _actualRewardAmount = _actualRewardAmount + _stakerRewardAmount; i++; } delete rewards[firstReward]; contractRewarded = 0; processedToStakerIndex = 0; isContractStakeCalculated = false; if (++firstReward > lastRewardId) { firstReward = 0; } tokenController().mint(address(this), _actualRewardAmount); emit Rewarded(_contractAddress, _actualRewardAmount, _stakedOnContract); return (true, iterationsLeft); } function _rewardStaker( address stakerAddress, address contractAddress, uint totalRewardAmount, uint totalStakedOnContract ) internal returns (uint rewardedAmount, uint stake) { Staker storage staker = stakers[stakerAddress]; uint deposit = staker.deposit; stake = staker.stakes[contractAddress]; if (stake > deposit) { stake = deposit; } // prevent division by zero and set stake to zero if (totalStakedOnContract == 0 || stake == 0) { staker.stakes[contractAddress] = 0; return (0, 0); } // reward = staker_stake / total_contract_stake * total_reward rewardedAmount = totalRewardAmount * stake / totalStakedOnContract; staker.reward = staker.reward + rewardedAmount; } function updateUintParameters(bytes8 code, uint value) external onlyGovernance { if (code == "MIN_STAK") { MIN_STAKE = value; return; } if (code == "MAX_EXPO") { MAX_EXPOSURE = value; return; } if (code == "MIN_UNST") { MIN_UNSTAKE = value; return; } if (code == "UNST_LKT") { UNSTAKE_LOCK_TIME = value; return; } } function tokenController() internal view returns (ITokenController) { return ITokenController(internalContracts[uint(ID.TC)]); } function memberRoles() internal view returns (IMemberRoles) { return IMemberRoles(internalContracts[uint(ID.MR)]); } function changeDependentContractAddress() public { internalContracts[uint(ID.TC)] = master.getLatestAddress("TC"); internalContracts[uint(ID.MR)] = master.getLatestAddress("MR"); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BurnRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"contractStakeBeforeBurn","type":"uint256"}],"name":"Burned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"finished","type":"bool"}],"name":"PendingActionsProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"contractStake","type":"uint256"}],"name":"Rewarded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unstakeAt","type":"uint256"}],"name":"UnstakeRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unstaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"MAX_EXPOSURE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_STAKE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_UNSTAKE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_ROUNDS_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_ROUND_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNSTAKE_LOCK_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxIterations","type":"uint256"}],"name":"_processPendingActions","outputs":[{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256","name":"iterationsLeft","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"accumulateReward","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"accumulatedRewards","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"lastDistributionRound","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burn","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"burnedAt","type":"uint256"},{"internalType":"address","name":"contractAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"changeDependentContractAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"masterAddress","type":"address"}],"name":"changeMasterAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractBurned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractRewarded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"name":"contractStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"stakerIndex","type":"uint256"}],"name":"contractStakerAtIndex","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"name":"contractStakerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"contractStakers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"name":"contractStakersArray","outputs":[{"internalType":"address[]","name":"_stakers","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cover","outputs":[{"internalType":"contract ICover","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"name":"depositAndStake","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"firstReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentRewardsRound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hasPendingActions","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hasPendingBurns","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hasPendingRewards","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hasPendingUnstakeRequests","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"_tokenControllerAddress","type":"address"},{"internalType":"uint256","name":"minStake","type":"uint256"},{"internalType":"uint256","name":"minUnstake","type":"uint256"},{"internalType":"uint256","name":"maxExposure","type":"uint256"},{"internalType":"uint256","name":"unstakeLockTime","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"internalContracts","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isContractStakeCalculated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastRewardId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUnstakeRequestId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"master","outputs":[{"internalType":"contract ISAFURAMaster","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxIterations","type":"uint256"}],"name":"processPendingActions","outputs":[{"internalType":"bool","name":"finished","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxIterations","type":"uint256"}],"name":"processPendingActionsReturnLeft","outputs":[{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256","name":"iterationsLeft","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"processedToStakerIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"pushBurn","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address[]","name":"contractAddresses","type":"address[]"}],"name":"pushRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"requestUnstake","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewards","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"rewardedAt","type":"uint256"},{"internalType":"address","name":"contractAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"uint256","name":"contractIndex","type":"uint256"}],"name":"stakerContractAtIndex","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"stakerContractCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"contractAddress","type":"address"}],"name":"stakerContractPendingUnstakeTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"contractAddress","type":"address"}],"name":"stakerContractStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"stakerContractsArray","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"stakerDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stakerAddress","type":"address"}],"name":"stakerMaxWithdrawable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"stakerReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakers","outputs":[{"internalType":"uint256","name":"deposit","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingNFT","outputs":[{"internalType":"contract IStakingNFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"unstakeRequestId","type":"uint256"}],"name":"unstakeRequestAtIndex","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"unstakeAt","type":"uint256"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"address","name":"stakerAddress","type":"address"},{"internalType":"uint256","name":"next","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"unstakeRequests","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"unstakeAt","type":"uint256"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"address","name":"stakerAddress","type":"address"},{"internalType":"uint256","name":"next","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes8","name":"code","type":"bytes8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"updateUintParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"withdrawForUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"stakerAddress","type":"address"}],"name":"withdrawReward","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60e06040523480156200001157600080fd5b5060405162002e6738038062002e67833981016040819052620000349162000050565b6000608081905260a0526001600160a01b031660c05262000082565b6000602082840312156200006357600080fd5b81516001600160a01b03811681146200007b57600080fd5b9392505050565b60805160a05160c051612da7620000c06000396000818161163401528181611bb80152611f33015260006103a9015260006107b50152612da76000f3fe608060405234801561001057600080fd5b50600436106103835760003560e01c80639168ae72116101de578063e3bc92c01161010f578063f0f923c0116100ad578063f6ceefa21161007c578063f6ceefa21461089a578063f87975af146108ad578063f92ad219146108f7578063ff551c841461090a57600080fd5b8063f0f923c01461053a578063f2078db514610846578063f301af4214610859578063f52790bc1461089157600080fd5b8063eae01718116100e9578063eae01718146107e4578063eb962360146107f7578063ee97f7f314610820578063ef30375d1461083357600080fd5b8063e3bc92c014610734578063e7d931e4146107b0578063ead4d174146107d757600080fd5b8063afd369fd1161017c578063c65cfd5211610156578063c65cfd52146106fc578063cb1c2b5c14610705578063d46655f41461070e578063d6b5b8521461072157600080fd5b8063afd369fd146106c8578063b86e321c146106db578063c001472e146106ee57600080fd5b80639dd86e0f116101b85780639dd86e0f1461065c578063a4cc380b1461066f578063a81d80101461068b578063abb215be146106b557600080fd5b80639168ae72146106235780639abbed051461064a5780639c6f6e841461065357600080fd5b806339ac5eb9116102b857806373f273fc1161025657806376552b341161023057806376552b34146105d057806385b39d83146105e35780638e91e6bd1461060c578063908ad10a1461061a57600080fd5b806373f273fc1461056057806374ff6b901461059c57806375a7720f146105a457600080fd5b806365f212f91161029257806365f212f91461052757806368989a591461053a5780637272135a1461054d57806372af29321461055757600080fd5b806339ac5eb91461049f57806344df8e70146104c85780635840ee441461050757600080fd5b80631a839ba711610325578063285ece4e116102ff578063285ece4e146104675780632e1a7d4d146104705780632e23dc8f1461048357806334892cea1461048c57600080fd5b80631a839ba71461043e57806322b1c2961461045657806324f412541461045e57600080fd5b80630ea9c984116103615780630ea9c9841461040f5780631354839d1461041957806315c5673c1461042c5780631694a36a1461043557600080fd5b80630ca6de03146103885780630ce71e32146103a45780630ea474c7146103e3575b600080fd5b61039160055481565b6040519081526020015b60405180910390f35b6103cb7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161039b565b6103916103f13660046128ed565b6001600160a01b031660009081526007602052604090206001015490565b61041761091d565b005b6103cb610427366004612911565b610a84565b61039160145481565b61039160185481565b610446610abc565b604051901515815260200161039b565b610446610aff565b61039160045481565b61039160175481565b61041761047e36600461293d565b610b40565b61039160105481565b61039161049a366004612956565b610ce9565b6103916104ad3660046128ed565b6001600160a01b031660009081526007602052604090205490565b600c54600d54600e546104e39291906001600160a01b031683565b6040805193845260208401929092526001600160a01b03169082015260600161039b565b61051a6105153660046128ed565b610d1a565b60405161039b919061298f565b6103916105353660046128ed565b610d93565b610417610548366004612911565b610e4a565b600d541515610446565b61039160135481565b61058761056e3660046128ed565b6016602052600090815260409020805460019091015482565b6040805192835260208301919091520161039b565b610391610e82565b6103916105b23660046128ed565b6001600160a01b031660009081526007602052604090206002015490565b6104176105de3660046128ed565b610e8c565b6103916105f13660046128ed565b6001600160a01b03166000908152600b602052604090205490565b610417610548366004612a28565b61039160065481565b6105876106313660046128ed565b6007602052600090815260409020805460019091015482565b610391600a5481565b61039160095481565b61041761066a366004612a9c565b611029565b6010546000908152600f60205260409020600101541515610446565b61069e61069936600461293d565b611178565b60408051921515835260208301919091520161039b565b61069e6106c336600461293d565b6113dc565b6103916106d63660046128ed565b61147d565b6104176106e93660046128ed565b611563565b610417610548366004612ac7565b61039160085481565b61039160035481565b61041761071c3660046128ed565b6116e9565b6103cb61072f366004612911565b611763565b61077c61074236600461293d565b60009081526012602052604090208054600182015460028301546003840154600490940154929491936001600160a01b0391821693911691565b6040805195865260208601949094526001600160a01b0392831693850193909352166060830152608082015260a00161039b565b6103cb7f000000000000000000000000000000000000000000000000000000000000000081565b6015546104469060ff1681565b6103916107f2366004612956565b6117a9565b6103cb61080536600461293d565b6001602052600090815260409020546001600160a01b031681565b6000546103cb906001600160a01b031681565b6103cb610841366004612911565b6117f1565b61051a6108543660046128ed565b61181e565b6104e361086736600461293d565b600f602052600090815260409020805460018201546002909201549091906001600160a01b031683565b61039160115481565b6104176108a8366004612b41565b611892565b61077c6108bb36600461293d565b60126020526000908152604090208054600182015460028301546003840154600490940154929391926001600160a01b03918216929091169085565b610417610905366004612b83565b611963565b61044661091836600461293d565b611a18565b6000546040516227050b60e31b815261544360f01b60048201526001600160a01b0390911690630138285890602401602060405180830381865afa158015610969573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098d9190612bc7565b600080805260016020527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4980546001600160a01b039384166001600160a01b0319909116179055546040516227050b60e31b81526126a960f11b6004820152911690630138285890602401602060405180830381865afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a399190612bc7565b600260005260016020527fd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f80546001600160a01b0319166001600160a01b0392909216919091179055565b600b6020528160005260406000208181548110610aa057600080fd5b6000918252602090912001546001600160a01b03169150829050565b60008080526012602052600080516020612d5283398151915254808203610ae557600091505090565b600090815260126020526040902060010154421015919050565b6000610b0c600d54151590565b80610b1a5750610b1a610abc565b80610b3b5750506010546000908152600f6020526040902060010154151590565b905090565b60008054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb59190612be4565b15610bdb5760405162461bcd60e51b8152600401610bd290612c06565b60405180910390fd5b6002600081905260016020527fd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f5460405163505ef22f60e01b815233600482015260248101929092526001600160a01b03169063505ef22f90604401602060405180830381865afa158015610c54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c789190612be4565b610cbd5760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba10309036b2b6b132b960511b6044820152606401610bd2565b600d5415610cdd5760405162461bcd60e51b8152600401610bd290612c30565b610ce633611abd565b50565b6001600160a01b03808316600090815260076020908152604080832093851683526004909301905220545b92915050565b6001600160a01b038116600090815260076020908152604091829020600201805483518184028101840190945280845260609392830182828015610d8757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610d69575b50505050509050919050565b6001600160a01b0381166000908152600b60205260408120805482805b82811015610e4157600060076000868481548110610dd057610dd0612c80565b60009182526020808320909101546001600160a01b03908116845283820194909452604092830182208054948c1683526003810190915291902054909250808210610e1b5780610e1d565b815b9050610e298186612cac565b94505050508080610e3990612cbf565b915050610db0565b50949350505050565b60405162461bcd60e51b815260206004820152600d60248201526c26b4b3b930ba32903a37903b1960991b6044820152606401610bd2565b6000610b3b611c61565b60008054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610edd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f019190612be4565b15610f1e5760405162461bcd60e51b8152600401610bd290612c06565b6002600081905260016020527fd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f5460405163505ef22f60e01b815233600482015260248101929092526001600160a01b03169063505ef22f90604401602060405180830381865afa158015610f97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fbb9190612be4565b6110005760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba10309036b2b6b132b960511b6044820152606401610bd2565b600d54156110205760405162461bcd60e51b8152600401610bd290612c30565b610ce681611abd565b600054604051632c1a733d60e11b81523360048201526001600160a01b0390911690635834e67a90602401602060405180830381865afa158015611071573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110959190612be4565b6110ec5760405162461bcd60e51b815260206004820152602260248201527f43616c6c6572206973206e6f7420617574686f72697a656420746f20676f7665604482015261393760f11b6064820152608401610bd2565b6001600160c01b03198216674d494e5f5354414b60c01b0361110e5760035550565b6001600160c01b03198216674d41585f4558504f60c01b036111305760045550565b6001600160c01b031982166713525397d55394d560c21b036111525760055550565b6001600160c01b0319821667155394d517d312d560c21b036111745760068190555b5050565b6000805460408051600162f6c75960e01b03198152905183926001600160a01b03169163ff0938a79160048083019260209291908290030181865afa1580156111c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e99190612be4565b156112065760405162461bcd60e51b8152600401610bd290612c06565b50815b60126020908152600080516020612d5283398151915254600081815260408082206010548352600f9094528120600d5460018083015490860154949594929391929091861580159061125b5750428211155b601054909150841580159115159082611272575082155b801561127c575080155b1561128f5750505050505050505061139f565b8180156112a357508215806112a357508386105b80156112b657508015806112b657508486105b15611323576112c48a611cf5565b909b5099508a61131557604051600081527ff3b343b97db20514b20b9c54105a005716230e231e9bf5d180b1a0dfe6e4fb8a906020015b60405180910390a160009a50505050505050505050915091565b505050505050505050611209565b828015611337575080158061133757508484105b15611396578960000361137557604051600081527ff3b343b97db20514b20b9c54105a005716230e231e9bf5d180b1a0dfe6e4fb8a906020016112fb565b61137d611ff4565b6113868a612cd8565b9950505050505050505050611209565b6112c48a612170565b604051600181527ff3b343b97db20514b20b9c54105a005716230e231e9bf5d180b1a0dfe6e4fb8a9060200160405180910390a160019150915091565b6000805460408051600162f6c75960e01b03198152905183926001600160a01b03169163ff0938a79160048083019260209291908290030181865afa158015611429573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144d9190612be4565b1561146a5760405162461bcd60e51b8152600401610bd290612c06565b61147383611178565b9094909350915050565b6001600160a01b038116600090815260076020526040812080548280805b60028501548110156115275760008560020182815481106114be576114be612c80565b60009182526020808320909101546001600160a01b0316808352600389019091526040822054909250908187106114f557816114f7565b865b90506115038187612cac565b955084811115611511578094505b505050808061151f90612cbf565b91505061149b565b506000600454836115389190612cef565b90506000818311611549578161154b565b825b90506115578186612d11565b98975050505050505050565b60008054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d89190612be4565b156115f55760405162461bcd60e51b8152600401610bd290612c06565b6001600160a01b0381811660008181526007602052604080822060010180549290555163a9059cbb60e01b8152600481019290925260248201819052917f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af115801561167d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a19190612be4565b50816001600160a01b03167f1d3eee4ca001cff39eec6ec7615aacf2f2bd61791273830728ba00ccbd6e1337826040516116dd91815260200190565b60405180910390a25050565b6000546001600160a01b031615611741576000546001600160a01b031633146117415760405162461bcd60e51b815260206004820152600a6024820152692737ba1036b0b9ba32b960b11b6044820152606401610bd2565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0382166000908152600b6020526040812080548390811061178d5761178d612c80565b6000918252602090912001546001600160a01b03169392505050565b6001600160a01b03808316600081815260076020818152604080842095871684526003860182528320549383525291548082106117e657806117e8565b815b95945050505050565b6001600160a01b038216600090815260076020526040812060020180548390811061178d5761178d612c80565b6001600160a01b0381166000908152600b6020908152604091829020805483518184028101840190945280845260609392830182828015610d87576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610d695750505050509050919050565b60008054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119079190612be4565b156119245760405162461bcd60e51b8152600401610bd290612c06565b611174828280806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250600192506124b6915050565b6000805260016020527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4980546001600160a01b0387166001600160a01b0319909116811790915560405163e43252d760e01b815230600482015263e43252d790602401600060405180830381600087803b1580156119e057600080fd5b505af11580156119f4573d6000803e3d6000fd5b505050600394909455600592909255600455600655505062093a8060175542601855565b60008060009054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a909190612be4565b15611aad5760405162461bcd60e51b8152600401610bd290612c06565b611ab682611178565b5092915050565b6001600160a01b038116731337def1fc06783d4b03cb8c1bf3ebf7d0593fc414801590611b0757506001600160a01b0381167387b2a7559d85f4653f13e6546a14189cd5455d4514155b8015611b3057506001600160a01b03811673963df0066ff8345922df88eebeb1095be4e4e12e14155b611b7c5760405162461bcd60e51b815260206004820152601760248201527f4e6f7420616c6c6f77656420746f2077697468647261770000000000000000006044820152606401610bd2565b6001600160a01b0381811660008181526007602052604080822080549290555163a9059cbb60e01b8152600481019290925260248201819052917f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015611c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c259190612be4565b50816001600160a01b03167f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5826040516116dd91815260200190565b60175460185460009190808303611cc95760405162461bcd60e51b815260206004820152602660248201527f5245574152445f524f554e44535f5354415254206973206e6f7420696e697469604482015265185b1a5e995960d21b6064820152608401610bd2565b80421115611ceb5781611cdc8242612d11565b611ce69190612cef565b611cee565b60005b9250505090565b600e5460009082906001600160a01b031682611d118284612659565b9095509350905083611d2857600093505050915091565b6001600160a01b0382166000908152600b602052604090208054600c5460095484821115611d54578491505b6014545b83811015611ee65787600003611d81576009919091556014555060009794965093945050505050565b611d8a88612cd8565b9750600060076000878481548110611da457611da4612c80565b60009182526020808320909101546001600160a01b031683528201929092526040018120915080611dd7838b8b89612784565b9092509050611de68286612cac565b94508015611e035783611df881612cbf565b945050505050611d58565b6001600160a01b038a1660009081526005840160205260409020805460ff1916905587611e31600189612d11565b81548110611e4157611e41612c80565b9060005260206000200160009054906101000a90046001600160a01b0316888581548110611e7157611e71612c80565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555087805480611eaf57611eaf612d24565b600082815260209020810160001990810180546001600160a01b031916905501905586611edb81612cd8565b975050505050611d58565b506000600c819055600d819055600e80546001600160a01b031916905560098190556014556015805460ff19169055604051630852cd8d60e31b8152600481018290526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342966c68906024016020604051808303816000875af1158015611f7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa09190612be4565b5060408051828152602081018790526001600160a01b038816917f23ff0e75edf108e3d0392d92e13e8c8a868ef19001bd49f9e94876dc46dff87f910160405180910390a260019750505050505050915091565b60126020908152600080516020612d5283398151915254600081815260408082206003808201546001600160a01b039081168086526007885284862060028501548154931680885293810190985293852054959692959394929391929091908183106120605781612062565b825b875490915060008183106120765781612078565b825b90506120848184612d11565b6001600160a01b038716600090815260038901602090815260408083209390935560048a01905220546120b78382612d11565b6001600160a01b0380891660008181526004808d0160209081526040808420969096558f8201546012909152600080516020612d52833981519152558f8252848220828155600181018390556002810180546001600160a01b0319908116909155600382018054909116905501559151908b1691907fd8654fcc8cf5b36d30b3f5e4688fc78118e6d68de60b9994e09902268b57c3e39061215b9087815260200190565b60405180910390a35050505050505050505050565b6010546000908152600f60205260408120600281015481548492916001600160a01b031690846121a08386612659565b90975095509050856121b9576000955050505050915091565b6001600160a01b0383166000908152600b602052604090208054600a546014545b82811015612367578860000361220457600a91909155601455506000989597509495505050505050565b61220d89612cd8565b9850600084828154811061222357612223612c80565b60009182526020822001546001600160a01b0316915080612246838b8b8b612829565b9150915080600003612346576001600160a01b038084166000908152600760209081526040808320938e168352600584019091529020805460ff1916905587612290600189612d11565b815481106122a0576122a0612c80565b9060005260206000200160009054906101000a90046001600160a01b03168886815481106122d0576122d0612c80565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508780548061230e5761230e612d24565b600082815260209020810160001990810180546001600160a01b03191690550190558661233a81612cd8565b975050505050506121da565b6123508286612cac565b94508361235c81612cbf565b9450505050506121da565b50601080546000908152600f602052604081208181556001810182905560020180546001600160a01b0319169055600a81905560148190556015805460ff191690556011548254909291906123bb90612cbf565b918290555011156123cc5760006010555b6000805260016020527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49546001600160a01b03166040516340c10f1960e01b8152306004820152602481018390526001600160a01b0391909116906340c10f1990604401600060405180830381600087803b15801561244a57600080fd5b505af115801561245e573d6000803e3d6000fd5b505060408051848152602081018890526001600160a01b038a1693507f291e8ba3c0f4b0bd86e6e2346fcee1e7ca0975b1cc1886bfbc722d34f3f24d9192500160405180910390a26001985050505050505050915091565b60006124c0611c61565b6011549091506000805b85518110156126455760008682815181106124e7576124e7612c80565b6020908102919091018101516001600160a01b0381166000908152601690925260408220600181015481549294509092909190811580159061252f5750898061252f57508289115b90508061254f5788831461254557600184018990555b5050505050612633565b6040518060600160405280838152602001428152602001866001600160a01b0316815250600f60008a61258190612cbf565b80825260208083019390935260409182016000208451815584840151600182015593820151600290940180546001600160a01b0319166001600160a01b039586161790559051858152909a50918716917f5f5b850fcbd0c09e2b8624b44902a5be89312011ae945e14bc73514fb719891e910160405180910390a2600084556001840189905561261087612cbf565b96508660011480156126225750601054155b1561262d5760108890555b50505050505b8061263d81612cbf565b9150506124ca565b5080156126525760118290555b5050505050565b6015546000908190839060ff16156126795760085460019250925061277d565b6001600160a01b0385166000908152600b60205260409020805460145480156126a25760085495505b805b8281101561275c57846000036126c85760145550505060088390556000915061277d565b6126d185612cd8565b94506000600760008684815481106126eb576126eb612c80565b60009182526020808320909101546001600160a01b03908116845283820194909452604092830182208054948f16835260038101909152919020549092508082106127365780612738565b815b9050612744818b612cac565b9950505050808061275490612cbf565b9150506126a4565b5050506008849055506015805460ff19166001908117909155600060145591505b9250925092565b600080808085156127b957505085546001600160a01b0386166000908152600388016020526040902054818111156127b95750805b8486146127e857856127cb8683612d3a565b6127d59190612cef565b93506127e18482612d11565b92506127ec565b8093505b83156127ff576127fc8483612d11565b88555b50506001600160a01b03909416600090815260039095016020526040909420839055509192909150565b6001600160a01b0380851660009081526007602090815260408083208054948816845260038101909252822054919280831115612864578092505b84158061286f575082155b1561289d57506001600160a01b038616600090815260039091016020526040812081905591508190506128cf565b846128a88488612d3a565b6128b29190612cef565b93508382600101546128c49190612cac565b826001018190555050505b94509492505050565b6001600160a01b0381168114610ce657600080fd5b6000602082840312156128ff57600080fd5b813561290a816128d8565b9392505050565b6000806040838503121561292457600080fd5b823561292f816128d8565b946020939093013593505050565b60006020828403121561294f57600080fd5b5035919050565b6000806040838503121561296957600080fd5b8235612974816128d8565b91506020830135612984816128d8565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b818110156129d05783516001600160a01b0316835292840192918401916001016129ab565b50909695505050505050565b60008083601f8401126129ee57600080fd5b50813567ffffffffffffffff811115612a0657600080fd5b6020830191508360208260051b8501011115612a2157600080fd5b9250929050565b600080600080600060608688031215612a4057600080fd5b853567ffffffffffffffff80821115612a5857600080fd5b612a6489838a016129dc565b90975095506020880135915080821115612a7d57600080fd5b50612a8a888289016129dc565b96999598509660400135949350505050565b60008060408385031215612aaf57600080fd5b82356001600160c01b03198116811461292f57600080fd5b600080600080600060608688031215612adf57600080fd5b85359450602086013567ffffffffffffffff80821115612afe57600080fd5b612b0a89838a016129dc565b90965094506040880135915080821115612b2357600080fd5b50612b30888289016129dc565b969995985093965092949392505050565b60008060208385031215612b5457600080fd5b823567ffffffffffffffff811115612b6b57600080fd5b612b77858286016129dc565b90969095509350505050565b600080600080600060a08688031215612b9b57600080fd5b8535612ba6816128d8565b97602087013597506040870135966060810135965060800135945092505050565b600060208284031215612bd957600080fd5b815161290a816128d8565b600060208284031215612bf657600080fd5b8151801515811461290a57600080fd5b60208082526010908201526f14de5cdd195b481a5cc81c185d5cd95960821b604082015260600190565b60208082526030908201527f556e61626c6520746f206578656375746520726571756573742077697468207560408201526f6e70726f636573736564206275726e7360801b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610d1457610d14612c96565b600060018201612cd157612cd1612c96565b5060010190565b600081612ce757612ce7612c96565b506000190190565b600082612d0c57634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115610d1457610d14612c96565b634e487b7160e01b600052603160045260246000fd5b8082028115828204841417610d1457610d14612c9656fe7e7fa33969761a458e04f477e039a608702b4f924981d6653935a8319a08ad7fa2646970667358221220cc6e077809878a904606c779af7c0da2558936f337024eb085614b521e6fbba864736f6c63430008120033000000000000000000000000ecef1e050432c9304b23b3226659bf8981cf83a2
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103835760003560e01c80639168ae72116101de578063e3bc92c01161010f578063f0f923c0116100ad578063f6ceefa21161007c578063f6ceefa21461089a578063f87975af146108ad578063f92ad219146108f7578063ff551c841461090a57600080fd5b8063f0f923c01461053a578063f2078db514610846578063f301af4214610859578063f52790bc1461089157600080fd5b8063eae01718116100e9578063eae01718146107e4578063eb962360146107f7578063ee97f7f314610820578063ef30375d1461083357600080fd5b8063e3bc92c014610734578063e7d931e4146107b0578063ead4d174146107d757600080fd5b8063afd369fd1161017c578063c65cfd5211610156578063c65cfd52146106fc578063cb1c2b5c14610705578063d46655f41461070e578063d6b5b8521461072157600080fd5b8063afd369fd146106c8578063b86e321c146106db578063c001472e146106ee57600080fd5b80639dd86e0f116101b85780639dd86e0f1461065c578063a4cc380b1461066f578063a81d80101461068b578063abb215be146106b557600080fd5b80639168ae72146106235780639abbed051461064a5780639c6f6e841461065357600080fd5b806339ac5eb9116102b857806373f273fc1161025657806376552b341161023057806376552b34146105d057806385b39d83146105e35780638e91e6bd1461060c578063908ad10a1461061a57600080fd5b806373f273fc1461056057806374ff6b901461059c57806375a7720f146105a457600080fd5b806365f212f91161029257806365f212f91461052757806368989a591461053a5780637272135a1461054d57806372af29321461055757600080fd5b806339ac5eb91461049f57806344df8e70146104c85780635840ee441461050757600080fd5b80631a839ba711610325578063285ece4e116102ff578063285ece4e146104675780632e1a7d4d146104705780632e23dc8f1461048357806334892cea1461048c57600080fd5b80631a839ba71461043e57806322b1c2961461045657806324f412541461045e57600080fd5b80630ea9c984116103615780630ea9c9841461040f5780631354839d1461041957806315c5673c1461042c5780631694a36a1461043557600080fd5b80630ca6de03146103885780630ce71e32146103a45780630ea474c7146103e3575b600080fd5b61039160055481565b6040519081526020015b60405180910390f35b6103cb7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161039b565b6103916103f13660046128ed565b6001600160a01b031660009081526007602052604090206001015490565b61041761091d565b005b6103cb610427366004612911565b610a84565b61039160145481565b61039160185481565b610446610abc565b604051901515815260200161039b565b610446610aff565b61039160045481565b61039160175481565b61041761047e36600461293d565b610b40565b61039160105481565b61039161049a366004612956565b610ce9565b6103916104ad3660046128ed565b6001600160a01b031660009081526007602052604090205490565b600c54600d54600e546104e39291906001600160a01b031683565b6040805193845260208401929092526001600160a01b03169082015260600161039b565b61051a6105153660046128ed565b610d1a565b60405161039b919061298f565b6103916105353660046128ed565b610d93565b610417610548366004612911565b610e4a565b600d541515610446565b61039160135481565b61058761056e3660046128ed565b6016602052600090815260409020805460019091015482565b6040805192835260208301919091520161039b565b610391610e82565b6103916105b23660046128ed565b6001600160a01b031660009081526007602052604090206002015490565b6104176105de3660046128ed565b610e8c565b6103916105f13660046128ed565b6001600160a01b03166000908152600b602052604090205490565b610417610548366004612a28565b61039160065481565b6105876106313660046128ed565b6007602052600090815260409020805460019091015482565b610391600a5481565b61039160095481565b61041761066a366004612a9c565b611029565b6010546000908152600f60205260409020600101541515610446565b61069e61069936600461293d565b611178565b60408051921515835260208301919091520161039b565b61069e6106c336600461293d565b6113dc565b6103916106d63660046128ed565b61147d565b6104176106e93660046128ed565b611563565b610417610548366004612ac7565b61039160085481565b61039160035481565b61041761071c3660046128ed565b6116e9565b6103cb61072f366004612911565b611763565b61077c61074236600461293d565b60009081526012602052604090208054600182015460028301546003840154600490940154929491936001600160a01b0391821693911691565b6040805195865260208601949094526001600160a01b0392831693850193909352166060830152608082015260a00161039b565b6103cb7f000000000000000000000000000000000000000000000000000000000000000081565b6015546104469060ff1681565b6103916107f2366004612956565b6117a9565b6103cb61080536600461293d565b6001602052600090815260409020546001600160a01b031681565b6000546103cb906001600160a01b031681565b6103cb610841366004612911565b6117f1565b61051a6108543660046128ed565b61181e565b6104e361086736600461293d565b600f602052600090815260409020805460018201546002909201549091906001600160a01b031683565b61039160115481565b6104176108a8366004612b41565b611892565b61077c6108bb36600461293d565b60126020526000908152604090208054600182015460028301546003840154600490940154929391926001600160a01b03918216929091169085565b610417610905366004612b83565b611963565b61044661091836600461293d565b611a18565b6000546040516227050b60e31b815261544360f01b60048201526001600160a01b0390911690630138285890602401602060405180830381865afa158015610969573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098d9190612bc7565b600080805260016020527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4980546001600160a01b039384166001600160a01b0319909116179055546040516227050b60e31b81526126a960f11b6004820152911690630138285890602401602060405180830381865afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a399190612bc7565b600260005260016020527fd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f80546001600160a01b0319166001600160a01b0392909216919091179055565b600b6020528160005260406000208181548110610aa057600080fd5b6000918252602090912001546001600160a01b03169150829050565b60008080526012602052600080516020612d5283398151915254808203610ae557600091505090565b600090815260126020526040902060010154421015919050565b6000610b0c600d54151590565b80610b1a5750610b1a610abc565b80610b3b5750506010546000908152600f6020526040902060010154151590565b905090565b60008054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb59190612be4565b15610bdb5760405162461bcd60e51b8152600401610bd290612c06565b60405180910390fd5b6002600081905260016020527fd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f5460405163505ef22f60e01b815233600482015260248101929092526001600160a01b03169063505ef22f90604401602060405180830381865afa158015610c54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c789190612be4565b610cbd5760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba10309036b2b6b132b960511b6044820152606401610bd2565b600d5415610cdd5760405162461bcd60e51b8152600401610bd290612c30565b610ce633611abd565b50565b6001600160a01b03808316600090815260076020908152604080832093851683526004909301905220545b92915050565b6001600160a01b038116600090815260076020908152604091829020600201805483518184028101840190945280845260609392830182828015610d8757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610d69575b50505050509050919050565b6001600160a01b0381166000908152600b60205260408120805482805b82811015610e4157600060076000868481548110610dd057610dd0612c80565b60009182526020808320909101546001600160a01b03908116845283820194909452604092830182208054948c1683526003810190915291902054909250808210610e1b5780610e1d565b815b9050610e298186612cac565b94505050508080610e3990612cbf565b915050610db0565b50949350505050565b60405162461bcd60e51b815260206004820152600d60248201526c26b4b3b930ba32903a37903b1960991b6044820152606401610bd2565b6000610b3b611c61565b60008054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610edd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f019190612be4565b15610f1e5760405162461bcd60e51b8152600401610bd290612c06565b6002600081905260016020527fd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f5460405163505ef22f60e01b815233600482015260248101929092526001600160a01b03169063505ef22f90604401602060405180830381865afa158015610f97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fbb9190612be4565b6110005760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba10309036b2b6b132b960511b6044820152606401610bd2565b600d54156110205760405162461bcd60e51b8152600401610bd290612c30565b610ce681611abd565b600054604051632c1a733d60e11b81523360048201526001600160a01b0390911690635834e67a90602401602060405180830381865afa158015611071573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110959190612be4565b6110ec5760405162461bcd60e51b815260206004820152602260248201527f43616c6c6572206973206e6f7420617574686f72697a656420746f20676f7665604482015261393760f11b6064820152608401610bd2565b6001600160c01b03198216674d494e5f5354414b60c01b0361110e5760035550565b6001600160c01b03198216674d41585f4558504f60c01b036111305760045550565b6001600160c01b031982166713525397d55394d560c21b036111525760055550565b6001600160c01b0319821667155394d517d312d560c21b036111745760068190555b5050565b6000805460408051600162f6c75960e01b03198152905183926001600160a01b03169163ff0938a79160048083019260209291908290030181865afa1580156111c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e99190612be4565b156112065760405162461bcd60e51b8152600401610bd290612c06565b50815b60126020908152600080516020612d5283398151915254600081815260408082206010548352600f9094528120600d5460018083015490860154949594929391929091861580159061125b5750428211155b601054909150841580159115159082611272575082155b801561127c575080155b1561128f5750505050505050505061139f565b8180156112a357508215806112a357508386105b80156112b657508015806112b657508486105b15611323576112c48a611cf5565b909b5099508a61131557604051600081527ff3b343b97db20514b20b9c54105a005716230e231e9bf5d180b1a0dfe6e4fb8a906020015b60405180910390a160009a50505050505050505050915091565b505050505050505050611209565b828015611337575080158061133757508484105b15611396578960000361137557604051600081527ff3b343b97db20514b20b9c54105a005716230e231e9bf5d180b1a0dfe6e4fb8a906020016112fb565b61137d611ff4565b6113868a612cd8565b9950505050505050505050611209565b6112c48a612170565b604051600181527ff3b343b97db20514b20b9c54105a005716230e231e9bf5d180b1a0dfe6e4fb8a9060200160405180910390a160019150915091565b6000805460408051600162f6c75960e01b03198152905183926001600160a01b03169163ff0938a79160048083019260209291908290030181865afa158015611429573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144d9190612be4565b1561146a5760405162461bcd60e51b8152600401610bd290612c06565b61147383611178565b9094909350915050565b6001600160a01b038116600090815260076020526040812080548280805b60028501548110156115275760008560020182815481106114be576114be612c80565b60009182526020808320909101546001600160a01b0316808352600389019091526040822054909250908187106114f557816114f7565b865b90506115038187612cac565b955084811115611511578094505b505050808061151f90612cbf565b91505061149b565b506000600454836115389190612cef565b90506000818311611549578161154b565b825b90506115578186612d11565b98975050505050505050565b60008054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d89190612be4565b156115f55760405162461bcd60e51b8152600401610bd290612c06565b6001600160a01b0381811660008181526007602052604080822060010180549290555163a9059cbb60e01b8152600481019290925260248201819052917f000000000000000000000000ecef1e050432c9304b23b3226659bf8981cf83a2169063a9059cbb906044016020604051808303816000875af115801561167d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a19190612be4565b50816001600160a01b03167f1d3eee4ca001cff39eec6ec7615aacf2f2bd61791273830728ba00ccbd6e1337826040516116dd91815260200190565b60405180910390a25050565b6000546001600160a01b031615611741576000546001600160a01b031633146117415760405162461bcd60e51b815260206004820152600a6024820152692737ba1036b0b9ba32b960b11b6044820152606401610bd2565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0382166000908152600b6020526040812080548390811061178d5761178d612c80565b6000918252602090912001546001600160a01b03169392505050565b6001600160a01b03808316600081815260076020818152604080842095871684526003860182528320549383525291548082106117e657806117e8565b815b95945050505050565b6001600160a01b038216600090815260076020526040812060020180548390811061178d5761178d612c80565b6001600160a01b0381166000908152600b6020908152604091829020805483518184028101840190945280845260609392830182828015610d87576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610d695750505050509050919050565b60008054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119079190612be4565b156119245760405162461bcd60e51b8152600401610bd290612c06565b611174828280806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250600192506124b6915050565b6000805260016020527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4980546001600160a01b0387166001600160a01b0319909116811790915560405163e43252d760e01b815230600482015263e43252d790602401600060405180830381600087803b1580156119e057600080fd5b505af11580156119f4573d6000803e3d6000fd5b505050600394909455600592909255600455600655505062093a8060175542601855565b60008060009054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a909190612be4565b15611aad5760405162461bcd60e51b8152600401610bd290612c06565b611ab682611178565b5092915050565b6001600160a01b038116731337def1fc06783d4b03cb8c1bf3ebf7d0593fc414801590611b0757506001600160a01b0381167387b2a7559d85f4653f13e6546a14189cd5455d4514155b8015611b3057506001600160a01b03811673963df0066ff8345922df88eebeb1095be4e4e12e14155b611b7c5760405162461bcd60e51b815260206004820152601760248201527f4e6f7420616c6c6f77656420746f2077697468647261770000000000000000006044820152606401610bd2565b6001600160a01b0381811660008181526007602052604080822080549290555163a9059cbb60e01b8152600481019290925260248201819052917f000000000000000000000000ecef1e050432c9304b23b3226659bf8981cf83a2169063a9059cbb906044016020604051808303816000875af1158015611c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c259190612be4565b50816001600160a01b03167f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5826040516116dd91815260200190565b60175460185460009190808303611cc95760405162461bcd60e51b815260206004820152602660248201527f5245574152445f524f554e44535f5354415254206973206e6f7420696e697469604482015265185b1a5e995960d21b6064820152608401610bd2565b80421115611ceb5781611cdc8242612d11565b611ce69190612cef565b611cee565b60005b9250505090565b600e5460009082906001600160a01b031682611d118284612659565b9095509350905083611d2857600093505050915091565b6001600160a01b0382166000908152600b602052604090208054600c5460095484821115611d54578491505b6014545b83811015611ee65787600003611d81576009919091556014555060009794965093945050505050565b611d8a88612cd8565b9750600060076000878481548110611da457611da4612c80565b60009182526020808320909101546001600160a01b031683528201929092526040018120915080611dd7838b8b89612784565b9092509050611de68286612cac565b94508015611e035783611df881612cbf565b945050505050611d58565b6001600160a01b038a1660009081526005840160205260409020805460ff1916905587611e31600189612d11565b81548110611e4157611e41612c80565b9060005260206000200160009054906101000a90046001600160a01b0316888581548110611e7157611e71612c80565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555087805480611eaf57611eaf612d24565b600082815260209020810160001990810180546001600160a01b031916905501905586611edb81612cd8565b975050505050611d58565b506000600c819055600d819055600e80546001600160a01b031916905560098190556014556015805460ff19169055604051630852cd8d60e31b8152600481018290526001600160a01b037f000000000000000000000000ecef1e050432c9304b23b3226659bf8981cf83a216906342966c68906024016020604051808303816000875af1158015611f7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa09190612be4565b5060408051828152602081018790526001600160a01b038816917f23ff0e75edf108e3d0392d92e13e8c8a868ef19001bd49f9e94876dc46dff87f910160405180910390a260019750505050505050915091565b60126020908152600080516020612d5283398151915254600081815260408082206003808201546001600160a01b039081168086526007885284862060028501548154931680885293810190985293852054959692959394929391929091908183106120605781612062565b825b875490915060008183106120765781612078565b825b90506120848184612d11565b6001600160a01b038716600090815260038901602090815260408083209390935560048a01905220546120b78382612d11565b6001600160a01b0380891660008181526004808d0160209081526040808420969096558f8201546012909152600080516020612d52833981519152558f8252848220828155600181018390556002810180546001600160a01b0319908116909155600382018054909116905501559151908b1691907fd8654fcc8cf5b36d30b3f5e4688fc78118e6d68de60b9994e09902268b57c3e39061215b9087815260200190565b60405180910390a35050505050505050505050565b6010546000908152600f60205260408120600281015481548492916001600160a01b031690846121a08386612659565b90975095509050856121b9576000955050505050915091565b6001600160a01b0383166000908152600b602052604090208054600a546014545b82811015612367578860000361220457600a91909155601455506000989597509495505050505050565b61220d89612cd8565b9850600084828154811061222357612223612c80565b60009182526020822001546001600160a01b0316915080612246838b8b8b612829565b9150915080600003612346576001600160a01b038084166000908152600760209081526040808320938e168352600584019091529020805460ff1916905587612290600189612d11565b815481106122a0576122a0612c80565b9060005260206000200160009054906101000a90046001600160a01b03168886815481106122d0576122d0612c80565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508780548061230e5761230e612d24565b600082815260209020810160001990810180546001600160a01b03191690550190558661233a81612cd8565b975050505050506121da565b6123508286612cac565b94508361235c81612cbf565b9450505050506121da565b50601080546000908152600f602052604081208181556001810182905560020180546001600160a01b0319169055600a81905560148190556015805460ff191690556011548254909291906123bb90612cbf565b918290555011156123cc5760006010555b6000805260016020527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49546001600160a01b03166040516340c10f1960e01b8152306004820152602481018390526001600160a01b0391909116906340c10f1990604401600060405180830381600087803b15801561244a57600080fd5b505af115801561245e573d6000803e3d6000fd5b505060408051848152602081018890526001600160a01b038a1693507f291e8ba3c0f4b0bd86e6e2346fcee1e7ca0975b1cc1886bfbc722d34f3f24d9192500160405180910390a26001985050505050505050915091565b60006124c0611c61565b6011549091506000805b85518110156126455760008682815181106124e7576124e7612c80565b6020908102919091018101516001600160a01b0381166000908152601690925260408220600181015481549294509092909190811580159061252f5750898061252f57508289115b90508061254f5788831461254557600184018990555b5050505050612633565b6040518060600160405280838152602001428152602001866001600160a01b0316815250600f60008a61258190612cbf565b80825260208083019390935260409182016000208451815584840151600182015593820151600290940180546001600160a01b0319166001600160a01b039586161790559051858152909a50918716917f5f5b850fcbd0c09e2b8624b44902a5be89312011ae945e14bc73514fb719891e910160405180910390a2600084556001840189905561261087612cbf565b96508660011480156126225750601054155b1561262d5760108890555b50505050505b8061263d81612cbf565b9150506124ca565b5080156126525760118290555b5050505050565b6015546000908190839060ff16156126795760085460019250925061277d565b6001600160a01b0385166000908152600b60205260409020805460145480156126a25760085495505b805b8281101561275c57846000036126c85760145550505060088390556000915061277d565b6126d185612cd8565b94506000600760008684815481106126eb576126eb612c80565b60009182526020808320909101546001600160a01b03908116845283820194909452604092830182208054948f16835260038101909152919020549092508082106127365780612738565b815b9050612744818b612cac565b9950505050808061275490612cbf565b9150506126a4565b5050506008849055506015805460ff19166001908117909155600060145591505b9250925092565b600080808085156127b957505085546001600160a01b0386166000908152600388016020526040902054818111156127b95750805b8486146127e857856127cb8683612d3a565b6127d59190612cef565b93506127e18482612d11565b92506127ec565b8093505b83156127ff576127fc8483612d11565b88555b50506001600160a01b03909416600090815260039095016020526040909420839055509192909150565b6001600160a01b0380851660009081526007602090815260408083208054948816845260038101909252822054919280831115612864578092505b84158061286f575082155b1561289d57506001600160a01b038616600090815260039091016020526040812081905591508190506128cf565b846128a88488612d3a565b6128b29190612cef565b93508382600101546128c49190612cac565b826001018190555050505b94509492505050565b6001600160a01b0381168114610ce657600080fd5b6000602082840312156128ff57600080fd5b813561290a816128d8565b9392505050565b6000806040838503121561292457600080fd5b823561292f816128d8565b946020939093013593505050565b60006020828403121561294f57600080fd5b5035919050565b6000806040838503121561296957600080fd5b8235612974816128d8565b91506020830135612984816128d8565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b818110156129d05783516001600160a01b0316835292840192918401916001016129ab565b50909695505050505050565b60008083601f8401126129ee57600080fd5b50813567ffffffffffffffff811115612a0657600080fd5b6020830191508360208260051b8501011115612a2157600080fd5b9250929050565b600080600080600060608688031215612a4057600080fd5b853567ffffffffffffffff80821115612a5857600080fd5b612a6489838a016129dc565b90975095506020880135915080821115612a7d57600080fd5b50612a8a888289016129dc565b96999598509660400135949350505050565b60008060408385031215612aaf57600080fd5b82356001600160c01b03198116811461292f57600080fd5b600080600080600060608688031215612adf57600080fd5b85359450602086013567ffffffffffffffff80821115612afe57600080fd5b612b0a89838a016129dc565b90965094506040880135915080821115612b2357600080fd5b50612b30888289016129dc565b969995985093965092949392505050565b60008060208385031215612b5457600080fd5b823567ffffffffffffffff811115612b6b57600080fd5b612b77858286016129dc565b90969095509350505050565b600080600080600060a08688031215612b9b57600080fd5b8535612ba6816128d8565b97602087013597506040870135966060810135965060800135945092505050565b600060208284031215612bd957600080fd5b815161290a816128d8565b600060208284031215612bf657600080fd5b8151801515811461290a57600080fd5b60208082526010908201526f14de5cdd195b481a5cc81c185d5cd95960821b604082015260600190565b60208082526030908201527f556e61626c6520746f206578656375746520726571756573742077697468207560408201526f6e70726f636573736564206275726e7360801b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610d1457610d14612c96565b600060018201612cd157612cd1612c96565b5060010190565b600081612ce757612ce7612c96565b506000190190565b600082612d0c57634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115610d1457610d14612c96565b634e487b7160e01b600052603160045260246000fd5b8082028115828204841417610d1457610d14612c9656fe7e7fa33969761a458e04f477e039a608702b4f924981d6653935a8319a08ad7fa2646970667358221220cc6e077809878a904606c779af7c0da2558936f337024eb085614b521e6fbba864736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ecef1e050432c9304b23b3226659bf8981cf83a2
-----Decoded View---------------
Arg [0] : _tokenAddress (address): 0xeceF1e050432c9304B23b3226659bF8981Cf83a2
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000ecef1e050432c9304b23b3226659bf8981cf83a2
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.