Source Code
Latest 23 from a total of 23 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Set Reward Ratio | 16598195 | 194 days ago | IN | 0 ETH | 0.00000014 | ||||
| Set Reward Ratio | 16248839 | 202 days ago | IN | 0 ETH | 0.00000016 | ||||
| Set Reward Ratio | 15863955 | 211 days ago | IN | 0 ETH | 0.00000011 | ||||
| Claim Rewards | 15839559 | 212 days ago | IN | 0 ETH | 0.00000015 | ||||
| Stake | 15839275 | 212 days ago | IN | 0 ETH | 0.00000016 | ||||
| Set Reward Ratio | 15394900 | 222 days ago | IN | 0 ETH | 0.00000011 | ||||
| Set Reward Ratio | 13918238 | 256 days ago | IN | 0 ETH | 0.00000016 | ||||
| Set Reward Ratio | 13841924 | 258 days ago | IN | 0 ETH | 0.00000012 | ||||
| Set Reward Ratio | 13749789 | 260 days ago | IN | 0 ETH | 0.00000011 | ||||
| Set Reward Ratio | 13717742 | 261 days ago | IN | 0 ETH | 0.00000014 | ||||
| Set Reward Ratio | 13706834 | 261 days ago | IN | 0 ETH | 0.00000015 | ||||
| Withdraw Reward ... | 11168565 | 320 days ago | IN | 0 ETH | 0.00000013 | ||||
| Set Reward Ratio | 11167378 | 320 days ago | IN | 0 ETH | 0.00000019 | ||||
| Set Reward Ratio | 11113843 | 321 days ago | IN | 0 ETH | 0.00000012 | ||||
| Set Reward Ratio | 11076454 | 322 days ago | IN | 0 ETH | 0.00000011 | ||||
| Set Reward Ratio | 11057458 | 322 days ago | IN | 0 ETH | 0.00000012 | ||||
| Set Reward Ratio | 11034657 | 323 days ago | IN | 0 ETH | 0.00000013 | ||||
| Set Reward Ratio | 11014813 | 323 days ago | IN | 0 ETH | 0.00000082 | ||||
| Set Reward Ratio | 10992678 | 324 days ago | IN | 0 ETH | 0.00000011 | ||||
| Set Reward Ratio | 10970969 | 324 days ago | IN | 0 ETH | 0.00000032 | ||||
| Set Reward Ratio | 10947538 | 325 days ago | IN | 0 ETH | 0.00000011 | ||||
| Stake | 10193717 | 342 days ago | IN | 0 ETH | 0.00000032 | ||||
| Deposit Reward T... | 10172576 | 343 days ago | IN | 0 ETH | 0.0000001 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0xf17B4017...bFf618dBE The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
Staking20Base
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 20 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
import "../extension/ContractMetadata.sol";
import "../extension/Multicall.sol";
import "../extension/Ownable.sol";
import "../extension/Staking20.sol";
import "../eip/interface/IERC20.sol";
import "../eip/interface/IERC20Metadata.sol";
import { CurrencyTransferLib } from "../lib/CurrencyTransferLib.sol";
/**
*
* EXTENSION: Staking20
*
* The `Staking20Base` smart contract implements Token staking mechanism.
* Allows users to stake their ERC-20 Tokens and earn rewards in form of another ERC-20 tokens.
*
* Following features and implementation setup must be noted:
*
* - ERC-20 Tokens from only one contract can be staked.
*
* - Contract admin can choose to give out rewards by either transferring or minting the rewardToken,
* which is ideally a different ERC20 token. See {_mintRewards}.
*
* - To implement custom logic for staking, reward calculation, etc. corresponding functions can be
* overridden from the extension `Staking20`.
*
* - Ownership of the contract, with the ability to restrict certain functions to
* only be called by the contract's owner.
*
* - Multicall capability to perform multiple actions atomically.
*
*/
/// note: This contract is provided as a base contract.
// This is to support a variety of use-cases that can be build on top of this base.
//
// Additional functionality such as deposit functions, reward-minting, etc.
// must be implemented by the deployer of this contract, as needed for their use-case.
contract Staking20Base is ContractMetadata, Multicall, Ownable, Staking20 {
/// @dev ERC20 Reward Token address. See {_mintRewards} below.
address public immutable rewardToken;
/// @dev Total amount of reward tokens in the contract.
uint256 private rewardTokenBalance;
constructor(
uint80 _timeUnit,
address _defaultAdmin,
uint256 _rewardRatioNumerator,
uint256 _rewardRatioDenominator,
address _stakingToken,
address _rewardToken,
address _nativeTokenWrapper
)
Staking20(
_nativeTokenWrapper,
_stakingToken,
IERC20Metadata(_stakingToken).decimals(),
IERC20Metadata(_rewardToken).decimals()
)
{
_setupOwner(_defaultAdmin);
_setStakingCondition(_timeUnit, _rewardRatioNumerator, _rewardRatioDenominator);
require(_rewardToken != _stakingToken, "Reward Token and Staking Token can't be same.");
rewardToken = _rewardToken;
}
/// @dev Lets the contract receive ether to unwrap native tokens.
receive() external payable virtual {
require(msg.sender == nativeTokenWrapper, "caller not native token wrapper.");
}
/// @dev Admin deposits reward tokens.
function depositRewardTokens(uint256 _amount) external payable virtual nonReentrant {
_depositRewardTokens(_amount); // override this for custom logic.
}
/// @dev Admin can withdraw excess reward tokens.
function withdrawRewardTokens(uint256 _amount) external virtual nonReentrant {
_withdrawRewardTokens(_amount); // override this for custom logic.
}
/// @notice View total rewards available in the staking contract.
function getRewardTokenBalance() external view virtual override returns (uint256) {
return rewardTokenBalance;
}
/*//////////////////////////////////////////////////////////////
Minting logic
//////////////////////////////////////////////////////////////*/
/**
* @dev Mint ERC20 rewards to the staker. Override for custom logic.
*
* @param _staker Address for which to calculated rewards.
* @param _rewards Amount of tokens to be given out as reward.
*
*/
function _mintRewards(address _staker, uint256 _rewards) internal virtual override {
require(_rewards <= rewardTokenBalance, "Not enough reward tokens");
rewardTokenBalance -= _rewards;
CurrencyTransferLib.transferCurrencyWithWrapper(
rewardToken,
address(this),
_staker,
_rewards,
nativeTokenWrapper
);
}
/*//////////////////////////////////////////////////////////////
Other Internal functions
//////////////////////////////////////////////////////////////*/
/// @dev Admin deposits reward tokens -- override for custom logic.
function _depositRewardTokens(uint256 _amount) internal virtual {
require(msg.sender == owner(), "Not authorized");
address _rewardToken = rewardToken == CurrencyTransferLib.NATIVE_TOKEN ? nativeTokenWrapper : rewardToken;
uint256 balanceBefore = IERC20(_rewardToken).balanceOf(address(this));
CurrencyTransferLib.transferCurrencyWithWrapper(
rewardToken,
msg.sender,
address(this),
_amount,
nativeTokenWrapper
);
uint256 actualAmount = IERC20(_rewardToken).balanceOf(address(this)) - balanceBefore;
rewardTokenBalance += actualAmount;
}
/// @dev Admin can withdraw excess reward tokens -- override for custom logic.
function _withdrawRewardTokens(uint256 _amount) internal virtual {
require(msg.sender == owner(), "Not authorized");
// to prevent locking of direct-transferred tokens
rewardTokenBalance = _amount > rewardTokenBalance ? 0 : rewardTokenBalance - _amount;
CurrencyTransferLib.transferCurrencyWithWrapper(
rewardToken,
address(this),
msg.sender,
_amount,
nativeTokenWrapper
);
// The withdrawal shouldn't reduce staking token balance. `>=` accounts for any accidental transfers.
address _stakingToken = stakingToken == CurrencyTransferLib.NATIVE_TOKEN ? nativeTokenWrapper : stakingToken;
require(
IERC20(_stakingToken).balanceOf(address(this)) >= stakingTokenBalance,
"Staking token balance reduced."
);
}
/// @dev Returns whether staking restrictions can be set in given execution context.
function _canSetStakeConditions() internal view virtual override returns (bool) {
return msg.sender == owner();
}
/// @dev Returns whether contract metadata can be set in the given execution context.
function _canSetContractURI() internal view virtual override returns (bool) {
return msg.sender == owner();
}
/// @dev Returns whether owner can be set in the given execution context.
function _canSetOwner() internal view virtual override returns (bool) {
return msg.sender == owner();
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
import "./interface/IContractMetadata.sol";
/**
* @title Contract Metadata
* @notice Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI
* for you contract.
* Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea.
*/
abstract contract ContractMetadata is IContractMetadata {
/// @dev The sender is not authorized to perform the action
error ContractMetadataUnauthorized();
/// @notice Returns the contract metadata URI.
string public override contractURI;
/**
* @notice Lets a contract admin set the URI for contract-level metadata.
* @dev Caller should be authorized to setup contractURI, e.g. contract admin.
* See {_canSetContractURI}.
* Emits {ContractURIUpdated Event}.
*
* @param _uri keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
*/
function setContractURI(string memory _uri) external override {
if (!_canSetContractURI()) {
revert ContractMetadataUnauthorized();
}
_setupContractURI(_uri);
}
/// @dev Lets a contract admin set the URI for contract-level metadata.
function _setupContractURI(string memory _uri) internal {
string memory prevURI = contractURI;
contractURI = _uri;
emit ContractURIUpdated(prevURI, _uri);
}
/// @dev Returns whether contract metadata can be set in the given execution context.
function _canSetContractURI() internal view virtual returns (bool);
}// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.0;
/// @author thirdweb
import "../lib/Address.sol";
import "./interface/IMulticall.sol";
/**
* @dev Provides a function to batch together multiple calls in a single external call.
*
* _Available since v4.1._
*/
contract Multicall is IMulticall {
/**
* @notice Receives and executes a batch of function calls on this contract.
* @dev Receives and executes a batch of function calls on this contract.
*
* @param data The bytes data that makes up the batch of function calls to execute.
* @return results The bytes data that makes up the result of the batch of function calls executed.
*/
function multicall(bytes[] calldata data) external returns (bytes[] memory results) {
results = new bytes[](data.length);
address sender = _msgSender();
bool isForwarder = msg.sender != sender;
for (uint256 i = 0; i < data.length; i++) {
if (isForwarder) {
results[i] = Address.functionDelegateCall(address(this), abi.encodePacked(data[i], sender));
} else {
results[i] = Address.functionDelegateCall(address(this), data[i]);
}
}
return results;
}
/// @notice Returns the sender in the given execution context.
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
import "./interface/IOwnable.sol";
/**
* @title Ownable
* @notice Thirdweb's `Ownable` is a contract extension to be used with any base contract. It exposes functions for setting and reading
* who the 'owner' of the inheriting smart contract is, and lets the inheriting contract perform conditional logic that uses
* information about who the contract's owner is.
*/
abstract contract Ownable is IOwnable {
/// @dev The sender is not authorized to perform the action
error OwnableUnauthorized();
/// @dev Owner of the contract (purpose: OpenSea compatibility)
address private _owner;
/// @dev Reverts if caller is not the owner.
modifier onlyOwner() {
if (msg.sender != _owner) {
revert OwnableUnauthorized();
}
_;
}
/**
* @notice Returns the owner of the contract.
*/
function owner() public view override returns (address) {
return _owner;
}
/**
* @notice Lets an authorized wallet set a new owner for the contract.
* @param _newOwner The address to set as the new owner of the contract.
*/
function setOwner(address _newOwner) external override {
if (!_canSetOwner()) {
revert OwnableUnauthorized();
}
_setupOwner(_newOwner);
}
/// @dev Lets a contract admin set a new owner for the contract. The new owner must be a contract admin.
function _setupOwner(address _newOwner) internal {
address _prevOwner = _owner;
_owner = _newOwner;
emit OwnerUpdated(_prevOwner, _newOwner);
}
/// @dev Returns whether owner can be set in the given execution context.
function _canSetOwner() internal view virtual returns (bool);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.11;
/// @author thirdweb
import "../external-deps/openzeppelin/security/ReentrancyGuard.sol";
import "../external-deps/openzeppelin/utils/math/SafeMath.sol";
import "../eip/interface/IERC20.sol";
import { CurrencyTransferLib } from "../lib/CurrencyTransferLib.sol";
import "./interface/IStaking20.sol";
abstract contract Staking20 is ReentrancyGuard, IStaking20 {
/*///////////////////////////////////////////////////////////////
State variables / Mappings
//////////////////////////////////////////////////////////////*/
/// @dev The address of the native token wrapper contract.
address internal immutable nativeTokenWrapper;
///@dev Address of ERC20 contract -- staked tokens belong to this contract.
address public immutable stakingToken;
/// @dev Decimals of staking token.
uint16 public immutable stakingTokenDecimals;
/// @dev Decimals of reward token.
uint16 public immutable rewardTokenDecimals;
///@dev Next staking condition Id. Tracks number of conditon updates so far.
uint64 private nextConditionId;
/// @dev Total amount of tokens staked in the contract.
uint256 public stakingTokenBalance;
/// @dev Mapping address to if they have staked.
mapping(address => bool) public hasStaked;
///@dev Mapping staker address to Staker struct. See {struct IStaking20.Staker}.
mapping(address => Staker) public stakers;
///@dev Mapping from condition Id to staking condition. See {struct IStaking721.StakingCondition}
mapping(uint256 => StakingCondition) private stakingConditions;
constructor(
address _nativeTokenWrapper,
address _stakingToken,
uint16 _stakingTokenDecimals,
uint16 _rewardTokenDecimals
) ReentrancyGuard() {
require(_stakingToken != address(0) && _nativeTokenWrapper != address(0), "address 0");
require(_stakingTokenDecimals != 0 && _rewardTokenDecimals != 0, "decimals 0");
nativeTokenWrapper = _nativeTokenWrapper;
stakingToken = _stakingToken;
stakingTokenDecimals = _stakingTokenDecimals;
rewardTokenDecimals = _rewardTokenDecimals;
}
/*///////////////////////////////////////////////////////////////
External/Public Functions
//////////////////////////////////////////////////////////////*/
/**
* @notice Stake ERC20 Tokens.
*
* @dev See {_stake}. Override that to implement custom logic.
*/
function stake() external nonReentrant {
require(!hasStaked[msg.sender], "Already staked");
_stake();
hasStaked[msg.sender] = true;
}
/**
* @notice Withdraw staked ERC20 tokens.
*
* @dev See {_withdraw}. Override that to implement custom logic.
*/
function withdraw() external nonReentrant {
require(hasStaked[msg.sender], "Not staked");
_withdraw();
hasStaked[msg.sender] = false;
}
/**
* @notice Claim accumulated rewards.
*
* @dev See {_claimRewards}. Override that to implement custom logic.
* See {_calculateRewards} for reward-calculation logic.
*/
function claimRewards() external nonReentrant {
_claimRewards();
}
/**
* @notice Set time unit. Set as a number of seconds.
* Could be specified as -- x * 1 hours, x * 1 days, etc.
*
* @dev Only admin/authorized-account can call it.
*
* @param _timeUnit New time unit.
*/
function setTimeUnit(uint80 _timeUnit) external virtual {
if (!_canSetStakeConditions()) {
revert("Not authorized");
}
StakingCondition memory condition = stakingConditions[nextConditionId - 1];
require(_timeUnit != condition.timeUnit, "Time-unit unchanged.");
_setStakingCondition(_timeUnit, condition.rewardRatioNumerator, condition.rewardRatioDenominator);
emit UpdatedTimeUnit(condition.timeUnit, _timeUnit);
}
/**
* @notice Set rewards per unit of time.
* Interpreted as (numerator/denominator) rewards per second/per day/etc based on time-unit.
*
* For e.g., ratio of 1/20 would mean 1 reward token for every 20 tokens staked.
*
* @dev Only admin/authorized-account can call it.
*
* @param _numerator Reward ratio numerator.
* @param _denominator Reward ratio denominator.
*/
function setRewardRatio(uint256 _numerator, uint256 _denominator) external virtual {
if (!_canSetStakeConditions()) {
revert("Not authorized");
}
StakingCondition memory condition = stakingConditions[nextConditionId - 1];
require(
_numerator != condition.rewardRatioNumerator || _denominator != condition.rewardRatioDenominator,
"Reward ratio unchanged."
);
_setStakingCondition(condition.timeUnit, _numerator, _denominator);
emit UpdatedRewardRatio(
condition.rewardRatioNumerator,
_numerator,
condition.rewardRatioDenominator,
_denominator
);
}
/**
* @notice View amount staked and rewards for a user.
*
* @param _staker Address for which to calculated rewards.
* @return _tokensStaked Amount of tokens staked.
* @return _rewards Available reward amount.
*/
function getStakeInfo(address _staker) external view virtual returns (uint256 _tokensStaked, uint256 _rewards) {
_tokensStaked = stakers[_staker].amountStaked;
_rewards = _availableRewards(_staker);
}
function getTimeUnit() public view returns (uint256 _timeUnit) {
_timeUnit = stakingConditions[nextConditionId - 1].timeUnit;
}
function getRewardRatio() public view returns (uint256 _numerator, uint256 _denominator) {
_numerator = stakingConditions[nextConditionId - 1].rewardRatioNumerator;
_denominator = stakingConditions[nextConditionId - 1].rewardRatioDenominator;
}
/*///////////////////////////////////////////////////////////////
Internal Functions
//////////////////////////////////////////////////////////////*/
/// @dev Staking logic. Override to add custom logic.
function _stake() internal virtual {
stakers[_stakeMsgSender()].timeOfLastUpdate = uint80(block.timestamp);
stakers[_stakeMsgSender()].conditionIdOflastUpdate = nextConditionId - 1;
stakers[_stakeMsgSender()].amountStaked = 1000000000000000000;
stakingTokenBalance += 1000000000000000000;
emit TokensStaked(_stakeMsgSender(), 1000000000000000000);
}
/// @dev Withdraw logic. Override to add custom logic.
function _withdraw() internal virtual {
_updateUnclaimedRewardsForStaker(_stakeMsgSender());
stakers[_stakeMsgSender()].amountStaked = 0;
stakingTokenBalance -= 1000000000000000000;
emit TokensWithdrawn(_stakeMsgSender(), 1000000000000000000);
}
/// @dev Logic for claiming rewards. Override to add custom logic.
function _claimRewards() internal virtual {
uint256 rewards = stakers[_stakeMsgSender()].unclaimedRewards + _calculateRewards(_stakeMsgSender());
require(rewards != 0, "No rewards");
stakers[_stakeMsgSender()].timeOfLastUpdate = uint80(block.timestamp);
stakers[_stakeMsgSender()].unclaimedRewards = 0;
stakers[_stakeMsgSender()].conditionIdOflastUpdate = nextConditionId - 1;
_mintRewards(_stakeMsgSender(), rewards);
emit RewardsClaimed(_stakeMsgSender(), rewards);
}
/// @dev View available rewards for a user.
function _availableRewards(address _staker) internal view virtual returns (uint256 _rewards) {
if (stakers[_staker].amountStaked == 0) {
_rewards = stakers[_staker].unclaimedRewards;
} else {
_rewards = stakers[_staker].unclaimedRewards + _calculateRewards(_staker);
}
}
/// @dev Update unclaimed rewards for a users. Called for every state change for a user.
function _updateUnclaimedRewardsForStaker(address _staker) internal virtual {
uint256 rewards = _calculateRewards(_staker);
stakers[_staker].unclaimedRewards += rewards;
stakers[_staker].timeOfLastUpdate = uint80(block.timestamp);
stakers[_staker].conditionIdOflastUpdate = nextConditionId - 1;
}
/// @dev Set staking conditions.
function _setStakingCondition(uint80 _timeUnit, uint256 _numerator, uint256 _denominator) internal virtual {
require(_denominator != 0, "divide by 0");
require(_timeUnit != 0, "time-unit can't be 0");
uint256 conditionId = nextConditionId;
nextConditionId += 1;
stakingConditions[conditionId] = StakingCondition({
timeUnit: _timeUnit,
rewardRatioNumerator: _numerator,
rewardRatioDenominator: _denominator,
startTimestamp: uint80(block.timestamp),
endTimestamp: 0
});
if (conditionId > 0) {
stakingConditions[conditionId - 1].endTimestamp = uint80(block.timestamp);
}
}
/// @dev Calculate rewards for a staker.
function _calculateRewards(address _staker) internal view virtual returns (uint256 _rewards) {
Staker memory staker = stakers[_staker];
uint256 _stakerConditionId = staker.conditionIdOflastUpdate;
uint256 _nextConditionId = nextConditionId;
for (uint256 i = _stakerConditionId; i < _nextConditionId; i += 1) {
StakingCondition memory condition = stakingConditions[i];
uint256 startTime = i != _stakerConditionId ? condition.startTimestamp : staker.timeOfLastUpdate;
uint256 endTime = condition.endTimestamp != 0 ? condition.endTimestamp : block.timestamp;
(bool noOverflowProduct, uint256 rewardsProduct) = SafeMath.tryMul(
(endTime - startTime) * staker.amountStaked,
condition.rewardRatioNumerator
);
(bool noOverflowSum, uint256 rewardsSum) = SafeMath.tryAdd(
_rewards,
(rewardsProduct / condition.timeUnit) / condition.rewardRatioDenominator
);
_rewards = noOverflowProduct && noOverflowSum ? rewardsSum : _rewards;
}
(, _rewards) = SafeMath.tryMul(_rewards, 10 ** rewardTokenDecimals);
_rewards /= (10 ** stakingTokenDecimals);
}
/*////////////////////////////////////////////////////////////////////
Optional hooks that can be implemented in the derived contract
///////////////////////////////////////////////////////////////////*/
/// @dev Exposes the ability to override the msg sender -- support ERC2771.
function _stakeMsgSender() internal virtual returns (address) {
return msg.sender;
}
/*///////////////////////////////////////////////////////////////
Virtual functions to be implemented in derived contract
//////////////////////////////////////////////////////////////*/
/**
* @notice View total rewards available in the staking contract.
*
*/
function getRewardTokenBalance() external view virtual returns (uint256 _rewardsAvailableInContract);
/**
* @dev Mint/Transfer ERC20 rewards to the staker. Must override.
*
* @param _staker Address for which to calculated rewards.
* @param _rewards Amount of tokens to be given out as reward.
*
* For example, override as below to mint ERC20 rewards:
*
* ```
* function _mintRewards(address _staker, uint256 _rewards) internal override {
*
* TokenERC20(rewardTokenAddress).mintTo(_staker, _rewards);
*
* }
* ```
*/
function _mintRewards(address _staker, uint256 _rewards) internal virtual;
/**
* @dev Returns whether staking restrictions can be set in given execution context.
* Must override.
*
*
* For example, override as below to restrict access to admin:
*
* ```
* function _canSetStakeConditions() internal override {
*
* return msg.sender == adminAddress;
*
* }
* ```
*/
function _canSetStakeConditions() internal view virtual returns (bool);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/**
* @title ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/**
* @title ERC20Metadata interface
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
interface IERC20Metadata {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
// Helper interfaces
import { IWETH } from "../infra/interface/IWETH.sol";
import { SafeERC20, IERC20 } from "../external-deps/openzeppelin/token/ERC20/utils/SafeERC20.sol";
library CurrencyTransferLib {
using SafeERC20 for IERC20;
error CurrencyTransferLibMismatchedValue(uint256 expected, uint256 actual);
error CurrencyTransferLibFailedNativeTransfer(address recipient, uint256 value);
/// @dev The address interpreted as native token of the chain.
address public constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
/// @dev Transfers a given amount of currency.
function transferCurrency(address _currency, address _from, address _to, uint256 _amount) internal {
if (_amount == 0) {
return;
}
if (_currency == NATIVE_TOKEN) {
safeTransferNativeToken(_to, _amount);
} else {
safeTransferERC20(_currency, _from, _to, _amount);
}
}
/// @dev Transfers a given amount of currency. (With native token wrapping)
function transferCurrencyWithWrapper(
address _currency,
address _from,
address _to,
uint256 _amount,
address _nativeTokenWrapper
) internal {
if (_amount == 0) {
return;
}
if (_currency == NATIVE_TOKEN) {
if (_from == address(this)) {
// withdraw from weth then transfer withdrawn native token to recipient
IWETH(_nativeTokenWrapper).withdraw(_amount);
safeTransferNativeTokenWithWrapper(_to, _amount, _nativeTokenWrapper);
} else if (_to == address(this)) {
// store native currency in weth
if (_amount != msg.value) {
revert CurrencyTransferLibMismatchedValue(msg.value, _amount);
}
IWETH(_nativeTokenWrapper).deposit{ value: _amount }();
} else {
safeTransferNativeTokenWithWrapper(_to, _amount, _nativeTokenWrapper);
}
} else {
safeTransferERC20(_currency, _from, _to, _amount);
}
}
/// @dev Transfer `amount` of ERC20 token from `from` to `to`.
function safeTransferERC20(address _currency, address _from, address _to, uint256 _amount) internal {
if (_from == _to) {
return;
}
if (_from == address(this)) {
IERC20(_currency).safeTransfer(_to, _amount);
} else {
IERC20(_currency).safeTransferFrom(_from, _to, _amount);
}
}
/// @dev Transfers `amount` of native token to `to`.
function safeTransferNativeToken(address to, uint256 value) internal {
// solhint-disable avoid-low-level-calls
// slither-disable-next-line low-level-calls
(bool success, ) = to.call{ value: value }("");
if (!success) {
revert CurrencyTransferLibFailedNativeTransfer(to, value);
}
}
/// @dev Transfers `amount` of native token to `to`. (With native token wrapping)
function safeTransferNativeTokenWithWrapper(address to, uint256 value, address _nativeTokenWrapper) internal {
// solhint-disable avoid-low-level-calls
// slither-disable-next-line low-level-calls
(bool success, ) = to.call{ value: value }("");
if (!success) {
IWETH(_nativeTokenWrapper).deposit{ value: value }();
IERC20(_nativeTokenWrapper).safeTransfer(to, value);
}
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
/**
* Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI
* for you contract.
*
* Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea.
*/
interface IContractMetadata {
/// @dev Returns the metadata URI of the contract.
function contractURI() external view returns (string memory);
/**
* @dev Sets contract URI for the storefront-level metadata of the contract.
* Only module admin can call this function.
*/
function setContractURI(string calldata _uri) external;
/// @dev Emitted when the contract URI is updated.
event ContractURIUpdated(string prevURI, string newURI);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.1;
/// @author thirdweb, OpenZeppelin Contracts (v4.9.0)
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author thirdweb
/**
* @dev Provides a function to batch together multiple calls in a single external call.
*
* _Available since v4.1._
*/
interface IMulticall {
/**
* @dev Receives and executes a batch of function calls on this contract.
*/
function multicall(bytes[] calldata data) external returns (bytes[] memory results);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
/**
* Thirdweb's `Ownable` is a contract extension to be used with any base contract. It exposes functions for setting and reading
* who the 'owner' of the inheriting smart contract is, and lets the inheriting contract perform conditional logic that uses
* information about who the contract's owner is.
*/
interface IOwnable {
/// @dev Returns the owner of the contract.
function owner() external view returns (address);
/// @dev Lets a module admin set a new owner for the contract. The new owner must be a module admin.
function setOwner(address _newOwner) external;
/// @dev Emitted when a new Owner is set.
event OwnerUpdated(address indexed prevOwner, address indexed newOwner);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.11;
/// @author thirdweb
interface IStaking20 {
/// @dev Emitted when tokens are staked.
event TokensStaked(address indexed staker, uint256 amount);
/// @dev Emitted when a tokens are withdrawn.
event TokensWithdrawn(address indexed staker, uint256 amount);
/// @dev Emitted when a staker claims staking rewards.
event RewardsClaimed(address indexed staker, uint256 rewardAmount);
/// @dev Emitted when contract admin updates timeUnit.
event UpdatedTimeUnit(uint256 oldTimeUnit, uint256 newTimeUnit);
/// @dev Emitted when contract admin updates rewardsPerUnitTime.
event UpdatedRewardRatio(
uint256 oldNumerator,
uint256 newNumerator,
uint256 oldDenominator,
uint256 newDenominator
);
/// @dev Emitted when contract admin updates minimum staking amount.
event UpdatedMinStakeAmount(uint256 oldAmount, uint256 newAmount);
/**
* @notice Staker Info.
*
* @param amountStaked Total number of tokens staked by the staker.
*
* @param timeOfLastUpdate Last reward-update timestamp.
*
* @param unclaimedRewards Rewards accumulated but not claimed by user yet.
*
* @param conditionIdOflastUpdate Condition-Id when rewards were last updated for user.
*/
struct Staker {
uint128 timeOfLastUpdate;
uint64 conditionIdOflastUpdate;
uint256 amountStaked;
uint256 unclaimedRewards;
}
/**
* @notice Staking Condition.
*
* @param timeUnit Unit of time specified in number of seconds. Can be set as 1 seconds, 1 days, 1 hours, etc.
*
* @param rewardRatioNumerator Rewards ratio is the number of reward tokens for a number of staked tokens,
* per unit of time.
*
* @param rewardRatioDenominator Rewards ratio is the number of reward tokens for a number of staked tokens,
* per unit of time.
*
* @param startTimestamp Condition start timestamp.
*
* @param endTimestamp Condition end timestamp.
*/
struct StakingCondition {
uint80 timeUnit;
uint80 startTimestamp;
uint80 endTimestamp;
uint256 rewardRatioNumerator;
uint256 rewardRatioDenominator;
}
/**
* @notice Stake ERC721 Tokens.
*
*/
function stake() external;
/**
* @notice Withdraw staked tokens.
*
*/
function withdraw() external;
/**
* @notice Claim accumulated rewards.
*
*/
function claimRewards() external;
/**
* @notice View amount staked and total rewards for a user.
*
* @param staker Address for which to calculated rewards.
*/
function getStakeInfo(address staker) external view returns (uint256 _tokensStaked, uint256 _rewards);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
interface IWETH {
function deposit() external payable;
function withdraw(uint256 amount) external;
function transfer(address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../../../../../eip/interface/IERC20.sol";
import { Address } from "../../../../../lib/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}{
"remappings": [
"@uniswap/v3-core/contracts/=lib/v3-core/contracts/",
"@uniswap/v3-periphery/contracts/=lib/v3-periphery/contracts/",
"@uniswap/swap-router-contracts/contracts/=lib/swap-router-contracts/contracts/",
"@chainlink/=lib/chainlink/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"@ds-test/=lib/ds-test/src/",
"@std/=lib/forge-std/src/",
"contracts/=contracts/",
"erc721a-upgradeable/=lib/ERC721A-Upgradeable/",
"erc721a/=lib/ERC721A/",
"@thirdweb-dev/dynamic-contracts/=lib/dynamic-contracts/",
"lib/sstore2/=lib/dynamic-contracts/lib/sstore2/",
"solady/=lib/solady/",
"@seaport/=lib/seaport/contracts/",
"seaport-types/=lib/seaport/lib/seaport-types/",
"seaport-core/=lib/seaport/lib/seaport-core/",
"@rari-capital/solmate/=lib/seaport/lib/solmate/",
"ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/",
"ERC721A/=lib/ERC721A/contracts/",
"chainlink/=lib/chainlink/contracts/",
"ds-test/=lib/ds-test/src/",
"dynamic-contracts/=lib/dynamic-contracts/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"murky/=lib/murky/src/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"openzeppelin/=lib/openzeppelin-contracts/contracts/",
"seaport-sol/=lib/seaport-sol/src/",
"seaport/=lib/seaport/",
"solarray/=lib/seaport-sol/lib/solarray/src/",
"solmate/=lib/seaport/lib/solmate/src/",
"sstore2/=lib/dynamic-contracts/lib/sstore2/contracts/",
"swap-router-contracts/=lib/swap-router-contracts/contracts/",
"v3-core/=lib/v3-core/",
"v3-periphery/=lib/v3-periphery/contracts/"
],
"optimizer": {
"enabled": true,
"runs": 20
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint80","name":"_timeUnit","type":"uint80"},{"internalType":"address","name":"_defaultAdmin","type":"address"},{"internalType":"uint256","name":"_rewardRatioNumerator","type":"uint256"},{"internalType":"uint256","name":"_rewardRatioDenominator","type":"uint256"},{"internalType":"address","name":"_stakingToken","type":"address"},{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"address","name":"_nativeTokenWrapper","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ContractMetadataUnauthorized","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"name":"CurrencyTransferLibMismatchedValue","type":"error"},{"inputs":[],"name":"OwnableUnauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"prevURI","type":"string"},{"indexed":false,"internalType":"string","name":"newURI","type":"string"}],"name":"ContractURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"prevOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"name":"RewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensStaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newAmount","type":"uint256"}],"name":"UpdatedMinStakeAmount","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldNumerator","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newNumerator","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldDenominator","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newDenominator","type":"uint256"}],"name":"UpdatedRewardRatio","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldTimeUnit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTimeUnit","type":"uint256"}],"name":"UpdatedTimeUnit","type":"event"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositRewardTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getRewardRatio","outputs":[{"internalType":"uint256","name":"_numerator","type":"uint256"},{"internalType":"uint256","name":"_denominator","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardTokenBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"getStakeInfo","outputs":[{"internalType":"uint256","name":"_tokensStaked","type":"uint256"},{"internalType":"uint256","name":"_rewards","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTimeUnit","outputs":[{"internalType":"uint256","name":"_timeUnit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"hasStaked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardTokenDecimals","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_numerator","type":"uint256"},{"internalType":"uint256","name":"_denominator","type":"uint256"}],"name":"setRewardRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint80","name":"_timeUnit","type":"uint80"}],"name":"setTimeUnit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakers","outputs":[{"internalType":"uint128","name":"timeOfLastUpdate","type":"uint128"},{"internalType":"uint64","name":"conditionIdOflastUpdate","type":"uint64"},{"internalType":"uint256","name":"amountStaked","type":"uint256"},{"internalType":"uint256","name":"unclaimedRewards","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingTokenBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingTokenDecimals","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawRewardTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
0x6101206040523480156200001257600080fd5b5060405162002ef838038062002ef88339810160408190526200003591620004c9565b8083846001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000076573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009c919062000559565b60ff16846001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000104919062000559565b600160025560ff166001600160a01b038316158015906200012d57506001600160a01b03841615155b6200016b5760405162461bcd60e51b815260206004820152600960248201526806164647265737320360bc1b60448201526064015b60405180910390fd5b61ffff82161580159062000182575061ffff811615155b620001bd5760405162461bcd60e51b815260206004820152600a6024820152690646563696d616c7320360b41b604482015260640162000162565b6001600160a01b039384166080529190921660a05261ffff91821660c0521660e052620001ea866200028a565b620001f7878686620002dc565b826001600160a01b0316826001600160a01b031603620002705760405162461bcd60e51b815260206004820152602d60248201527f52657761726420546f6b656e20616e64205374616b696e6720546f6b656e206360448201526c30b713ba1031329039b0b6b29760991b606482015260840162000162565b506001600160a01b03166101005250620005e19350505050565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7690600090a35050565b806000036200031c5760405162461bcd60e51b815260206004820152600b60248201526a064697669646520627920360ac1b604482015260640162000162565b826001600160501b0316600003620003775760405162461bcd60e51b815260206004820152601460248201527f74696d652d756e69742063616e27742062652030000000000000000000000000604482015260640162000162565b600380546001600160401b03169060019060006200039683856200059b565b82546001600160401b039182166101009390930a9283029190920219909116179055506040805160a0810182526001600160501b03808716825242811660208084019182526000848601818152606086018a8152608087018a815289845260079094529690912094518554935191518516600160a01b02600160a01b600160f01b03199286166a0100000000000000000000026001600160a01b0319909516919095161792909217919091169190911782559151600182015590516002909101558015620004a657426007600062000470600185620005c5565b815260200190815260200160002060000160146101000a8154816001600160501b0302191690836001600160501b031602179055505b50505050565b80516001600160a01b0381168114620004c457600080fd5b919050565b600080600080600080600060e0888a031215620004e557600080fd5b87516001600160501b0381168114620004fd57600080fd5b96506200050d60208901620004ac565b955060408801519450606088015193506200052b60808901620004ac565b92506200053b60a08901620004ac565b91506200054b60c08901620004ac565b905092959891949750929550565b6000602082840312156200056c57600080fd5b815160ff811681146200057e57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b6001600160401b03818116838216019080821115620005be57620005be62000585565b5092915050565b81810381811115620005db57620005db62000585565b92915050565b60805160a05160c05160e05161010051612870620006886000396000818161052a01528181610f9e01528181610fe2015281816110a0015281816115c80152611b560152600081816103ab0152611a7f01526000818161043f0152611ab301526000818161024001528181611614015261165801526000818161012301528181611008015281816110c4015281816115ec0152818161167e0152611b7a01526128706000f3fe6080604052600436106101135760003560e01c80621b79341461019c57806313af4035146101bc57806316c621e0146101dc578063372500ab146101ef5780633a4b66f1146102045780633ccfd60b1461021957806372f702f31461022e5780638caaa271146102785780638da5cb5b1461029c5780639168ae72146102b1578063938e3d7b1461033a57806393ce53431461035a57806397e1b4bc1461036f5780639bdcecd114610399578063ac9650d8146103e0578063b218f0691461040d578063b9f7a7b51461042d578063c345315314610461578063c93c8f3414610481578063cb43b2dd146104c1578063d68124c7146104e1578063e8a3d485146104f6578063f7c618c11461051857600080fd5b3661019757336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146101955760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206e6f74206e617469766520746f6b656e20777261707065722e60448201526064015b60405180910390fd5b005b600080fd5b3480156101a857600080fd5b506101956101b736600461210a565b61054c565b3480156101c857600080fd5b506101956101d736600461212c565b6106b6565b6101956101ea366004612155565b6106e7565b3480156101fb57600080fd5b5061019561071d565b34801561021057600080fd5b50610195610751565b34801561022557600080fd5b506101956107f1565b34801561023a57600080fd5b506102627f000000000000000000000000000000000000000000000000000000000000000081565b60405161026f919061216e565b60405180910390f35b34801561028457600080fd5b5061028e60045481565b60405190815260200161026f565b3480156102a857600080fd5b50610262610888565b3480156102bd57600080fd5b506103086102cc36600461212c565b6006602052600090815260409020805460018201546002909201546001600160801b03821692600160801b9092046001600160401b0316919084565b604080516001600160801b0390951685526001600160401b03909316602085015291830152606082015260800161026f565b34801561034657600080fd5b50610195610355366004612198565b610897565b34801561036657600080fd5b5060085461028e565b34801561037b57600080fd5b506103846108c5565b6040805192835260208301919091520161026f565b3480156103a557600080fd5b506103cd7f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff909116815260200161026f565b3480156103ec57600080fd5b506104006103fb366004612248565b61094b565b60405161026f919061230c565b34801561041957600080fd5b50610195610428366004612370565b610ab1565b34801561043957600080fd5b506103cd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561046d57600080fd5b5061038461047c36600461212c565b610c05565b34801561048d57600080fd5b506104b161049c36600461212c565b60056020526000908152604090205460ff1681565b604051901515815260200161026f565b3480156104cd57600080fd5b506101956104dc366004612155565b610c32565b3480156104ed57600080fd5b5061028e610c60565b34801561050257600080fd5b5061050b610ca8565b60405161026f9190612399565b34801561052457600080fd5b506102627f000000000000000000000000000000000000000000000000000000000000000081565b610554610d36565b6105705760405162461bcd60e51b815260040161018c906123ac565b6003546000906007908290610590906001906001600160401b03166123ea565b6001600160401b031681526020808201929092526040908101600020815160a08101835281546001600160501b038082168352600160501b8204811695830195909552600160a01b900490931691830191909152600181015460608301819052600290910154608083015290915083141580610610575080608001518214155b6106565760405162461bcd60e51b81526020600482015260176024820152762932bbb0b932103930ba34b7903ab731b430b733b2b21760491b604482015260640161018c565b8051610663908484610d59565b60608082015160808084015160408051938452602084018890528301529181018490527feb6684a1e7c9bd2adc792fb253558f022bcbef39fb6ad31dc58cdfefdd5b5190910160405180910390a1505050565b6106be610d36565b6106db576040516316ccb9cb60e11b815260040160405180910390fd5b6106e481610f10565b50565b60028054036107085760405162461bcd60e51b815260040161018c90612411565b6002805561071581610f62565b506001600255565b600280540361073e5760405162461bcd60e51b815260040161018c90612411565b6002805561074a611181565b6001600255565b60028054036107725760405162461bcd60e51b815260040161018c90612411565b600280553360009081526005602052604090205460ff16156107c75760405162461bcd60e51b815260206004820152600e60248201526d105b1c9958591e481cdd185ad95960921b604482015260640161018c565b6107cf6112a7565b336000908152600560205260409020805460ff19166001908117909155600255565b60028054036108125760405162461bcd60e51b815260040161018c90612411565b600280553360009081526005602052604090205460ff166108625760405162461bcd60e51b815260206004820152600a602482015269139bdd081cdd185ad95960b21b604482015260640161018c565b61086a611387565b336000908152600560205260409020805460ff191690556001600255565b6001546001600160a01b031690565b61089f610d36565b6108bc57604051639f7f092560e01b815260040160405180910390fd5b6106e4816113fe565b600354600090819060079082906108e7906001906001600160401b03166123ea565b6001600160401b03168152602001908152602001600020600101549150600760006001600360009054906101000a90046001600160401b031661092a91906123ea565b6001600160401b031681526020019081526020016000206002015490509091565b6060816001600160401b0381111561096557610965612182565b60405190808252806020026020018201604052801561099857816020015b60608152602001906001900390816109835790505b509050336000805b84811015610aa7578115610a1f576109fd308787848181106109c4576109c4612448565b90506020028101906109d6919061245e565b866040516020016109e9939291906124a4565b6040516020818303038152906040526114cd565b848281518110610a0f57610a0f612448565b6020026020010181905250610a9f565b610a8130878784818110610a3557610a35612448565b9050602002810190610a47919061245e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506114cd92505050565b848281518110610a9357610a93612448565b60200260200101819052505b6001016109a0565b5050505b92915050565b610ab9610d36565b610ad55760405162461bcd60e51b815260040161018c906123ac565b6003546000906007908290610af5906001906001600160401b03166123ea565b6001600160401b031681526020808201929092526040908101600020815160a08101835281546001600160501b03808216808452600160501b8304821696840196909652600160a01b9091048116938201939093526001820154606082015260029091015460808201529250831603610ba75760405162461bcd60e51b81526020600482015260146024820152732a34b6b296bab734ba103ab731b430b733b2b21760611b604482015260640161018c565b610bba8282606001518360800151610d59565b8051604080516001600160501b03928316815291841660208301527fd968de290ed68f978b9e4816f7d4be9ef46189fe8eeb3eeb86199e7229cf2de091015b60405180910390a15050565b6001600160a01b03811660009081526006602052604081206001015490610c2b836114f9565b9050915091565b6002805403610c535760405162461bcd60e51b815260040161018c90612411565b6002805561071581611569565b6003546000906007908290610c80906001906001600160401b03166123ea565b6001600160401b031681526020810191909152604001600020546001600160501b0316919050565b60008054610cb5906124c5565b80601f0160208091040260200160405190810160405280929190818152602001828054610ce1906124c5565b8015610d2e5780601f10610d0357610100808354040283529160200191610d2e565b820191906000526020600020905b815481529060010190602001808311610d1157829003601f168201915b505050505081565b6000610d40610888565b6001600160a01b0316336001600160a01b031614905090565b80600003610d975760405162461bcd60e51b815260206004820152600b60248201526a064697669646520627920360ac1b604482015260640161018c565b826001600160501b0316600003610de75760405162461bcd60e51b8152602060048201526014602482015273074696d652d756e69742063616e277420626520360641b604482015260640161018c565b600380546001600160401b0316906001906000610e0483856124ff565b82546001600160401b039182166101009390930a9283029190920219909116179055506040805160a0810182526001600160501b03808716825242811660208084019182526000848601818152606086018a8152608087018a815289845260079094529690912094518554935191518516600160a01b02600160a01b600160f01b0319928616600160501b026001600160a01b0319909516919095161792909217919091169190911782559151600182015590516002909101558015610f0a574260076000610ed460018561251f565b815260200190815260200160002060000160146101000a8154816001600160501b0302191690836001600160501b031602179055505b50505050565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7690600090a35050565b610f6a610888565b6001600160a01b0316336001600160a01b031614610f9a5760405162461bcd60e51b815260040161018c906123ac565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611006577f0000000000000000000000000000000000000000000000000000000000000000611028565b7f00000000000000000000000000000000000000000000000000000000000000005b90506000816001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611058919061216e565b602060405180830381865afa158015611075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110999190612532565b90506110e87f00000000000000000000000000000000000000000000000000000000000000003330867f0000000000000000000000000000000000000000000000000000000000000000611762565b600081836001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611117919061216e565b602060405180830381865afa158015611134573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111589190612532565b611162919061251f565b90508060086000828254611176919061254b565b909155505050505050565b600061118c336118b7565b336000908152600660205260409020600201546111a9919061254b565b9050806000036111e85760405162461bcd60e51b815260206004820152600a6024820152694e6f207265776172647360b01b604482015260640161018c565b33600090815260066020526040812080546001600160801b031916426001600160501b03161781556002015560035461122c906001906001600160401b03166123ea565b33600081815260066020526040902080546001600160401b0393909316600160801b02600160801b600160c01b03199093169290921790915561126f9082611aec565b60405181815233907ffc30cddea38e2bf4d6ea7d3f9ed3b6ad7f176419f4963bd81318067a4aee73fe9060200160405180910390a250565b33600090815260066020526040902080546001600160801b031916426001600160501b03161790556003546112e7906001906001600160401b03166123ea565b33600090815260066020526040812080546001600160401b0393909316600160801b02600160801b600160c01b0319909316929092178255670de0b6b3a764000060019092018290556004805490919061134290849061254b565b9091555050604051670de0b6b3a7640000815233907fb539ca1e5c8d398ddf1c41c30166f33404941683be4683319b57669a93dad4ef906020015b60405180910390a2565b61139033611b9e565b33600090815260066020526040812060010181905560048054670de0b6b3a764000092906113bf90849061251f565b9091555050604051670de0b6b3a7640000815233907f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b9060200161137d565b600080805461140c906124c5565b80601f0160208091040260200160405190810160405280929190818152602001828054611438906124c5565b80156114855780601f1061145a57610100808354040283529160200191611485565b820191906000526020600020905b81548152906001019060200180831161146857829003601f168201915b50505050509050816000908161149b91906125ae565b507fc9c7c3fe08b88b4df9d4d47ef47d2c43d55c025a0ba88ca442580ed9e7348a168183604051610bf992919061266d565b60606114f2838360405180606001604052806027815260200161281460279139611c6d565b9392505050565b6001600160a01b038116600090815260066020526040812060010154810361153a57506001600160a01b031660009081526006602052604090206002015490565b611543826118b7565b6001600160a01b038316600090815260066020526040902060020154610aab919061254b565b611571610888565b6001600160a01b0316336001600160a01b0316146115a15760405162461bcd60e51b815260040161018c906123ac565b60085481116115bd57806008546115b8919061251f565b6115c0565b60005b6008556116107f00000000000000000000000000000000000000000000000000000000000000003033847f0000000000000000000000000000000000000000000000000000000000000000611762565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1461167c577f000000000000000000000000000000000000000000000000000000000000000061169e565b7f00000000000000000000000000000000000000000000000000000000000000005b9050600454816001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016116cf919061216e565b602060405180830381865afa1580156116ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117109190612532565b101561175e5760405162461bcd60e51b815260206004820152601e60248201527f5374616b696e6720746f6b656e2062616c616e636520726564756365642e0000604482015260640161018c565b5050565b81156118b05773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038616016118a457306001600160a01b0385160361180757604051632e1a7d4d60e01b8152600481018390526001600160a01b03821690632e1a7d4d90602401600060405180830381600087803b1580156117df57600080fd5b505af11580156117f3573d6000803e3d6000fd5b50505050611802838383611ce5565b6118b0565b306001600160a01b0384160361189957348214611840576040516303e085f960e01b81523460048201526024810183905260440161018c565b806001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b15801561187b57600080fd5b505af115801561188f573d6000803e3d6000fd5b50505050506118b0565b611802838383611ce5565b6118b085858585611daa565b5050505050565b6001600160a01b0381166000908152600660209081526040808320815160808101835281546001600160801b03811682526001600160401b03600160801b9091048116948201859052600183015493820193909352600290910154606082015260035490929116815b81811015611a75576000818152600760209081526040808320815160a08101835281546001600160501b038082168352600160501b8204811695830195909552600160a01b90049093169183019190915260018101546060830152600201546080820152908483036119935785516119a2565b81602001516001600160501b03165b6001600160801b03169050600082604001516001600160501b03166000036119ca57426119d9565b82604001516001600160501b03165b9050600080611a06896040015185856119f2919061251f565b6119fc9190612692565b8660600151611e02565b91509150600080611a3e8c886080015189600001516001600160501b031686611a2f91906126bf565b611a3991906126bf565b611e4d565b91509150838015611a4c5750815b611a56578b611a58565b805b9b5050505050505050600181611a6e919061254b565b9050611920565b50611aaa84611aa57f0000000000000000000000000000000000000000000000000000000000000000600a6127c5565b611e02565b9450611ad990507f0000000000000000000000000000000000000000000000000000000000000000600a6127c5565b611ae390856126bf565b95945050505050565b600854811115611b395760405162461bcd60e51b81526020600482015260186024820152774e6f7420656e6f7567682072657761726420746f6b656e7360401b604482015260640161018c565b8060086000828254611b4b919061251f565b9091555061175e90507f00000000000000000000000000000000000000000000000000000000000000003084847f0000000000000000000000000000000000000000000000000000000000000000611762565b6000611ba9826118b7565b6001600160a01b038316600090815260066020526040812060020180549293508392909190611bd990849061254b565b90915550506001600160a01b038216600090815260066020526040902080546001600160801b0319166001600160501b034216179055600354611c27906001906001600160401b03166123ea565b6001600160a01b03909216600090815260066020526040902080546001600160401b0393909316600160801b02600160801b600160c01b03199093169290921790915550565b6060600080856001600160a01b031685604051611c8a91906127d5565b600060405180830381855af49150503d8060008114611cc5576040519150601f19603f3d011682016040523d82523d6000602084013e611cca565b606091505b5091509150611cdb86838387611e68565b9695505050505050565b6000836001600160a01b03168360405160006040518083038185875af1925050503d8060008114611d32576040519150601f19603f3d011682016040523d82523d6000602084013e611d37565b606091505b5050905080610f0a57816001600160a01b031663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d7b57600080fd5b505af1158015611d8f573d6000803e3d6000fd5b50610f0a935050506001600160a01b03841690508585611ee9565b816001600160a01b0316836001600160a01b03160315610f0a57306001600160a01b03841603611ded57611de86001600160a01b0385168383611ee9565b610f0a565b610f0a6001600160a01b038516848484611f51565b60008083600003611e195750600190506000611e46565b83830283858281611e2c57611e2c6126a9565b0414611e3f576000809250925050611e46565b6001925090505b9250929050565b60008083830184811015611e3f576000809250925050611e46565b60608315611ed7578251600003611ed0576001600160a01b0385163b611ed05760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161018c565b5081611ee1565b611ee18383611f89565b949350505050565b6040516001600160a01b038316602482015260448101829052611f4c90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611fb3565b505050565b6040516001600160a01b0380851660248301528316604482015260648101829052610f0a9085906323b872dd60e01b90608401611f15565b815115611f995781518083602001fd5b8060405162461bcd60e51b815260040161018c9190612399565b6000612008826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166120859092919063ffffffff16565b805190915015611f4c578080602001905181019061202691906127f1565b611f4c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161018c565b6060611ee1848460008585600080866001600160a01b031685876040516120ac91906127d5565b60006040518083038185875af1925050503d80600081146120e9576040519150601f19603f3d011682016040523d82523d6000602084013e6120ee565b606091505b50915091506120ff87838387611e68565b979650505050505050565b6000806040838503121561211d57600080fd5b50508035926020909101359150565b60006020828403121561213e57600080fd5b81356001600160a01b03811681146114f257600080fd5b60006020828403121561216757600080fd5b5035919050565b6001600160a01b0391909116815260200190565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156121aa57600080fd5b81356001600160401b03808211156121c157600080fd5b818401915084601f8301126121d557600080fd5b8135818111156121e7576121e7612182565b604051601f8201601f19908116603f0116810190838211818310171561220f5761220f612182565b8160405282815287602084870101111561222857600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000806020838503121561225b57600080fd5b82356001600160401b038082111561227257600080fd5b818501915085601f83011261228657600080fd5b81358181111561229557600080fd5b8660208260051b85010111156122aa57600080fd5b60209290920196919550909350505050565b60005b838110156122d75781810151838201526020016122bf565b50506000910152565b600081518084526122f88160208601602086016122bc565b601f01601f19169290920160200192915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561236357603f198886030184526123518583516122e0565b94509285019290850190600101612335565b5092979650505050505050565b60006020828403121561238257600080fd5b81356001600160501b03811681146114f257600080fd5b6020815260006114f260208301846122e0565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b6001600160401b0382811682821603908082111561240a5761240a6123d4565b5092915050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261247557600080fd5b8301803591506001600160401b0382111561248f57600080fd5b602001915036819003821315611e4657600080fd5b8284823760609190911b6001600160601b0319169101908152601401919050565b600181811c908216806124d957607f821691505b6020821081036124f957634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160401b0381811683821601908082111561240a5761240a6123d4565b81810381811115610aab57610aab6123d4565b60006020828403121561254457600080fd5b5051919050565b80820180821115610aab57610aab6123d4565b601f821115611f4c576000816000526020600020601f850160051c810160208610156125875750805b601f850160051c820191505b818110156125a657828155600101612593565b505050505050565b81516001600160401b038111156125c7576125c7612182565b6125db816125d584546124c5565b8461255e565b602080601f83116001811461261057600084156125f85750858301515b600019600386901b1c1916600185901b1785556125a6565b600085815260208120601f198616915b8281101561263f57888601518255948401946001909101908401612620565b508582101561265d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60408152600061268060408301856122e0565b8281036020840152611ae381856122e0565b8082028115828204841417610aab57610aab6123d4565b634e487b7160e01b600052601260045260246000fd5b6000826126dc57634e487b7160e01b600052601260045260246000fd5b500490565b600181815b8085111561271c578160001904821115612702576127026123d4565b8085161561270f57918102915b93841c93908002906126e6565b509250929050565b60008261273357506001610aab565b8161274057506000610aab565b816001811461275657600281146127605761277c565b6001915050610aab565b60ff841115612771576127716123d4565b50506001821b610aab565b5060208310610133831016604e8410600b841016171561279f575081810a610aab565b6127a983836126e1565b80600019048211156127bd576127bd6123d4565b029392505050565b60006114f261ffff841683612724565b600082516127e78184602087016122bc565b9190910192915050565b60006020828403121561280357600080fd5b815180151581146114f257600080fdfe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122097099cb2b1d5e5462d2ed985c348aebf25c6dc2ec2040261da1ec5622de1e7ab64736f6c634300081700330000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a3c2c8ce6be1c55401b5f1efb6112a86f6374429000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000021c0000000000000000000000000f7127c505ef9bb661da4e104b01dc9aee2bf4435000000000000000000000000ede54d9c024ee80c85ec0a75ed2d8774c7fbac9b0000000000000000000000004200000000000000000000000000000000000006
Deployed Bytecode
0x6080604052600436106101135760003560e01c80621b79341461019c57806313af4035146101bc57806316c621e0146101dc578063372500ab146101ef5780633a4b66f1146102045780633ccfd60b1461021957806372f702f31461022e5780638caaa271146102785780638da5cb5b1461029c5780639168ae72146102b1578063938e3d7b1461033a57806393ce53431461035a57806397e1b4bc1461036f5780639bdcecd114610399578063ac9650d8146103e0578063b218f0691461040d578063b9f7a7b51461042d578063c345315314610461578063c93c8f3414610481578063cb43b2dd146104c1578063d68124c7146104e1578063e8a3d485146104f6578063f7c618c11461051857600080fd5b3661019757336001600160a01b037f000000000000000000000000420000000000000000000000000000000000000616146101955760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206e6f74206e617469766520746f6b656e20777261707065722e60448201526064015b60405180910390fd5b005b600080fd5b3480156101a857600080fd5b506101956101b736600461210a565b61054c565b3480156101c857600080fd5b506101956101d736600461212c565b6106b6565b6101956101ea366004612155565b6106e7565b3480156101fb57600080fd5b5061019561071d565b34801561021057600080fd5b50610195610751565b34801561022557600080fd5b506101956107f1565b34801561023a57600080fd5b506102627f000000000000000000000000f7127c505ef9bb661da4e104b01dc9aee2bf443581565b60405161026f919061216e565b60405180910390f35b34801561028457600080fd5b5061028e60045481565b60405190815260200161026f565b3480156102a857600080fd5b50610262610888565b3480156102bd57600080fd5b506103086102cc36600461212c565b6006602052600090815260409020805460018201546002909201546001600160801b03821692600160801b9092046001600160401b0316919084565b604080516001600160801b0390951685526001600160401b03909316602085015291830152606082015260800161026f565b34801561034657600080fd5b50610195610355366004612198565b610897565b34801561036657600080fd5b5060085461028e565b34801561037b57600080fd5b506103846108c5565b6040805192835260208301919091520161026f565b3480156103a557600080fd5b506103cd7f000000000000000000000000000000000000000000000000000000000000001281565b60405161ffff909116815260200161026f565b3480156103ec57600080fd5b506104006103fb366004612248565b61094b565b60405161026f919061230c565b34801561041957600080fd5b50610195610428366004612370565b610ab1565b34801561043957600080fd5b506103cd7f000000000000000000000000000000000000000000000000000000000000001281565b34801561046d57600080fd5b5061038461047c36600461212c565b610c05565b34801561048d57600080fd5b506104b161049c36600461212c565b60056020526000908152604090205460ff1681565b604051901515815260200161026f565b3480156104cd57600080fd5b506101956104dc366004612155565b610c32565b3480156104ed57600080fd5b5061028e610c60565b34801561050257600080fd5b5061050b610ca8565b60405161026f9190612399565b34801561052457600080fd5b506102627f000000000000000000000000ede54d9c024ee80c85ec0a75ed2d8774c7fbac9b81565b610554610d36565b6105705760405162461bcd60e51b815260040161018c906123ac565b6003546000906007908290610590906001906001600160401b03166123ea565b6001600160401b031681526020808201929092526040908101600020815160a08101835281546001600160501b038082168352600160501b8204811695830195909552600160a01b900490931691830191909152600181015460608301819052600290910154608083015290915083141580610610575080608001518214155b6106565760405162461bcd60e51b81526020600482015260176024820152762932bbb0b932103930ba34b7903ab731b430b733b2b21760491b604482015260640161018c565b8051610663908484610d59565b60608082015160808084015160408051938452602084018890528301529181018490527feb6684a1e7c9bd2adc792fb253558f022bcbef39fb6ad31dc58cdfefdd5b5190910160405180910390a1505050565b6106be610d36565b6106db576040516316ccb9cb60e11b815260040160405180910390fd5b6106e481610f10565b50565b60028054036107085760405162461bcd60e51b815260040161018c90612411565b6002805561071581610f62565b506001600255565b600280540361073e5760405162461bcd60e51b815260040161018c90612411565b6002805561074a611181565b6001600255565b60028054036107725760405162461bcd60e51b815260040161018c90612411565b600280553360009081526005602052604090205460ff16156107c75760405162461bcd60e51b815260206004820152600e60248201526d105b1c9958591e481cdd185ad95960921b604482015260640161018c565b6107cf6112a7565b336000908152600560205260409020805460ff19166001908117909155600255565b60028054036108125760405162461bcd60e51b815260040161018c90612411565b600280553360009081526005602052604090205460ff166108625760405162461bcd60e51b815260206004820152600a602482015269139bdd081cdd185ad95960b21b604482015260640161018c565b61086a611387565b336000908152600560205260409020805460ff191690556001600255565b6001546001600160a01b031690565b61089f610d36565b6108bc57604051639f7f092560e01b815260040160405180910390fd5b6106e4816113fe565b600354600090819060079082906108e7906001906001600160401b03166123ea565b6001600160401b03168152602001908152602001600020600101549150600760006001600360009054906101000a90046001600160401b031661092a91906123ea565b6001600160401b031681526020019081526020016000206002015490509091565b6060816001600160401b0381111561096557610965612182565b60405190808252806020026020018201604052801561099857816020015b60608152602001906001900390816109835790505b509050336000805b84811015610aa7578115610a1f576109fd308787848181106109c4576109c4612448565b90506020028101906109d6919061245e565b866040516020016109e9939291906124a4565b6040516020818303038152906040526114cd565b848281518110610a0f57610a0f612448565b6020026020010181905250610a9f565b610a8130878784818110610a3557610a35612448565b9050602002810190610a47919061245e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506114cd92505050565b848281518110610a9357610a93612448565b60200260200101819052505b6001016109a0565b5050505b92915050565b610ab9610d36565b610ad55760405162461bcd60e51b815260040161018c906123ac565b6003546000906007908290610af5906001906001600160401b03166123ea565b6001600160401b031681526020808201929092526040908101600020815160a08101835281546001600160501b03808216808452600160501b8304821696840196909652600160a01b9091048116938201939093526001820154606082015260029091015460808201529250831603610ba75760405162461bcd60e51b81526020600482015260146024820152732a34b6b296bab734ba103ab731b430b733b2b21760611b604482015260640161018c565b610bba8282606001518360800151610d59565b8051604080516001600160501b03928316815291841660208301527fd968de290ed68f978b9e4816f7d4be9ef46189fe8eeb3eeb86199e7229cf2de091015b60405180910390a15050565b6001600160a01b03811660009081526006602052604081206001015490610c2b836114f9565b9050915091565b6002805403610c535760405162461bcd60e51b815260040161018c90612411565b6002805561071581611569565b6003546000906007908290610c80906001906001600160401b03166123ea565b6001600160401b031681526020810191909152604001600020546001600160501b0316919050565b60008054610cb5906124c5565b80601f0160208091040260200160405190810160405280929190818152602001828054610ce1906124c5565b8015610d2e5780601f10610d0357610100808354040283529160200191610d2e565b820191906000526020600020905b815481529060010190602001808311610d1157829003601f168201915b505050505081565b6000610d40610888565b6001600160a01b0316336001600160a01b031614905090565b80600003610d975760405162461bcd60e51b815260206004820152600b60248201526a064697669646520627920360ac1b604482015260640161018c565b826001600160501b0316600003610de75760405162461bcd60e51b8152602060048201526014602482015273074696d652d756e69742063616e277420626520360641b604482015260640161018c565b600380546001600160401b0316906001906000610e0483856124ff565b82546001600160401b039182166101009390930a9283029190920219909116179055506040805160a0810182526001600160501b03808716825242811660208084019182526000848601818152606086018a8152608087018a815289845260079094529690912094518554935191518516600160a01b02600160a01b600160f01b0319928616600160501b026001600160a01b0319909516919095161792909217919091169190911782559151600182015590516002909101558015610f0a574260076000610ed460018561251f565b815260200190815260200160002060000160146101000a8154816001600160501b0302191690836001600160501b031602179055505b50505050565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7690600090a35050565b610f6a610888565b6001600160a01b0316336001600160a01b031614610f9a5760405162461bcd60e51b815260040161018c906123ac565b60007f000000000000000000000000ede54d9c024ee80c85ec0a75ed2d8774c7fbac9b6001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611006577f000000000000000000000000ede54d9c024ee80c85ec0a75ed2d8774c7fbac9b611028565b7f00000000000000000000000042000000000000000000000000000000000000065b90506000816001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611058919061216e565b602060405180830381865afa158015611075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110999190612532565b90506110e87f000000000000000000000000ede54d9c024ee80c85ec0a75ed2d8774c7fbac9b3330867f0000000000000000000000004200000000000000000000000000000000000006611762565b600081836001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611117919061216e565b602060405180830381865afa158015611134573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111589190612532565b611162919061251f565b90508060086000828254611176919061254b565b909155505050505050565b600061118c336118b7565b336000908152600660205260409020600201546111a9919061254b565b9050806000036111e85760405162461bcd60e51b815260206004820152600a6024820152694e6f207265776172647360b01b604482015260640161018c565b33600090815260066020526040812080546001600160801b031916426001600160501b03161781556002015560035461122c906001906001600160401b03166123ea565b33600081815260066020526040902080546001600160401b0393909316600160801b02600160801b600160c01b03199093169290921790915561126f9082611aec565b60405181815233907ffc30cddea38e2bf4d6ea7d3f9ed3b6ad7f176419f4963bd81318067a4aee73fe9060200160405180910390a250565b33600090815260066020526040902080546001600160801b031916426001600160501b03161790556003546112e7906001906001600160401b03166123ea565b33600090815260066020526040812080546001600160401b0393909316600160801b02600160801b600160c01b0319909316929092178255670de0b6b3a764000060019092018290556004805490919061134290849061254b565b9091555050604051670de0b6b3a7640000815233907fb539ca1e5c8d398ddf1c41c30166f33404941683be4683319b57669a93dad4ef906020015b60405180910390a2565b61139033611b9e565b33600090815260066020526040812060010181905560048054670de0b6b3a764000092906113bf90849061251f565b9091555050604051670de0b6b3a7640000815233907f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b9060200161137d565b600080805461140c906124c5565b80601f0160208091040260200160405190810160405280929190818152602001828054611438906124c5565b80156114855780601f1061145a57610100808354040283529160200191611485565b820191906000526020600020905b81548152906001019060200180831161146857829003601f168201915b50505050509050816000908161149b91906125ae565b507fc9c7c3fe08b88b4df9d4d47ef47d2c43d55c025a0ba88ca442580ed9e7348a168183604051610bf992919061266d565b60606114f2838360405180606001604052806027815260200161281460279139611c6d565b9392505050565b6001600160a01b038116600090815260066020526040812060010154810361153a57506001600160a01b031660009081526006602052604090206002015490565b611543826118b7565b6001600160a01b038316600090815260066020526040902060020154610aab919061254b565b611571610888565b6001600160a01b0316336001600160a01b0316146115a15760405162461bcd60e51b815260040161018c906123ac565b60085481116115bd57806008546115b8919061251f565b6115c0565b60005b6008556116107f000000000000000000000000ede54d9c024ee80c85ec0a75ed2d8774c7fbac9b3033847f0000000000000000000000004200000000000000000000000000000000000006611762565b60007f000000000000000000000000f7127c505ef9bb661da4e104b01dc9aee2bf44356001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1461167c577f000000000000000000000000f7127c505ef9bb661da4e104b01dc9aee2bf443561169e565b7f00000000000000000000000042000000000000000000000000000000000000065b9050600454816001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016116cf919061216e565b602060405180830381865afa1580156116ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117109190612532565b101561175e5760405162461bcd60e51b815260206004820152601e60248201527f5374616b696e6720746f6b656e2062616c616e636520726564756365642e0000604482015260640161018c565b5050565b81156118b05773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038616016118a457306001600160a01b0385160361180757604051632e1a7d4d60e01b8152600481018390526001600160a01b03821690632e1a7d4d90602401600060405180830381600087803b1580156117df57600080fd5b505af11580156117f3573d6000803e3d6000fd5b50505050611802838383611ce5565b6118b0565b306001600160a01b0384160361189957348214611840576040516303e085f960e01b81523460048201526024810183905260440161018c565b806001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b15801561187b57600080fd5b505af115801561188f573d6000803e3d6000fd5b50505050506118b0565b611802838383611ce5565b6118b085858585611daa565b5050505050565b6001600160a01b0381166000908152600660209081526040808320815160808101835281546001600160801b03811682526001600160401b03600160801b9091048116948201859052600183015493820193909352600290910154606082015260035490929116815b81811015611a75576000818152600760209081526040808320815160a08101835281546001600160501b038082168352600160501b8204811695830195909552600160a01b90049093169183019190915260018101546060830152600201546080820152908483036119935785516119a2565b81602001516001600160501b03165b6001600160801b03169050600082604001516001600160501b03166000036119ca57426119d9565b82604001516001600160501b03165b9050600080611a06896040015185856119f2919061251f565b6119fc9190612692565b8660600151611e02565b91509150600080611a3e8c886080015189600001516001600160501b031686611a2f91906126bf565b611a3991906126bf565b611e4d565b91509150838015611a4c5750815b611a56578b611a58565b805b9b5050505050505050600181611a6e919061254b565b9050611920565b50611aaa84611aa57f0000000000000000000000000000000000000000000000000000000000000012600a6127c5565b611e02565b9450611ad990507f0000000000000000000000000000000000000000000000000000000000000012600a6127c5565b611ae390856126bf565b95945050505050565b600854811115611b395760405162461bcd60e51b81526020600482015260186024820152774e6f7420656e6f7567682072657761726420746f6b656e7360401b604482015260640161018c565b8060086000828254611b4b919061251f565b9091555061175e90507f000000000000000000000000ede54d9c024ee80c85ec0a75ed2d8774c7fbac9b3084847f0000000000000000000000004200000000000000000000000000000000000006611762565b6000611ba9826118b7565b6001600160a01b038316600090815260066020526040812060020180549293508392909190611bd990849061254b565b90915550506001600160a01b038216600090815260066020526040902080546001600160801b0319166001600160501b034216179055600354611c27906001906001600160401b03166123ea565b6001600160a01b03909216600090815260066020526040902080546001600160401b0393909316600160801b02600160801b600160c01b03199093169290921790915550565b6060600080856001600160a01b031685604051611c8a91906127d5565b600060405180830381855af49150503d8060008114611cc5576040519150601f19603f3d011682016040523d82523d6000602084013e611cca565b606091505b5091509150611cdb86838387611e68565b9695505050505050565b6000836001600160a01b03168360405160006040518083038185875af1925050503d8060008114611d32576040519150601f19603f3d011682016040523d82523d6000602084013e611d37565b606091505b5050905080610f0a57816001600160a01b031663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d7b57600080fd5b505af1158015611d8f573d6000803e3d6000fd5b50610f0a935050506001600160a01b03841690508585611ee9565b816001600160a01b0316836001600160a01b03160315610f0a57306001600160a01b03841603611ded57611de86001600160a01b0385168383611ee9565b610f0a565b610f0a6001600160a01b038516848484611f51565b60008083600003611e195750600190506000611e46565b83830283858281611e2c57611e2c6126a9565b0414611e3f576000809250925050611e46565b6001925090505b9250929050565b60008083830184811015611e3f576000809250925050611e46565b60608315611ed7578251600003611ed0576001600160a01b0385163b611ed05760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161018c565b5081611ee1565b611ee18383611f89565b949350505050565b6040516001600160a01b038316602482015260448101829052611f4c90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611fb3565b505050565b6040516001600160a01b0380851660248301528316604482015260648101829052610f0a9085906323b872dd60e01b90608401611f15565b815115611f995781518083602001fd5b8060405162461bcd60e51b815260040161018c9190612399565b6000612008826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166120859092919063ffffffff16565b805190915015611f4c578080602001905181019061202691906127f1565b611f4c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161018c565b6060611ee1848460008585600080866001600160a01b031685876040516120ac91906127d5565b60006040518083038185875af1925050503d80600081146120e9576040519150601f19603f3d011682016040523d82523d6000602084013e6120ee565b606091505b50915091506120ff87838387611e68565b979650505050505050565b6000806040838503121561211d57600080fd5b50508035926020909101359150565b60006020828403121561213e57600080fd5b81356001600160a01b03811681146114f257600080fd5b60006020828403121561216757600080fd5b5035919050565b6001600160a01b0391909116815260200190565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156121aa57600080fd5b81356001600160401b03808211156121c157600080fd5b818401915084601f8301126121d557600080fd5b8135818111156121e7576121e7612182565b604051601f8201601f19908116603f0116810190838211818310171561220f5761220f612182565b8160405282815287602084870101111561222857600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000806020838503121561225b57600080fd5b82356001600160401b038082111561227257600080fd5b818501915085601f83011261228657600080fd5b81358181111561229557600080fd5b8660208260051b85010111156122aa57600080fd5b60209290920196919550909350505050565b60005b838110156122d75781810151838201526020016122bf565b50506000910152565b600081518084526122f88160208601602086016122bc565b601f01601f19169290920160200192915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561236357603f198886030184526123518583516122e0565b94509285019290850190600101612335565b5092979650505050505050565b60006020828403121561238257600080fd5b81356001600160501b03811681146114f257600080fd5b6020815260006114f260208301846122e0565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b6001600160401b0382811682821603908082111561240a5761240a6123d4565b5092915050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261247557600080fd5b8301803591506001600160401b0382111561248f57600080fd5b602001915036819003821315611e4657600080fd5b8284823760609190911b6001600160601b0319169101908152601401919050565b600181811c908216806124d957607f821691505b6020821081036124f957634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160401b0381811683821601908082111561240a5761240a6123d4565b81810381811115610aab57610aab6123d4565b60006020828403121561254457600080fd5b5051919050565b80820180821115610aab57610aab6123d4565b601f821115611f4c576000816000526020600020601f850160051c810160208610156125875750805b601f850160051c820191505b818110156125a657828155600101612593565b505050505050565b81516001600160401b038111156125c7576125c7612182565b6125db816125d584546124c5565b8461255e565b602080601f83116001811461261057600084156125f85750858301515b600019600386901b1c1916600185901b1785556125a6565b600085815260208120601f198616915b8281101561263f57888601518255948401946001909101908401612620565b508582101561265d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60408152600061268060408301856122e0565b8281036020840152611ae381856122e0565b8082028115828204841417610aab57610aab6123d4565b634e487b7160e01b600052601260045260246000fd5b6000826126dc57634e487b7160e01b600052601260045260246000fd5b500490565b600181815b8085111561271c578160001904821115612702576127026123d4565b8085161561270f57918102915b93841c93908002906126e6565b509250929050565b60008261273357506001610aab565b8161274057506000610aab565b816001811461275657600281146127605761277c565b6001915050610aab565b60ff841115612771576127716123d4565b50506001821b610aab565b5060208310610133831016604e8410600b841016171561279f575081810a610aab565b6127a983836126e1565b80600019048211156127bd576127bd6123d4565b029392505050565b60006114f261ffff841683612724565b600082516127e78184602087016122bc565b9190910192915050565b60006020828403121561280357600080fd5b815180151581146114f257600080fdfe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122097099cb2b1d5e5462d2ed985c348aebf25c6dc2ec2040261da1ec5622de1e7ab64736f6c63430008170033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$1.49
Net Worth in ETH
0.000508
Token Allocations
WLD
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| WORLD | 100.00% | $0.468375 | 3.1858 | $1.49 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.