Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
StakingPoolToken
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.28; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "./interfaces/IDexAdapter.sol"; import "./interfaces/IInitializeSelector.sol"; import "./interfaces/IRewardsWhitelister.sol"; import "./interfaces/IProtocolFeeRouter.sol"; import "./interfaces/IStakingPoolToken.sol"; import "./TokenRewards.sol"; contract StakingPoolToken is Initializable, IInitializeSelector, IStakingPoolToken, ERC20Upgradeable, OwnableUpgradeable { using SafeERC20 for IERC20; address public override INDEX_FUND; address public override POOL_REWARDS; address public override stakeUserRestriction; address public override stakingToken; IDexAdapter public DEX_ADAPTER; IV3TwapUtilities public V3_TWAP_UTILS; modifier onlyRestricted() { require(_msgSender() == stakeUserRestriction, "R"); _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize( string memory _name, string memory _symbol, address _indexFund, address _stakeUserRestriction, bytes memory _immutables ) public initializer { __ERC20_init(_name, _symbol); __Ownable_init(_msgSender()); stakeUserRestriction = _stakeUserRestriction; INDEX_FUND = _indexFund; (,,,,, address _v3TwapUtilities, address _dexAdapter) = abi.decode(_immutables, (address, address, address, address, address, address, address)); DEX_ADAPTER = IDexAdapter(_dexAdapter); V3_TWAP_UTILS = IV3TwapUtilities(_v3TwapUtilities); } function initializeSelector() external pure override returns (bytes4) { return this.initialize.selector; } function stake(address _user, uint256 _amount) external override { require(stakingToken != address(0), "I"); if (stakeUserRestriction != address(0)) { require(_user == stakeUserRestriction, "U"); } _mint(_user, _amount); IERC20(stakingToken).safeTransferFrom(_msgSender(), address(this), _amount); emit Stake(_msgSender(), _user, _amount); } function unstake(uint256 _amount) external override { _burn(_msgSender(), _amount); IERC20(stakingToken).safeTransfer(_msgSender(), _amount); emit Unstake(_msgSender(), _amount); } function setPoolRewards(address _rewards) external onlyOwner { require(POOL_REWARDS == address(0), "I"); POOL_REWARDS = _rewards; } function setStakingToken(address _stakingToken) external onlyOwner { require(stakingToken == address(0), "S"); stakingToken = _stakingToken; } function removeStakeUserRestriction() external onlyRestricted { stakeUserRestriction = address(0); } function setStakeUserRestriction(address _user) external onlyRestricted { stakeUserRestriction = _user; } function _update(address _from, address _to, uint256 _value) internal override { super._update(_from, _to, _value); if (_from != address(0)) { TokenRewards(POOL_REWARDS).setShares(_from, _value, true); } if (_to != address(0) && _to != address(0xdead)) { TokenRewards(POOL_REWARDS).setShares(_to, _value, false); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.2.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC1363} from "../../../interfaces/IERC1363.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC-20 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 { /** * @dev An operation with an ERC-20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. * * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being * set here. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { safeTransfer(token, to, value); } else if (!token.transferAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferFromAndCallRelaxed( IERC1363 token, address from, address to, uint256 value, bytes memory data ) internal { if (to.code.length == 0) { safeTransferFrom(token, from, to, value); } else if (!token.transferFromAndCall(from, to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}. * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall} * once without retrying, and relies on the returned value to be true. * * Reverts if the returned value is other than `true`. */ function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { forceApprove(token, to, value); } else if (!token.approveAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements. */ function _callOptionalReturn(IERC20 token, bytes memory data) private { uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) // bubble errors if iszero(success) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } returnSize := returndatasize() returnValue := mload(0) } if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { bool success; uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) returnSize := returndatasize() returnValue := mload(0) } return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.2.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {ContextUpgradeable} from "../../utils/ContextUpgradeable.sol"; import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; import {Initializable} from "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC-20 * applications. */ abstract contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20, IERC20Metadata, IERC20Errors { /// @custom:storage-location erc7201:openzeppelin.storage.ERC20 struct ERC20Storage { mapping(address account => uint256) _balances; mapping(address account => mapping(address spender => uint256)) _allowances; uint256 _totalSupply; string _name; string _symbol; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC20")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00; function _getERC20Storage() private pure returns (ERC20Storage storage $) { assembly { $.slot := ERC20StorageLocation } } /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing { __ERC20_init_unchained(name_, symbol_); } function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing { ERC20Storage storage $ = _getERC20Storage(); $._name = name_; $._symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { ERC20Storage storage $ = _getERC20Storage(); return $._name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { ERC20Storage storage $ = _getERC20Storage(); return $._symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Skips emitting an {Approval} event indicating an allowance update. This is not * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { ERC20Storage storage $ = _getERC20Storage(); if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows $._totalSupply += value; } else { uint256 fromBalance = $._balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. $._balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. $._totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. $._balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * * ```solidity * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { ERC20Storage storage $ = _getERC20Storage(); if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } $._allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance < type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; interface IDexAdapter { function ASYNC_INITIALIZE() external view returns (bool); function V2_ROUTER() external view returns (address); function V3_ROUTER() external view returns (address); function WETH() external view returns (address); function getV3Pool(address _token0, address _token1, int24 _tickSpacing) external view returns (address _pool); function getV3Pool(address _token0, address _token1, uint24 _poolFee) external view returns (address _pool); function getV2Pool(address _token0, address _token1) external view returns (address _pool); function createV2Pool(address _token0, address _token1) external returns (address _pool); function getReserves(address _pool) external view returns (uint112, uint112); function swapV2Single( address _tokenIn, address _tokenOut, uint256 _amountIn, uint256 _amountOutMin, address _recipient ) external returns (uint256 _amountOut); function swapV2SingleExactOut( address _tokenIn, address _tokenOut, uint256 _amountInMax, uint256 _amountOut, address _recipient ) external returns (uint256 _amountInUsed); function swapV3Single( address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMin, address _recipient ) external returns (uint256 _amountOut); function addLiquidity( address tokenA, address tokenB, uint256 amountADesired, uint256 amountBDesired, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external; function removeLiquidity( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; interface IInitializeSelector { function initializeSelector() external view returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; interface IRewardsWhitelister { event PauseToken(address indexed token, bool isPaused); event SetWhitelistFromDebondFees(address addy, bool isWhitelisted); event ToggleToken(address indexed token, bool isWhitelisted); function isWhitelistedFromDebondFee(address addy) external view returns (bool); function paused(address token) external view returns (bool); function whitelist(address token) external view returns (bool); function getFullWhitelist() external view returns (address[] memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import "./IProtocolFees.sol"; interface IProtocolFeeRouter { function protocolFees() external view returns (IProtocolFees); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; interface IStakingPoolToken { event Stake(address indexed executor, address indexed user, uint256 amount); event Unstake(address indexed user, uint256 amount); function INDEX_FUND() external view returns (address); function POOL_REWARDS() external view returns (address); function stakingToken() external view returns (address); function stakeUserRestriction() external view returns (address); function stake(address user, uint256 amount) external; function unstake(uint256 amount) external; function setPoolRewards(address poolRewards) external; function setStakingToken(address stakingToken) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.28; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@uniswap/v3-core/contracts/libraries/FixedPoint96.sol"; import "./interfaces/IDecentralizedIndex.sol"; import "./interfaces/IDexAdapter.sol"; import "./interfaces/IInitializeSelector.sol"; import "./interfaces/IPEAS.sol"; import "./interfaces/IRewardsWhitelister.sol"; import "./interfaces/IProtocolFees.sol"; import "./interfaces/IProtocolFeeRouter.sol"; import "./interfaces/ITokenRewards.sol"; import "./interfaces/IV3TwapUtilities.sol"; contract TokenRewards is Initializable, IInitializeSelector, ContextUpgradeable, ITokenRewards { using SafeERC20 for IERC20; uint256 constant PRECISION = 10 ** 27; uint256 constant REWARDS_SWAP_SLIPPAGE = 20; // 2% uint24 constant REWARDS_POOL_FEE = 10000; // 1% int24 constant REWARDS_TICK_SPACING = 200; uint256 REWARDS_SWAP_OVERRIDE_MIN; address INDEX_FUND; address PAIRED_LP_TOKEN; bool LEAVE_AS_PAIRED_LP_TOKEN; IProtocolFeeRouter PROTOCOL_FEE_ROUTER; IRewardsWhitelister REWARDS_WHITELISTER; IDexAdapter DEX_ADAPTER; IV3TwapUtilities V3_TWAP_UTILS; struct Reward { uint256 excluded; uint256 realized; } address public override trackingToken; address public override rewardsToken; uint256 public override totalShares; uint256 public override totalStakers; mapping(address => uint256) public shares; mapping(address => mapping(address => Reward)) public rewards; uint256 _rewardsSwapAmountInOverride; mapping(address => uint256) _rewardsPerShare; mapping(address => uint256) public rewardsDistributed; mapping(address => uint256) public rewardsDeposited; address[] _allRewardsTokens; mapping(address => bool) _depositedRewardsToken; /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize(address _indexFund, address _trackingToken, bool _leaveAsPaired, bytes memory _immutables) public initializer { __Context_init(); ( address _pairedLpToken, address _lpRewardsToken, , address _feeRouter, address _rewardsWhitelist, address _v3TwapUtilities, address _dexAdapter ) = abi.decode(_immutables, (address, address, address, address, address, address, address)); PROTOCOL_FEE_ROUTER = IProtocolFeeRouter(_feeRouter); REWARDS_WHITELISTER = IRewardsWhitelister(_rewardsWhitelist); DEX_ADAPTER = IDexAdapter(_dexAdapter); V3_TWAP_UTILS = IV3TwapUtilities(_v3TwapUtilities); INDEX_FUND = _indexFund; PAIRED_LP_TOKEN = _pairedLpToken; LEAVE_AS_PAIRED_LP_TOKEN = _leaveAsPaired; trackingToken = _trackingToken; rewardsToken = _lpRewardsToken; // Setup min swap to be small amount of paired LP token to prevent DOS attemps uint8 _pd = IERC20Metadata(_pairedLpToken).decimals(); uint256 _minSwap = 10 ** (_pd / 2); REWARDS_SWAP_OVERRIDE_MIN = _minSwap == 0 ? 10 ** _pd : _minSwap; } function initializeSelector() external pure override returns (bytes4) { return this.initialize.selector; } function setShares(address _wallet, uint256 _amount, bool _sharesRemoving) external override { require(_msgSender() == trackingToken, "UNAUTHORIZED"); _setShares(_wallet, _amount, _sharesRemoving); } function _setShares(address _wallet, uint256 _amount, bool _sharesRemoving) internal { _processFeesIfApplicable(); if (_sharesRemoving) { _removeShares(_wallet, _amount); emit RemoveShares(_wallet, _amount); } else { _addShares(_wallet, _amount); emit AddShares(_wallet, _amount); } } function _addShares(address _wallet, uint256 _amount) internal { if (shares[_wallet] > 0) { _distributeReward(_wallet); } uint256 sharesBefore = shares[_wallet]; totalShares += _amount; shares[_wallet] += _amount; if (sharesBefore == 0 && shares[_wallet] > 0) { totalStakers++; } _resetExcluded(_wallet); } function _removeShares(address _wallet, uint256 _amount) internal { require(shares[_wallet] > 0 && _amount <= shares[_wallet], "RE"); _distributeReward(_wallet); totalShares -= _amount; shares[_wallet] -= _amount; if (shares[_wallet] == 0) { totalStakers--; } _resetExcluded(_wallet); } function _processFeesIfApplicable() internal { IDecentralizedIndex(INDEX_FUND).processPreSwapFeesAndSwap(); } function depositFromPairedLpToken(uint256 _amountTknDepositing) public override { require(PAIRED_LP_TOKEN != rewardsToken, "R"); if (_amountTknDepositing > 0) { IERC20(PAIRED_LP_TOKEN).safeTransferFrom(_msgSender(), address(this), _amountTknDepositing); } uint256 _unclaimedPairedLpTkns = rewardsDeposited[PAIRED_LP_TOKEN] - rewardsDistributed[PAIRED_LP_TOKEN]; uint256 _amountTkn = IERC20(PAIRED_LP_TOKEN).balanceOf(address(this)) - _unclaimedPairedLpTkns; require(_amountTkn > 0, "A"); uint256 _adminAmt = _getAdminFeeFromAmount(_amountTkn); _amountTkn -= _adminAmt; if (LEAVE_AS_PAIRED_LP_TOKEN) { (, uint256 _yieldBurnFee) = _getYieldFees(); uint256 _burnAmount = (_amountTkn * _yieldBurnFee) / PROTOCOL_FEE_ROUTER.protocolFees().DEN(); _adminAmt += _burnAmount; _amountTkn -= _burnAmount; if (_adminAmt > 0) { _processAdminFee(_adminAmt); } _depositRewards(PAIRED_LP_TOKEN, _amountTkn); return; } (address _token0, address _token1) = PAIRED_LP_TOKEN < rewardsToken ? (PAIRED_LP_TOKEN, rewardsToken) : (rewardsToken, PAIRED_LP_TOKEN); address _pool; try DEX_ADAPTER.getV3Pool(_token0, _token1, REWARDS_POOL_FEE) returns (address __pool) { _pool = __pool; } catch { _pool = DEX_ADAPTER.getV3Pool(_token0, _token1, REWARDS_TICK_SPACING); } uint160 _rewardsSqrtPriceX96 = V3_TWAP_UTILS.sqrtPriceX96FromPoolAndInterval(_pool); uint256 _rewardsPriceX96 = V3_TWAP_UTILS.priceX96FromSqrtPriceX96(_rewardsSqrtPriceX96); uint256 _amountOut = _token0 == PAIRED_LP_TOKEN ? (_rewardsPriceX96 * _amountTkn) / FixedPoint96.Q96 : (_amountTkn * FixedPoint96.Q96) / _rewardsPriceX96; _swapForRewards(_amountTkn, _amountOut, _adminAmt); } function depositRewards(address _token, uint256 _amount) external override { _depositRewardsFromToken(_msgSender(), _token, _amount, true); } function depositRewardsNoTransfer(address _token, uint256 _amount) external override { require(_msgSender() == INDEX_FUND, "AUTH"); _depositRewardsFromToken(_msgSender(), _token, _amount, false); } function _depositRewardsFromToken(address _user, address _token, uint256 _amount, bool _shouldTransfer) internal { require(_amount > 0, "A"); require(_isValidRewardsToken(_token), "V"); uint256 _finalAmt = _amount; if (_shouldTransfer) { uint256 _balBefore = IERC20(_token).balanceOf(address(this)); IERC20(_token).safeTransferFrom(_user, address(this), _finalAmt); _finalAmt = IERC20(_token).balanceOf(address(this)) - _balBefore; } uint256 _adminAmt = _getAdminFeeFromAmount(_finalAmt); if (_adminAmt > 0) { IERC20(_token).safeTransfer(OwnableUpgradeable(address(V3_TWAP_UTILS)).owner(), _adminAmt); _finalAmt -= _adminAmt; } _depositRewards(_token, _finalAmt); } function _depositRewards(address _token, uint256 _amountTotal) internal { if (_amountTotal == 0) { return; } if (!_depositedRewardsToken[_token]) { _depositedRewardsToken[_token] = true; _allRewardsTokens.push(_token); } if (totalShares == 0) { _burnRewards(_token, _amountTotal); return; } uint256 _depositAmount = _amountTotal; if (_token == rewardsToken) { (, uint256 _yieldBurnFee) = _getYieldFees(); if (_yieldBurnFee > 0) { uint256 _burnAmount = (_amountTotal * _yieldBurnFee) / PROTOCOL_FEE_ROUTER.protocolFees().DEN(); if (_burnAmount > 0) { _burnRewards(rewardsToken, _burnAmount); _depositAmount -= _burnAmount; } } } rewardsDeposited[_token] += _depositAmount; _rewardsPerShare[_token] += (PRECISION * _depositAmount) / totalShares; emit DepositRewards(_msgSender(), _token, _depositAmount); } function _distributeReward(address _wallet) internal { if (shares[_wallet] == 0) { return; } for (uint256 _i; _i < _allRewardsTokens.length; _i++) { address _token = _allRewardsTokens[_i]; if (REWARDS_WHITELISTER.paused(_token)) { continue; } uint256 _amount = getUnpaid(_token, _wallet); rewards[_token][_wallet].realized += _amount; rewards[_token][_wallet].excluded = _cumulativeRewards(_token, shares[_wallet], true); if (_amount > 0) { rewardsDistributed[_token] += _amount; IERC20(_token).safeTransfer(_wallet, _amount); emit DistributeReward(_wallet, _token, _amount); } } } function _resetExcluded(address _wallet) internal { for (uint256 _i; _i < _allRewardsTokens.length; _i++) { address _token = _allRewardsTokens[_i]; rewards[_token][_wallet].excluded = _cumulativeRewards(_token, shares[_wallet], true); } } function _burnRewards(address _token, uint256 _burnAmount) internal { try IPEAS(_token).burn(_burnAmount) {} catch { IERC20(_token).safeTransfer(OwnableUpgradeable(address(V3_TWAP_UTILS)).owner(), _burnAmount); } } function _isValidRewardsToken(address _token) internal view returns (bool) { return _token == rewardsToken || REWARDS_WHITELISTER.whitelist(_token); } function _getAdminFeeFromAmount(uint256 _amount) internal view returns (uint256) { (uint256 _yieldAdminFee,) = _getYieldFees(); if (_yieldAdminFee == 0) { return 0; } return (_amount * _yieldAdminFee) / PROTOCOL_FEE_ROUTER.protocolFees().DEN(); } function _getYieldFees() internal view returns (uint256 _admin, uint256 _burn) { IProtocolFees _fees = PROTOCOL_FEE_ROUTER.protocolFees(); if (address(_fees) != address(0)) { _admin = _fees.yieldAdmin(); _burn = _fees.yieldBurn(); } } function _swapForRewards(uint256 _amountIn, uint256 _amountOut, uint256 _adminAmt) internal { if (_rewardsSwapAmountInOverride > 0) { _adminAmt = (_adminAmt * _rewardsSwapAmountInOverride) / _amountIn; _amountOut = (_amountOut * _rewardsSwapAmountInOverride) / _amountIn; _amountIn = _rewardsSwapAmountInOverride; } uint256 _balBefore = IERC20(rewardsToken).balanceOf(address(this)); IERC20(PAIRED_LP_TOKEN).safeIncreaseAllowance(address(DEX_ADAPTER), _amountIn); try DEX_ADAPTER.swapV3Single( PAIRED_LP_TOKEN, rewardsToken, REWARDS_POOL_FEE, _amountIn, _amountIn == REWARDS_SWAP_OVERRIDE_MIN ? 0 : (_amountOut * (1000 - REWARDS_SWAP_SLIPPAGE)) / 1000, address(this) ) { _rewardsSwapAmountInOverride = 0; if (_adminAmt > 0) { _processAdminFee(_adminAmt); } _depositRewards(rewardsToken, IERC20(rewardsToken).balanceOf(address(this)) - _balBefore); } catch { _rewardsSwapAmountInOverride = _amountIn / 2 < REWARDS_SWAP_OVERRIDE_MIN ? REWARDS_SWAP_OVERRIDE_MIN : _amountIn / 2; IERC20(PAIRED_LP_TOKEN).safeDecreaseAllowance(address(DEX_ADAPTER), _amountIn); emit RewardSwapError(_amountIn); } } function _processAdminFee(uint256 _amount) internal { IERC20(PAIRED_LP_TOKEN).safeTransfer(OwnableUpgradeable(address(V3_TWAP_UTILS)).owner(), _amount); } function claimReward(address _wallet) external override { _processFeesIfApplicable(); _distributeReward(_wallet); emit ClaimReward(_wallet); } function getAllRewardsTokens() external view override returns (address[] memory) { return _allRewardsTokens; } function getUnpaid(address _token, address _wallet) public view returns (uint256) { if (shares[_wallet] == 0) { return 0; } uint256 earnedRewards = _cumulativeRewards(_token, shares[_wallet], false); uint256 rewardsExcluded = rewards[_token][_wallet].excluded; if (earnedRewards <= rewardsExcluded) { return 0; } return earnedRewards - rewardsExcluded; } function _cumulativeRewards(address _token, uint256 _share, bool _roundUp) internal view returns (uint256 _r) { _r = (_share * _rewardsPerShare[_token]) / PRECISION; if (_roundUp && (_share * _rewardsPerShare[_token]) % PRECISION > 0) { _r = _r + 1; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC165} from "./IERC165.sol"; /** * @title IERC1363 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. * * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction. */ interface IERC1363 is IERC20, IERC165 { /* * Note: the ERC-165 identifier for this interface is 0xb0202a11. * 0xb0202a11 === * bytes4(keccak256('transferAndCall(address,uint256)')) ^ * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^ * bytes4(keccak256('approveAndCall(address,uint256)')) ^ * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) */ /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @param data Additional data with no specified format, sent in call to `spender`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC-20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC-20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC-721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC-1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; interface IProtocolFees { event SetYieldAdmin(uint256 newFee); event SetYieldBurn(uint256 newFee); function DEN() external view returns (uint256); function yieldAdmin() external view returns (uint256); function yieldBurn() external view returns (uint256); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.4.0; /// @title FixedPoint96 /// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format) /// @dev Used in SqrtPriceMath.sol library FixedPoint96 { uint8 internal constant RESOLUTION = 96; uint256 internal constant Q96 = 0x1000000000000000000000000; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./IDexAdapter.sol"; interface IDecentralizedIndex is IERC20 { enum IndexType { WEIGHTED, UNWEIGHTED } struct Config { address partner; uint256 debondCooldown; bool hasTransferTax; bool blacklistTKNpTKNPoolV2; // DEPRECATED: we should remove this in future versions } // all fees: 1 == 0.01%, 10 == 0.1%, 100 == 1% struct Fees { uint16 burn; uint16 bond; uint16 debond; uint16 buy; uint16 sell; uint16 partner; } struct IndexAssetInfo { address token; uint256 weighting; uint256 basePriceUSDX96; address c1; // arbitrary contract/address field we can use for an index uint256 q1; // arbitrary quantity/number field we can use for an index } /// @notice The ```Create``` event fires when a new decentralized index has been created /// @param newIdx The CA of the new index contract /// @param wallet The creator of the new index event Create(address indexed newIdx, address indexed wallet); /// @notice The ```FlashLoan``` event fires when someone flash loans assets from the pod /// @param executor The sender of the request /// @param recipient The recipient of the flashed funds /// @param token The token being flash loaned /// @param amount The amount of token to flash loan event FlashLoan(address indexed executor, address indexed recipient, address token, uint256 amount); /// @notice The ```FlashMint``` event fires when someone flash mints pTKN from the pod /// @param executor The sender of the request /// @param recipient The recipient of the flashed funds /// @param amount The amount of pTKN to flash mint event FlashMint(address indexed executor, address indexed recipient, uint256 amount); /// @notice The ```Initialize``` event fires when the new pod has been initialized, /// @notice which is at creation on some and in another txn for others (gas limits) /// @param wallet The wallet that initialized /// @param v2Pool The new UniV2 derivative pool that was created at initialization event Initialize(address indexed wallet, address v2Pool); /// @notice The ```Bond``` event fires when someone wraps into the pod which mints new pod tokens /// @param wallet The wallet that wrapped /// @param token The token that was used as a ref to wrap into, representing an underlying tkn /// @param amountTokensBonded Amount of underlying tkns used to wrap/bond /// @param amountTokensMinted Amount of new pod tokens (pTKN) minted event Bond(address indexed wallet, address indexed token, uint256 amountTokensBonded, uint256 amountTokensMinted); /// @notice The ```Debond``` event fires when someone unwraps from a pod and redeems underlying tkn(s) /// @param wallet The wallet that unwrapped/debond /// @param amountDebonded Amount of pTKNs burned/unwrapped event Debond(address indexed wallet, uint256 amountDebonded); /// @notice The ```AddLiquidity``` event fires when new liquidity (LP) for a pod is added /// @param wallet The wallet that added LP /// @param amountTokens Amount of pTKNs used for LP /// @param amountDAI Amount of pairedLpAsset used for LP event AddLiquidity(address indexed wallet, uint256 amountTokens, uint256 amountDAI); /// @notice The ```RemoveLiquidity``` event fires when LP is removed for a pod /// @param wallet The wallet that removed LP /// @param amountLiquidity Amount of liquidity removed event RemoveLiquidity(address indexed wallet, uint256 amountLiquidity); event SetPartner(address indexed wallet, address newPartner); event SetPartnerFee(address indexed wallet, uint16 newFee); function BOND_FEE() external view returns (uint16); function DEBOND_FEE() external view returns (uint16); function DEX_HANDLER() external view returns (IDexAdapter); function FLASH_FEE_AMOUNT_DAI() external view returns (uint256); function PAIRED_LP_TOKEN() external view returns (address); function config() external view returns (Config calldata); function fees() external view returns (Fees calldata); function unlocked() external view returns (uint8); function isFlashMinting() external view returns (uint8); function indexType() external view returns (IndexType); function created() external view returns (uint256); function lpStakingPool() external view returns (address); function lpRewardsToken() external view returns (address); function isAsset(address token) external view returns (bool); function getAllAssets() external view returns (IndexAssetInfo[] memory); function getInitialAmount(address sToken, uint256 sAmount, address tToken) external view returns (uint256); function processPreSwapFeesAndSwap() external; function totalAssets() external view returns (uint256 totalManagedAssets); function totalAssets(address asset) external view returns (uint256 totalManagedAssets); function convertToShares(uint256 assets) external view returns (uint256 shares); function convertToAssets(uint256 shares) external view returns (uint256 assets); function convertToAssetsPreFlashMint(uint256 shares) external view returns (uint256 assets); function setup() external; function bond(address token, uint256 amount, uint256 amountMintMin) external; function debond(uint256 amount, address[] memory token, uint8[] memory percentage) external; function addLiquidityV2(uint256 idxTokens, uint256 daiTokens, uint256 slippage, uint256 deadline) external returns (uint256); function removeLiquidityV2(uint256 lpTokens, uint256 minTokens, uint256 minDAI, uint256 deadline) external; function flash(address recipient, address token, uint256 amount, bytes calldata data) external; function flashMint(address recipient, uint256 amount, bytes calldata data) external; function setLpStakingPool(address lpStakingPool) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IPEAS is IERC20 { event Burn(address indexed user, uint256 amount); function burn(uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; interface ITokenRewards { event AddShares(address indexed wallet, uint256 amount); event RemoveShares(address indexed wallet, uint256 amount); event ClaimReward(address indexed wallet); event DistributeReward(address indexed wallet, address indexed token, uint256 amount); event DepositRewards(address indexed wallet, address indexed token, uint256 amount); event RewardSwapError(uint256 amountIn); function totalShares() external view returns (uint256); function totalStakers() external view returns (uint256); function rewardsToken() external view returns (address); function trackingToken() external view returns (address); function depositFromPairedLpToken(uint256 amount) external; function depositRewards(address token, uint256 amount) external; function depositRewardsNoTransfer(address token, uint256 amount) external; function claimReward(address wallet) external; function getAllRewardsTokens() external view returns (address[] memory); function setShares(address wallet, uint256 amount, bool sharesRemoving) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; interface IV3TwapUtilities { function getV3Pool(address v3Factory, address token0, address token1) external view returns (address); function getV3Pool(address v3Factory, address token0, address token1, uint24 poolFee) external view returns (address); function getV3Pool(address v3Factory, address token0, address token1, int24 tickSpacing) external view returns (address); function getPoolPriceUSDX96(address pricePool, address nativeStablePool, address WETH9) external view returns (uint256); function sqrtPriceX96FromPoolAndInterval(address pool) external view returns (uint160); function sqrtPriceX96FromPoolAndPassedInterval(address pool, uint32 interval) external view returns (uint160); function priceX96FromSqrtPriceX96(uint160 sqrtPriceX96) external pure returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "remappings": [ "@chainlink/=node_modules/@chainlink/", "@fraxlend/=test/invariant/modules/fraxlend/", "fuzzlib/=lib/fuzzlib/src/", "swap-router/=test/invariant/modules/v3-periphery/swapRouter/", "v3-core/=test/invariant/modules/v3-core/", "v3-periphery/=test/invariant/modules/v3-periphery/", "v2-core/=test/invariant/modules/uniswap-v2/v2-core/contracts/", "v2-periphery/=test/invariant/modules/uniswap-v2/v2-periphery/contracts/", "uniswap-v2/=test/invariant/modules/uniswap-v2/", "solidity-bytes-utils/contracts/=test/invariant/modules/fraxlend/libraries/", "@rari-capital/solmate/=node_modules/solmate/", "@arbitrum/=node_modules/@arbitrum/", "@ensdomains/=node_modules/@ensdomains/", "@eth-optimism/=node_modules/@eth-optimism/", "@ethereum-waffle/=node_modules/@ethereum-waffle/", "@mean-finance/=node_modules/@mean-finance/", "@offchainlabs/=node_modules/@offchainlabs/", "@openzeppelin/=node_modules/@openzeppelin/", "@scroll-tech/=node_modules/@scroll-tech/", "@uniswap/=node_modules/@uniswap/", "@zksync/=node_modules/@zksync/", "base64-sol/=node_modules/base64-sol/", "ds-test/=lib/fuzzlib/lib/forge-std/lib/ds-test/src/", "erc721a/=node_modules/erc721a/", "eth-gas-reporter/=node_modules/eth-gas-reporter/", "forge-std/=lib/forge-std/src/", "hardhat/=node_modules/hardhat/", "solidity-code-metrics/=node_modules/solidity-code-metrics/", "solmate/=node_modules/solmate/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"executor","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unstake","type":"event"},{"inputs":[],"name":"DEX_ADAPTER","outputs":[{"internalType":"contract IDexAdapter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INDEX_FUND","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL_REWARDS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"V3_TWAP_UTILS","outputs":[{"internalType":"contract IV3TwapUtilities","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_indexFund","type":"address"},{"internalType":"address","name":"_stakeUserRestriction","type":"address"},{"internalType":"bytes","name":"_immutables","type":"bytes"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initializeSelector","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"removeStakeUserRestriction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rewards","type":"address"}],"name":"setPoolRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"setStakeUserRestriction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_stakingToken","type":"address"}],"name":"setStakingToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakeUserRestriction","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080604052348015600f57600080fd5b506016601a565b60ca565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560695760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c75780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b611699806100d96000396000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c8063a9059cbb116100de578063dba802d911610097578063effe0e1c11610071578063effe0e1c146103a5578063f191c16a146103b8578063f2fde38b146103cb578063f5996fe4146103de57600080fd5b8063dba802d91461036c578063dd62ed3e1461037f578063e8a2e34c1461039257600080fd5b8063a9059cbb14610305578063aa9aa14414610318578063adc9772e1461032b578063c3371efd1461033e578063c56e0ad814610351578063da0e1dab1461035957600080fd5b8063313ce5671161014b57806372f702f31161012557806372f702f31461028d578063871071d6146102b85780638da5cb5b146102cd57806395d89b41146102fd57600080fd5b8063313ce5671461024057806370a082311461024f578063715018a61461028557600080fd5b806306fdde0314610193578063095ea7b3146101b157806318160ddd146101d45780631e9b12ef1461020557806323b872dd1461021a5780632e17de781461022d575b600080fd5b61019b6103f1565b6040516101a89190611182565b60405180910390f35b6101c46101bf3660046111e5565b6104b4565b60405190151581526020016101a8565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b6040519081526020016101a8565b610218610213366004611211565b6104ce565b005b6101c4610228366004611235565b61053a565b61021861023b366004611276565b61055e565b604051601281526020016101a8565b6101f761025d366004611211565b6001600160a01b03166000908152600080516020611644833981519152602052604090205490565b6102186105b7565b6003546102a0906001600160a01b031681565b6040516001600160a01b0390911681526020016101a8565b604051633bff838760e21b81526020016101a8565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03166102a0565b61019b6105cb565b6101c46103133660046111e5565b61060a565b6000546102a0906001600160a01b031681565b6102186103393660046111e5565b610618565b6004546102a0906001600160a01b031681565b61021861070c565b6002546102a0906001600160a01b031681565b61021861037a366004611211565b610765565b6101f761038d36600461128f565b6107ce565b6102186103a0366004611211565b610818565b6102186103b3366004611378565b61087f565b6005546102a0906001600160a01b031681565b6102186103d9366004611211565b610a19565b6001546102a0906001600160a01b031681565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0380546060916000805160206116448339815191529161043090611446565b80601f016020809104026020016040519081016040528092919081815260200182805461045c90611446565b80156104a95780601f1061047e576101008083540402835291602001916104a9565b820191906000526020600020905b81548152906001019060200180831161048c57829003601f168201915b505050505091505090565b6000336104c2818585610a57565b60019150505b92915050565b6104d6610a69565b6003546001600160a01b0316156105185760405162461bcd60e51b81526020600482015260016024820152605360f81b60448201526064015b60405180910390fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b600033610548858285610ac4565b610553858585610b2b565b506001949350505050565b6105683382610b8a565b61057f336003546001600160a01b03169083610bc4565b60405181815233907f85082129d87b2fe11527cb1b3b7a520aeb5aa6913f88a3d8757fe40d1db02fdd9060200160405180910390a250565b6105bf610a69565b6105c96000610c23565b565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0480546060916000805160206116448339815191529161043090611446565b6000336104c2818585610b2b565b6003546001600160a01b03166106545760405162461bcd60e51b81526020600482015260016024820152604960f81b604482015260640161050f565b6002546001600160a01b0316156106a6576002546001600160a01b038381169116146106a65760405162461bcd60e51b81526020600482015260016024820152605560f81b604482015260640161050f565b6106b08282610c94565b6106c8336003546001600160a01b0316903084610cca565b6040518181526001600160a01b0383169033907f99039fcf0a98f484616c5196ee8b2ecfa971babf0b519848289ea4db381f85f79060200160405180910390a35050565b6002546001600160a01b0316336001600160a01b0316146107535760405162461bcd60e51b81526020600482015260016024820152602960f91b604482015260640161050f565b600280546001600160a01b0319169055565b6002546001600160a01b0316336001600160a01b0316146107ac5760405162461bcd60e51b81526020600482015260016024820152602960f91b604482015260640161050f565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0391821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b610820610a69565b6001546001600160a01b03161561085d5760405162461bcd60e51b81526020600482015260016024820152604960f81b604482015260640161050f565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156108c55750825b905060008267ffffffffffffffff1660011480156108e25750303b155b9050811580156108f0575080155b1561090e5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561093857845460ff60401b1916600160401b1785555b6109428a8a610d03565b61094b33610d15565b600280546001600160a01b03808a166001600160a01b03199283161790925560008054928b1692909116919091178155865181906109929089016020908101908a01611480565b600480546001600160a01b039283166001600160a01b03199182161790915560058054929093169116179055505088159450610a0d935050505057845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050505050565b610a21610a69565b6001600160a01b038116610a4b57604051631e4fbdf760e01b81526000600482015260240161050f565b610a5481610c23565b50565b610a648383836001610d26565b505050565b33610a9b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146105c95760405163118cdaa760e01b815233600482015260240161050f565b6000610ad084846107ce565b9050600019811015610b255781811015610b1657604051637dc7a0d960e11b81526001600160a01b0384166004820152602481018290526044810183905260640161050f565b610b2584848484036000610d26565b50505050565b6001600160a01b038316610b5557604051634b637e8f60e11b81526000600482015260240161050f565b6001600160a01b038216610b7f5760405163ec442f0560e01b81526000600482015260240161050f565b610a64838383610e0e565b6001600160a01b038216610bb457604051634b637e8f60e11b81526000600482015260240161050f565b610bc082600083610e0e565b5050565b6040516001600160a01b03838116602483015260448201839052610a6491859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050610f31565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6001600160a01b038216610cbe5760405163ec442f0560e01b81526000600482015260240161050f565b610bc060008383610e0e565b6040516001600160a01b038481166024830152838116604483015260648201839052610b259186918216906323b872dd90608401610bf1565b610d0b610fa2565b610bc08282610feb565b610d1d610fa2565b610a548161103c565b6000805160206116448339815191526001600160a01b038516610d5f5760405163e602df0560e01b81526000600482015260240161050f565b6001600160a01b038416610d8957604051634a1406b160e11b81526000600482015260240161050f565b6001600160a01b03808616600090815260018301602090815260408083209388168352929052208390558115610e0757836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92585604051610dfe91815260200190565b60405180910390a35b5050505050565b610e19838383611044565b6001600160a01b03831615610e97576001805460405163d6460b4b60e01b81526001600160a01b03868116600483015260248201859052604482019390935291169063d6460b4b90606401600060405180830381600087803b158015610e7e57600080fd5b505af1158015610e92573d6000803e3d6000fd5b505050505b6001600160a01b03821615801590610eba57506001600160a01b03821661dead14155b15610a645760015460405163d6460b4b60e01b81526001600160a01b03848116600483015260248201849052600060448301529091169063d6460b4b90606401600060405180830381600087803b158015610f1457600080fd5b505af1158015610f28573d6000803e3d6000fd5b50505050505050565b600080602060008451602086016000885af180610f54576040513d6000823e3d81fd5b50506000513d91508115610f6c578060011415610f79565b6001600160a01b0384163b155b15610b2557604051635274afe760e01b81526001600160a01b038516600482015260240161050f565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166105c957604051631afcd79f60e31b815260040160405180910390fd5b610ff3610fa2565b6000805160206116448339815191527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0361102d8482611563565b5060048101610b258382611563565b610a21610fa2565b6000805160206116448339815191526001600160a01b03841661108057818160020160008282546110759190611622565b909155506110f29050565b6001600160a01b038416600090815260208290526040902054828110156110d35760405163391434e360e21b81526001600160a01b0386166004820152602481018290526044810184905260640161050f565b6001600160a01b03851660009081526020839052604090209083900390555b6001600160a01b03831661111057600281018054839003905561112f565b6001600160a01b03831660009081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161117491815260200190565b60405180910390a350505050565b602081526000825180602084015260005b818110156111b05760208186018101516040868401015201611193565b506000604082850101526040601f19601f83011684010191505092915050565b6001600160a01b0381168114610a5457600080fd5b600080604083850312156111f857600080fd5b8235611203816111d0565b946020939093013593505050565b60006020828403121561122357600080fd5b813561122e816111d0565b9392505050565b60008060006060848603121561124a57600080fd5b8335611255816111d0565b92506020840135611265816111d0565b929592945050506040919091013590565b60006020828403121561128857600080fd5b5035919050565b600080604083850312156112a257600080fd5b82356112ad816111d0565b915060208301356112bd816111d0565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60008067ffffffffffffffff8411156112f9576112f96112c8565b50604051601f19601f85018116603f0116810181811067ffffffffffffffff82111715611328576113286112c8565b60405283815290508082840185101561134057600080fd5b83836020830137600060208583010152509392505050565b600082601f83011261136957600080fd5b61122e838335602085016112de565b600080600080600060a0868803121561139057600080fd5b853567ffffffffffffffff8111156113a757600080fd5b6113b388828901611358565b955050602086013567ffffffffffffffff8111156113d057600080fd5b6113dc88828901611358565b94505060408601356113ed816111d0565b925060608601356113fd816111d0565b9150608086013567ffffffffffffffff81111561141957600080fd5b8601601f8101881361142a57600080fd5b611439888235602084016112de565b9150509295509295909350565b600181811c9082168061145a57607f821691505b60208210810361147a57634e487b7160e01b600052602260045260246000fd5b50919050565b600080600080600080600060e0888a03121561149b57600080fd5b87516114a6816111d0565b60208901519097506114b7816111d0565b60408901519096506114c8816111d0565b60608901519095506114d9816111d0565b60808901519094506114ea816111d0565b60a08901519093506114fb816111d0565b60c089015190925061150c816111d0565b8091505092959891949750929550565b601f821115610a6457806000526020600020601f840160051c810160208510156115435750805b601f840160051c820191505b81811015610e07576000815560010161154f565b815167ffffffffffffffff81111561157d5761157d6112c8565b6115918161158b8454611446565b8461151c565b6020601f8211600181146115c557600083156115ad5750848201515b600019600385901b1c1916600184901b178455610e07565b600084815260208120601f198516915b828110156115f557878501518255602094850194600190920191016115d5565b50848210156116135786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b808201808211156104c857634e487b7160e01b600052601160045260246000fdfe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00a26469706673582212200793bf109c721c59365d702ad1654efb58adfa2955fbf510f17cf72b27a16a8064736f6c634300081c0033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061018e5760003560e01c8063a9059cbb116100de578063dba802d911610097578063effe0e1c11610071578063effe0e1c146103a5578063f191c16a146103b8578063f2fde38b146103cb578063f5996fe4146103de57600080fd5b8063dba802d91461036c578063dd62ed3e1461037f578063e8a2e34c1461039257600080fd5b8063a9059cbb14610305578063aa9aa14414610318578063adc9772e1461032b578063c3371efd1461033e578063c56e0ad814610351578063da0e1dab1461035957600080fd5b8063313ce5671161014b57806372f702f31161012557806372f702f31461028d578063871071d6146102b85780638da5cb5b146102cd57806395d89b41146102fd57600080fd5b8063313ce5671461024057806370a082311461024f578063715018a61461028557600080fd5b806306fdde0314610193578063095ea7b3146101b157806318160ddd146101d45780631e9b12ef1461020557806323b872dd1461021a5780632e17de781461022d575b600080fd5b61019b6103f1565b6040516101a89190611182565b60405180910390f35b6101c46101bf3660046111e5565b6104b4565b60405190151581526020016101a8565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b6040519081526020016101a8565b610218610213366004611211565b6104ce565b005b6101c4610228366004611235565b61053a565b61021861023b366004611276565b61055e565b604051601281526020016101a8565b6101f761025d366004611211565b6001600160a01b03166000908152600080516020611644833981519152602052604090205490565b6102186105b7565b6003546102a0906001600160a01b031681565b6040516001600160a01b0390911681526020016101a8565b604051633bff838760e21b81526020016101a8565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03166102a0565b61019b6105cb565b6101c46103133660046111e5565b61060a565b6000546102a0906001600160a01b031681565b6102186103393660046111e5565b610618565b6004546102a0906001600160a01b031681565b61021861070c565b6002546102a0906001600160a01b031681565b61021861037a366004611211565b610765565b6101f761038d36600461128f565b6107ce565b6102186103a0366004611211565b610818565b6102186103b3366004611378565b61087f565b6005546102a0906001600160a01b031681565b6102186103d9366004611211565b610a19565b6001546102a0906001600160a01b031681565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0380546060916000805160206116448339815191529161043090611446565b80601f016020809104026020016040519081016040528092919081815260200182805461045c90611446565b80156104a95780601f1061047e576101008083540402835291602001916104a9565b820191906000526020600020905b81548152906001019060200180831161048c57829003601f168201915b505050505091505090565b6000336104c2818585610a57565b60019150505b92915050565b6104d6610a69565b6003546001600160a01b0316156105185760405162461bcd60e51b81526020600482015260016024820152605360f81b60448201526064015b60405180910390fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b600033610548858285610ac4565b610553858585610b2b565b506001949350505050565b6105683382610b8a565b61057f336003546001600160a01b03169083610bc4565b60405181815233907f85082129d87b2fe11527cb1b3b7a520aeb5aa6913f88a3d8757fe40d1db02fdd9060200160405180910390a250565b6105bf610a69565b6105c96000610c23565b565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0480546060916000805160206116448339815191529161043090611446565b6000336104c2818585610b2b565b6003546001600160a01b03166106545760405162461bcd60e51b81526020600482015260016024820152604960f81b604482015260640161050f565b6002546001600160a01b0316156106a6576002546001600160a01b038381169116146106a65760405162461bcd60e51b81526020600482015260016024820152605560f81b604482015260640161050f565b6106b08282610c94565b6106c8336003546001600160a01b0316903084610cca565b6040518181526001600160a01b0383169033907f99039fcf0a98f484616c5196ee8b2ecfa971babf0b519848289ea4db381f85f79060200160405180910390a35050565b6002546001600160a01b0316336001600160a01b0316146107535760405162461bcd60e51b81526020600482015260016024820152602960f91b604482015260640161050f565b600280546001600160a01b0319169055565b6002546001600160a01b0316336001600160a01b0316146107ac5760405162461bcd60e51b81526020600482015260016024820152602960f91b604482015260640161050f565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0391821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b610820610a69565b6001546001600160a01b03161561085d5760405162461bcd60e51b81526020600482015260016024820152604960f81b604482015260640161050f565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156108c55750825b905060008267ffffffffffffffff1660011480156108e25750303b155b9050811580156108f0575080155b1561090e5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561093857845460ff60401b1916600160401b1785555b6109428a8a610d03565b61094b33610d15565b600280546001600160a01b03808a166001600160a01b03199283161790925560008054928b1692909116919091178155865181906109929089016020908101908a01611480565b600480546001600160a01b039283166001600160a01b03199182161790915560058054929093169116179055505088159450610a0d935050505057845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050505050565b610a21610a69565b6001600160a01b038116610a4b57604051631e4fbdf760e01b81526000600482015260240161050f565b610a5481610c23565b50565b610a648383836001610d26565b505050565b33610a9b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146105c95760405163118cdaa760e01b815233600482015260240161050f565b6000610ad084846107ce565b9050600019811015610b255781811015610b1657604051637dc7a0d960e11b81526001600160a01b0384166004820152602481018290526044810183905260640161050f565b610b2584848484036000610d26565b50505050565b6001600160a01b038316610b5557604051634b637e8f60e11b81526000600482015260240161050f565b6001600160a01b038216610b7f5760405163ec442f0560e01b81526000600482015260240161050f565b610a64838383610e0e565b6001600160a01b038216610bb457604051634b637e8f60e11b81526000600482015260240161050f565b610bc082600083610e0e565b5050565b6040516001600160a01b03838116602483015260448201839052610a6491859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050610f31565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6001600160a01b038216610cbe5760405163ec442f0560e01b81526000600482015260240161050f565b610bc060008383610e0e565b6040516001600160a01b038481166024830152838116604483015260648201839052610b259186918216906323b872dd90608401610bf1565b610d0b610fa2565b610bc08282610feb565b610d1d610fa2565b610a548161103c565b6000805160206116448339815191526001600160a01b038516610d5f5760405163e602df0560e01b81526000600482015260240161050f565b6001600160a01b038416610d8957604051634a1406b160e11b81526000600482015260240161050f565b6001600160a01b03808616600090815260018301602090815260408083209388168352929052208390558115610e0757836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92585604051610dfe91815260200190565b60405180910390a35b5050505050565b610e19838383611044565b6001600160a01b03831615610e97576001805460405163d6460b4b60e01b81526001600160a01b03868116600483015260248201859052604482019390935291169063d6460b4b90606401600060405180830381600087803b158015610e7e57600080fd5b505af1158015610e92573d6000803e3d6000fd5b505050505b6001600160a01b03821615801590610eba57506001600160a01b03821661dead14155b15610a645760015460405163d6460b4b60e01b81526001600160a01b03848116600483015260248201849052600060448301529091169063d6460b4b90606401600060405180830381600087803b158015610f1457600080fd5b505af1158015610f28573d6000803e3d6000fd5b50505050505050565b600080602060008451602086016000885af180610f54576040513d6000823e3d81fd5b50506000513d91508115610f6c578060011415610f79565b6001600160a01b0384163b155b15610b2557604051635274afe760e01b81526001600160a01b038516600482015260240161050f565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166105c957604051631afcd79f60e31b815260040160405180910390fd5b610ff3610fa2565b6000805160206116448339815191527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0361102d8482611563565b5060048101610b258382611563565b610a21610fa2565b6000805160206116448339815191526001600160a01b03841661108057818160020160008282546110759190611622565b909155506110f29050565b6001600160a01b038416600090815260208290526040902054828110156110d35760405163391434e360e21b81526001600160a01b0386166004820152602481018290526044810184905260640161050f565b6001600160a01b03851660009081526020839052604090209083900390555b6001600160a01b03831661111057600281018054839003905561112f565b6001600160a01b03831660009081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161117491815260200190565b60405180910390a350505050565b602081526000825180602084015260005b818110156111b05760208186018101516040868401015201611193565b506000604082850101526040601f19601f83011684010191505092915050565b6001600160a01b0381168114610a5457600080fd5b600080604083850312156111f857600080fd5b8235611203816111d0565b946020939093013593505050565b60006020828403121561122357600080fd5b813561122e816111d0565b9392505050565b60008060006060848603121561124a57600080fd5b8335611255816111d0565b92506020840135611265816111d0565b929592945050506040919091013590565b60006020828403121561128857600080fd5b5035919050565b600080604083850312156112a257600080fd5b82356112ad816111d0565b915060208301356112bd816111d0565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60008067ffffffffffffffff8411156112f9576112f96112c8565b50604051601f19601f85018116603f0116810181811067ffffffffffffffff82111715611328576113286112c8565b60405283815290508082840185101561134057600080fd5b83836020830137600060208583010152509392505050565b600082601f83011261136957600080fd5b61122e838335602085016112de565b600080600080600060a0868803121561139057600080fd5b853567ffffffffffffffff8111156113a757600080fd5b6113b388828901611358565b955050602086013567ffffffffffffffff8111156113d057600080fd5b6113dc88828901611358565b94505060408601356113ed816111d0565b925060608601356113fd816111d0565b9150608086013567ffffffffffffffff81111561141957600080fd5b8601601f8101881361142a57600080fd5b611439888235602084016112de565b9150509295509295909350565b600181811c9082168061145a57607f821691505b60208210810361147a57634e487b7160e01b600052602260045260246000fd5b50919050565b600080600080600080600060e0888a03121561149b57600080fd5b87516114a6816111d0565b60208901519097506114b7816111d0565b60408901519096506114c8816111d0565b60608901519095506114d9816111d0565b60808901519094506114ea816111d0565b60a08901519093506114fb816111d0565b60c089015190925061150c816111d0565b8091505092959891949750929550565b601f821115610a6457806000526020600020601f840160051c810160208510156115435750805b601f840160051c820191505b81811015610e07576000815560010161154f565b815167ffffffffffffffff81111561157d5761157d6112c8565b6115918161158b8454611446565b8461151c565b6020601f8211600181146115c557600083156115ad5750848201515b600019600385901b1c1916600184901b178455610e07565b600084815260208120601f198516915b828110156115f557878501518255602094850194600190920191016115d5565b50848210156116135786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b808201808211156104c857634e487b7160e01b600052601160045260246000fdfe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00a26469706673582212200793bf109c721c59365d702ad1654efb58adfa2955fbf510f17cf72b27a16a8064736f6c634300081c0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.