More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 7,126 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Approve | 134886281 | 1 hr ago | IN | 0 ETH | 0.00000137079 | ||||
Approve | 134867252 | 12 hrs ago | IN | 0 ETH | 0.000004655016 | ||||
Redeem | 134844650 | 25 hrs ago | IN | 0 ETH | 0.000004295021 | ||||
Approve | 134823587 | 36 hrs ago | IN | 0 ETH | 0.00000092676 | ||||
Mint | 134644066 | 5 days ago | IN | 0 ETH | 0.000001493283 | ||||
Approve | 134435299 | 10 days ago | IN | 0 ETH | 0.00000083371 | ||||
Redeem | 134434867 | 10 days ago | IN | 0 ETH | 0.000006298557 | ||||
Mint | 134373795 | 11 days ago | IN | 0 ETH | 0.00000228043 | ||||
Mint | 134341930 | 12 days ago | IN | 0 ETH | 0.000006274276 | ||||
Mint | 134341762 | 12 days ago | IN | 0 ETH | 0.000006012928 | ||||
Approve | 134316904 | 13 days ago | IN | 0 ETH | 0.000000126175 | ||||
Redeem | 134314122 | 13 days ago | IN | 0 ETH | 0.000006203135 | ||||
Approve | 134311426 | 13 days ago | IN | 0 ETH | 0.000000783066 | ||||
Redeem | 134307220 | 13 days ago | IN | 0 ETH | 0.000010712276 | ||||
Approve | 134305350 | 13 days ago | IN | 0 ETH | 0.00000020254 | ||||
Mint | 134284741 | 14 days ago | IN | 0 ETH | 0.000005668371 | ||||
Approve | 134274426 | 14 days ago | IN | 0 ETH | 0.000000220441 | ||||
Approve | 134257884 | 14 days ago | IN | 0 ETH | 0.00000013073 | ||||
Approve | 134257877 | 14 days ago | IN | 0 ETH | 0.000000224259 | ||||
Redeem | 134239084 | 15 days ago | IN | 0 ETH | 0.000005512986 | ||||
Approve | 134239052 | 15 days ago | IN | 0 ETH | 0.000000128015 | ||||
Mint | 134238690 | 15 days ago | IN | 0 ETH | 0.000007334609 | ||||
Redeem | 134097219 | 18 days ago | IN | 0 ETH | 0.000024949439 | ||||
Mint | 134034091 | 19 days ago | IN | 0 ETH | 0.00000116927 | ||||
Redeem | 134023390 | 20 days ago | IN | 0 ETH | 0.000000963896 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
120052182 | 343 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
LeveragedToken
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {Address} from "openzeppelin-contracts/contracts/utils/Address.sol"; import {TlxOwnable} from "./utils/TlxOwnable.sol"; import {Errors} from "./libraries/Errors.sol"; import {ScaledNumber} from "./libraries/ScaledNumber.sol"; import {ILeveragedToken} from "./interfaces/ILeveragedToken.sol"; import {IAddressProvider} from "./interfaces/IAddressProvider.sol"; import {IStaker} from "./interfaces/IStaker.sol"; import {IReferrals} from "./interfaces/IReferrals.sol"; import {ISynthetixHandler} from "./interfaces/ISynthetixHandler.sol"; contract LeveragedToken is ILeveragedToken, ERC20, TlxOwnable { using ScaledNumber for uint256; using Address for address; IAddressProvider internal immutable _addressProvider; uint256 internal _lastStreamingFeeTimestamp; /// @inheritdoc ILeveragedToken string public override targetAsset; /// @inheritdoc ILeveragedToken uint256 public immutable override targetLeverage; /// @inheritdoc ILeveragedToken bool public immutable override isLong; /// @inheritdoc ILeveragedToken bool public override isPaused; constructor( string memory name_, string memory symbol_, string memory targetAsset_, uint256 targetLeverage_, bool isLong_, address addressProvider_ ) ERC20(name_, symbol_) TlxOwnable(addressProvider_) { targetAsset = targetAsset_; targetLeverage = targetLeverage_; isLong = isLong_; _addressProvider = IAddressProvider(addressProvider_); } /// @inheritdoc ILeveragedToken function computePriceImpact( uint256 baseAmount_, bool isDeposit_ ) external view override returns (uint256, bool) { address market_ = _addressProvider.synthetixHandler().market( targetAsset ); return _computePriceImpact(market_, baseAmount_, isDeposit_); } /// @inheritdoc ILeveragedToken function mint( uint256 baseAmountIn_, uint256 minLeveragedTokenAmountOut_ ) public override returns (uint256) { if (baseAmountIn_ == 0) return 0; if (isPaused) revert Paused(); if (!isActive()) revert Inactive(); address market_ = _addressProvider.synthetixHandler().market( targetAsset ); uint256 maxBaseAssetAmount_ = _maxBaseAssetAmount(market_); if (baseAmountIn_ > maxBaseAssetAmount_) revert ExceedsLimit(); _ensureNoPendingLeverageUpdate(market_); // Accounting (uint256 slippage_, bool isLoss_) = _computePriceImpact( market_, baseAmountIn_, true ); uint256 exchangeRate_ = _exchangeRate(market_); uint256 leveragedTokenAmount_; if (isLoss_) { leveragedTokenAmount_ = (baseAmountIn_ - slippage_).div( exchangeRate_ ); } else { leveragedTokenAmount_ = baseAmountIn_.div(exchangeRate_); } // Verifying sufficient amount bool sufficient_ = leveragedTokenAmount_ >= minLeveragedTokenAmountOut_; if (!sufficient_) revert InsufficientAmount(); // Minting _addressProvider.baseAsset().transferFrom( msg.sender, address(this), baseAmountIn_ ); _depositMargin(baseAmountIn_, market_); _mint(msg.sender, leveragedTokenAmount_); emit Minted(msg.sender, baseAmountIn_, leveragedTokenAmount_); // Rebalancing if necessary if (_canRebalance(market_)) _rebalance(market_, 0); return leveragedTokenAmount_; } /// @inheritdoc ILeveragedToken function redeem( uint256 leveragedTokenAmount_, uint256 minBaseAmountReceived_ ) public override returns (uint256) { if (leveragedTokenAmount_ == 0) return 0; address market_ = _addressProvider.synthetixHandler().market( targetAsset ); _ensureNoPendingLeverageUpdate(market_); // Accounting uint256 exchangeRate_ = _exchangeRate(market_); uint256 baseWithdrawn_ = leveragedTokenAmount_.mul(exchangeRate_); uint256 maxBaseAssetAmount_ = _maxBaseAssetAmount(market_); if (baseWithdrawn_ > maxBaseAssetAmount_) revert ExceedsLimit(); (uint256 slippage_, bool isLoss_) = _computePriceImpact( market_, baseWithdrawn_, false ); IAddressProvider addressProvider_ = _addressProvider; uint256 feePercent_ = addressProvider_ .parameterProvider() .redemptionFee(); uint256 fee_ = baseWithdrawn_.mul(targetLeverage).mul(feePercent_); uint256 baseAmountReceived_ = baseWithdrawn_ - fee_; if (isLoss_) baseAmountReceived_ = baseAmountReceived_ - slippage_; // Verifying sufficient amount bool sufficient_ = baseAmountReceived_ >= minBaseAmountReceived_; if (!sufficient_) revert InsufficientAmount(); // Withdrawing margin _withdrawMargin(baseWithdrawn_, market_); // Charging fees _chargeRedemptionFee(fee_); // Redeeming _burn(msg.sender, leveragedTokenAmount_); addressProvider_.baseAsset().transfer(msg.sender, baseAmountReceived_); emit Redeemed(msg.sender, baseAmountReceived_, leveragedTokenAmount_); // Rebalancing if necessary if (_canRebalance(market_)) _rebalance(market_, 0); return baseAmountReceived_; } /// @inheritdoc ILeveragedToken function rebalance() public override { bool canRebalance_ = _addressProvider.isRebalancer(msg.sender); if (!canRebalance_) revert Errors.NotAuthorized(); address market_ = _addressProvider.synthetixHandler().market( targetAsset ); if (!_canRebalance(market_)) revert CannotRebalance(); _rebalance( market_, _addressProvider.parameterProvider().rebalanceFee() ); } /// @inheritdoc ILeveragedToken function chargeStreamingFee() public { address market_ = _addressProvider.synthetixHandler().market( targetAsset ); uint256 fee_ = _getStreamingFee(market_); _withdrawMargin(fee_, market_); _chargeStreamingFee(fee_); } /// @inheritdoc ILeveragedToken function setIsPaused(bool isPaused_) public override onlyOwner { if (isPaused == isPaused_) revert Errors.SameAsCurrent(); isPaused = isPaused_; emit PausedSet(isPaused_); } /// @inheritdoc ILeveragedToken function exchangeRate() public view override returns (uint256) { address market_ = _addressProvider.synthetixHandler().market( targetAsset ); return _exchangeRate(market_); } /// @inheritdoc ILeveragedToken function isActive() public view override returns (bool) { return exchangeRate() > 0; } /// @inheritdoc ILeveragedToken function canRebalance() public view override returns (bool) { address market_ = _addressProvider.synthetixHandler().market( targetAsset ); return _canRebalance(market_); } /// @inheritdoc ILeveragedToken function rebalanceThreshold() public view override returns (uint256) { return _addressProvider.parameterProvider().rebalanceThreshold( address(this) ); } function _rebalance(address market_, uint256 rebalanceFee_) internal { // Charging fees uint256 streamingFee_ = _getStreamingFee(market_); _withdrawMargin(streamingFee_ + rebalanceFee_, market_); _chargeRebalanceFee(rebalanceFee_); _chargeStreamingFee(streamingFee_); // Rebalancing _submitLeverageUpdate(market_); uint256 currentLeverage_ = _addressProvider.synthetixHandler().leverage( market_, address(this) ); emit Rebalanced(currentLeverage_); } function _chargeRedemptionFee(uint256 fee_) internal { // Paying referrals IAddressProvider addressProvider_ = _addressProvider; IReferrals referrals_ = addressProvider_.referrals(); IERC20 baseAsset_ = addressProvider_.baseAsset(); baseAsset_.approve(address(referrals_), fee_); uint256 referralAmount_ = referrals_.takeEarnings(fee_, msg.sender); // Sending fees to staker IStaker staker_ = addressProvider_.staker(); uint256 amount_ = fee_ - referralAmount_; if (amount_ == 0) return; if (staker_.totalStaked() == staker_.totalPrepared()) { baseAsset_.transfer(address(addressProvider_.treasury()), amount_); return; } baseAsset_.approve(address(staker_), amount_); staker_.donateRewards(amount_); } function _getStreamingFee(address market_) internal returns (uint256) { // First deposit, don't charge fee but start streaming if (_lastStreamingFeeTimestamp == 0) { _lastStreamingFeeTimestamp = block.timestamp; return 0; } // Accounting IAddressProvider addressProvider_ = _addressProvider; uint256 streamingFeePercent_ = addressProvider_ .parameterProvider() .streamingFee(); ISynthetixHandler synthetixHandler_ = addressProvider_ .synthetixHandler(); uint256 notionalValue_ = synthetixHandler_.notionalValue( market_, address(this) ); uint256 annualStreamingFee_ = notionalValue_.mul(streamingFeePercent_); uint256 pastTime_ = block.timestamp - _lastStreamingFeeTimestamp; uint256 fee_ = annualStreamingFee_.mul(pastTime_).div(365 days); if (fee_ == 0) return 0; // Return fees IStaker staker_ = _addressProvider.staker(); if (staker_.totalStaked() == staker_.totalPrepared()) return 0; return fee_; } function _chargeStreamingFee(uint256 fee_) internal { if (fee_ == 0) return; IStaker staker_ = _addressProvider.staker(); _addressProvider.baseAsset().approve(address(staker_), fee_); staker_.donateRewards(fee_); _lastStreamingFeeTimestamp = block.timestamp; } function _chargeRebalanceFee(uint256 fee_) internal { if (fee_ == 0) return; IAddressProvider addressProvider_ = _addressProvider; address receiver_ = addressProvider_.rebalanceFeeReceiver(); addressProvider_.baseAsset().transfer(receiver_, fee_); } function _depositMargin(uint256 amount_, address market_) internal { address(_addressProvider.synthetixHandler()).functionDelegateCall( abi.encodeWithSelector( ISynthetixHandler.depositMargin.selector, market_, amount_ ) ); } function _withdrawMargin(uint256 amount_, address market_) internal { address(_addressProvider.synthetixHandler()).functionDelegateCall( abi.encodeWithSelector( ISynthetixHandler.withdrawMargin.selector, market_, amount_ ) ); } function _submitLeverageUpdate(address market_) internal { address(_addressProvider.synthetixHandler()).functionDelegateCall( abi.encodeWithSelector( ISynthetixHandler.submitLeverageUpdate.selector, market_, targetLeverage, isLong ) ); } function _maxBaseAssetAmount( address market_ ) internal view returns (uint256) { return _addressProvider .synthetixHandler() .maxMarketValue(targetAsset, market_) .mul( 1e18 - _addressProvider .parameterProvider() .maxBaseAssetAmountBuffer() ); } function _canRebalance(address market_) internal view returns (bool) { // Can't rebalance if there is no margin if ( _addressProvider.synthetixHandler().remainingMargin( market_, address(this) ) == 0 ) return false; // Can't rebalance if there is a pending leverage update if ( _addressProvider.synthetixHandler().hasPendingLeverageUpdate( market_, address(this) ) ) return false; // Can't rebalance if the leverageDeviationFactor is already within the threshold uint256 leverageDeviationFactor_ = _addressProvider .synthetixHandler() .leverageDeviationFactor(market_, address(this), targetLeverage); return leverageDeviationFactor_ >= rebalanceThreshold(); } function _exchangeRate(address market_) internal view returns (uint256) { uint256 totalSupply_ = totalSupply(); if (totalSupply_ == 0) return 1e18; uint256 totalValue_ = _addressProvider.synthetixHandler().totalValue( market_, address(this) ); return totalValue_.div(totalSupply_); } function _computePriceImpact( address market_, uint256 baseAmount_, bool isDeposit_ ) internal view returns (uint256, bool) { return _addressProvider.synthetixHandler().computePriceImpact( market_, targetLeverage, baseAmount_, isLong, isDeposit_ ); } function _ensureNoPendingLeverageUpdate(address market_) internal view { if ( _addressProvider.synthetixHandler().hasPendingLeverageUpdate( market_, address(this) ) ) revert LeverageUpdatePending(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC20Metadata} from "./extensions/IERC20Metadata.sol"; import {Context} from "../../utils/Context.sol"; import {IERC20Errors} from "../../interfaces/draft-IERC6093.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. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the ERC may not emit * these events, as it isn't required by the specification. */ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { 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) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { 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) { 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}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the ERC. See the note at the beginning of {ERC20}. * * 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 { 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: * ``` * 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 { 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) (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.0.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.0.0) (utils/Address.sol) pragma solidity ^0.8.20; import {Errors} from "./Errors.sol"; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert Errors.InsufficientBalance(address(this).balance, amount); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert Errors.FailedCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {Errors.FailedCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case * of an unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {Errors.FailedCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert Errors.FailedCall(); } } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; import {IAddressProvider} from "../interfaces/IAddressProvider.sol"; abstract contract TlxOwnable { IAddressProvider private immutable _addressProvider; error NotOwner(); modifier onlyOwner() { if (_addressProvider.owner() != msg.sender) { revert NotOwner(); } _; } constructor(address addressProvider_) { _addressProvider = IAddressProvider(addressProvider_); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; library Errors { error NotAuthorized(); error AlreadyExists(); error DoesNotExist(); error ZeroAddress(); error SameAsCurrent(); error InvalidAddress(); error InsufficientAmount(); error NotLeveragedToken(); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; library ScaledNumber { uint8 internal constant _DEFAULT_DECIMALS = 18; function div( uint256 value, uint256 divisor ) internal pure returns (uint256) { return (value * 10 ** _DEFAULT_DECIMALS) / divisor; } function mul( uint256 value, uint256 multiplier ) internal pure returns (uint256) { return (value * multiplier) / 10 ** _DEFAULT_DECIMALS; } function absSub(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a - b : b - a; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; interface ILeveragedToken is IERC20Metadata { event Minted( address indexed account, uint256 leveragedTokenAmount, uint256 baseAssetAmount ); event Redeemed( address indexed account, uint256 leveragedTokenAmount, uint256 baseAssetAmount ); event Rebalanced(uint256 currentLeverage); event PausedSet(bool isPaused); error InsufficientAmount(); error CannotRebalance(); error LeverageUpdatePending(); error Paused(); error ExceedsLimit(); error Inactive(); /** * @notice Mints some leveraged tokens to the caller with the given baseAmountIn of the base asset. * @param baseAmountIn The amount of the base asset to mint with. * @param minLeveragedTokenAmountOut The minimum amount of leveragedTokens to mint (reverts otherwise). * @return leveragedTokenAmountOut The amount of leveragedTokens minted. */ function mint( uint256 baseAmountIn, uint256 minLeveragedTokenAmountOut ) external returns (uint256 leveragedTokenAmountOut); /** * @notice Redeems leveragedTokenAmount of the leveraged token and returns the base asset. * @param leveragedTokenAmount The amount of the leveraged token to redeem. * @param minBaseAmountReceived The minimum amount of the base asset to receive (reverts otherwise). * @return baseAmountReceived The amount of the base asset received. */ function redeem( uint256 leveragedTokenAmount, uint256 minBaseAmountReceived ) external returns (uint256 baseAmountReceived); /** * @notice Rebalances the position to the target leverage. */ function rebalance() external; /** * @notice Charges the streaming fee. * @dev This is done automatically during rebalances, but we might want to do this more frequently. */ function chargeStreamingFee() external; /** * @notice Sets if the leveraged token is paused. * @dev Only callable by the contract owner. * @param isPaused If the leveraged token should be paused or not. */ function setIsPaused(bool isPaused) external; /** * @notice Returns the target asset of the leveraged token. * @return targetAsset The target asset of the leveraged token. */ function targetAsset() external view returns (string memory targetAsset); /** * @notice Returns the target leverage of the leveraged token. * @return targetLeverage The target leverage of the leveraged token. */ function targetLeverage() external view returns (uint256 targetLeverage); /** * @notice Returns if the leveraged token is long or short. * @return isLong `true` if the leveraged token is long and `false` if the leveraged token is short. */ function isLong() external view returns (bool isLong); /** * @notice Returns if the leveraged token is active, * @dev A token is active if it still has some positive exchange rate (i.e. has not been liquidated). * @return isActive If the leveraged token is active. */ function isActive() external view returns (bool isActive); /** * @notice Returns if the leveraged token is paused, * @dev If a token is paused, deposits are disabled. * @return isPaused If the leveraged token is paused. */ function isPaused() external view returns (bool isPaused); /** * @notice Returns the rebalance threshold. * @dev Represented as a percent in 18 decimals, e.g. 20% = 0.2e18. * @return rebalanceThreshold The rebalance threshold. */ function rebalanceThreshold() external view returns (uint256 rebalanceThreshold); /** * @notice Returns the exchange rate from one leveraged token to one base asset. * @dev In 18 decimals. * @return exchangeRate The exchange rate. */ function exchangeRate() external view returns (uint256 exchangeRate); /** * @notice Returns the expected slippage from making an adjustment to a position. * @param baseAmount Margin amount to deposit in units of base asset. * @param isDeposit If the adjustment is a deposit. * @return slippage Slippage in units of base asset. * @return isLoss Whether the slippage is a loss. */ function computePriceImpact( uint256 baseAmount, bool isDeposit ) external view returns (uint256 slippage, bool isLoss); /** * @notice Returns if the leveraged token can be rebalanced. * @return canRebalance If the leveraged token can be rebalanced. */ function canRebalance() external view returns (bool canRebalance); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {ILeveragedTokenFactory} from "./ILeveragedTokenFactory.sol"; import {IReferrals} from "./IReferrals.sol"; import {IAirdrop} from "./IAirdrop.sol"; import {IBonding} from "./IBonding.sol"; import {IVesting} from "./IVesting.sol"; import {ITlxToken} from "./ITlxToken.sol"; import {IStaker} from "./IStaker.sol"; import {ISynthetixHandler} from "./ISynthetixHandler.sol"; import {IParameterProvider} from "./IParameterProvider.sol"; import {IZapSwap} from "./IZapSwap.sol"; interface IAddressProvider { event AddressUpdated(bytes32 indexed key, address value); event AddressFrozen(bytes32 indexed key); event RebalancerAdded(address indexed account); event RebalancerRemoved(address indexed account); error AddressIsFrozen(bytes32 key); /** * @notice Updates an address for the given key. * @param key The key of the address to be updated. * @param value The value of the address to be updated. */ function updateAddress(bytes32 key, address value) external; /** * @notice Freezes an address for the given key, making it immutable. * @param key The key of the address to be frozen. */ function freezeAddress(bytes32 key) external; /** * @notice Gives the `account` permissions to rebalance leveraged tokens. * @dev Reverts if the `account` is already a rebalancer. * @param account The address of the account to be added. */ function addRebalancer(address account) external; /** * @notice Removes the `account` permissions to rebalance leveraged tokens. * @dev Reverts if the `account` is not a rebalancer. * @param account The address of the account to be removed. */ function removeRebalancer(address account) external; /** * @notice Returns the address for a kiven key. * @param key The key of the address to be returned. * @return value The address for the given key. */ function addressOf(bytes32 key) external view returns (address value); /** * @notice Returns whether an address is frozen. * @param key The key of the address to be checked. * @return Whether the address is frozen. */ function isAddressFrozen(bytes32 key) external view returns (bool); /** * @notice Returns the LeveragedTokenFactory contract. * @return leveragedTokenFactory The LeveragedTokenFactory contract. */ function leveragedTokenFactory() external view returns (ILeveragedTokenFactory leveragedTokenFactory); /** * @notice Returns the Referrals contract. * @return referrals The Referrals contract. */ function referrals() external view returns (IReferrals referrals); /** * @notice Returns the Airdrop contract. * @return airdrop The Airdrop contract. */ function airdrop() external view returns (IAirdrop airdrop); /** * @notice Returns the Bonding contract. * @return bonding The Bonding contract. */ function bonding() external view returns (IBonding bonding); /** * @notice Returns the address for the Treasury contract. * @return treasury The address of the Treasury contract. */ function treasury() external view returns (address treasury); /** * @notice Returns the Vesting contract. * @return vesting The Vesting contract. */ function vesting() external view returns (IVesting vesting); /** * @notice Returns the TLX contract. * @return tlx The TLX contract. */ function tlx() external view returns (ITlxToken tlx); /** * @notice Returns the Staker contract. * @return staker The Staker contract. */ function staker() external view returns (IStaker staker); /** * @notice Returns the ZapSwap contract. * @return zapSwap The ZapSwap contract. */ function zapSwap() external view returns (IZapSwap zapSwap); /** * @notice Returns the base asset. * @return baseAsset The base asset. */ function baseAsset() external view returns (IERC20Metadata baseAsset); /** * @notice Returns the SynthetixHandler contract. * @return synthetixHandler The SynthetixHandler contract. */ function synthetixHandler() external view returns (ISynthetixHandler synthetixHandler); /** * @notice Returns the address for the POL token. * @return pol The address of the POL token. */ function pol() external view returns (address pol); /** * @notice Returns the Parameter Provider contract. * @return parameterProvider The Parameter Provider contract. */ function parameterProvider() external view returns (IParameterProvider parameterProvider); /** * @notice Returns if the given `account` is permitted to rebalance leveraged tokens. * @param account The address of the account to be checked. * @return isRebalancer Whether the account is permitted to rebalance leveraged tokens. */ function isRebalancer( address account ) external view returns (bool isRebalancer); /** * @notice Returns the list of rebalancers. * @return rebalancers The list of rebalancers. */ function rebalancers() external view returns (address[] memory rebalancers); /** * @notice Returns the address for the Rebalance Fee Receiver. * @return rebalanceFeeReceiver The address of the Rebalance Fee Receiver. */ function rebalanceFeeReceiver() external view returns (address rebalanceFeeReceiver); /** * @notice Returns the owner of all TLX contracts. * @return owner The owner of all TLX contracts. */ function owner() external view returns (address owner); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; import {IRewardsStreaming} from "./IRewardsStreaming.sol"; import {Unstakes} from "../libraries/Unstakes.sol"; interface IStaker is IRewardsStreaming { event Staked( address indexed accountFrom, address indexed accountTo, uint256 amount ); event PreparedUnstake(address indexed account, uint256 amount, uint256 id); event Unstaked( address indexed accountFrom, address indexed accountTo, uint256 amount ); event Restaked(address indexed account, uint256 amount); error NotUnstaked(); error ClaimingNotEnabled(); error ClaimingAlreadyEnabled(); error ZeroBalance(); /** * @notice Stakes TLX tokens for the caller. * @param amount The amount of TLX tokens to stake. */ function stake(uint256 amount) external; /** * @notice Stakes TLX tokens for the caller for the account. * @param amount The amount of TLX tokens to stake. * @param account The account to stake the TLX tokens to. */ function stakeFor(uint256 amount, address account) external; /** * @notice Prepares the caller's staked TLX tokens for unstaking. * @return id The ID of the withdrawal to be unstaked. */ function prepareUnstake(uint256 amount) external returns (uint256 id); /** * @notice Unstakes the caller's TLX tokens. * @param withdrawalId The ID of the withdrawal to unstake. */ function unstake(uint256 withdrawalId) external; /** * @notice Restakes the caller's prepared TLX tokens. * @param withdrawalId The ID of the withdrawal to restake. */ function restake(uint256 withdrawalId) external; /** * @notice Unstakes the caller's TLX tokens for the given account. * @param account The account to send the TLX tokens to. * @param withdrawalId The ID of the withdrawal to unstake. */ function unstakeFor(address account, uint256 withdrawalId) external; /** * @notice Enables claiming for stakers. * @dev This can only be called by the owner. */ function enableClaiming() external; /** * @notice Returns if claiming is enabled for stakers. * @return claimingEnabled Whether claiming is enabled for stakers. */ function claimingEnabled() external view returns (bool claimingEnabled); /** * @notice Returns the symbol of the Staker. * @return symbol The symbol of the Staker. */ function symbol() external view returns (string memory symbol); /** * @notice Returns the name of the Staker. * @return name The name of the Staker. */ function name() external view returns (string memory name); /** * @notice Returns the total amount of TLX tokens prepared for unstaking. * @return amount The total amount of TLX tokens prepared for unstaking. */ function totalPrepared() external view returns (uint256 amount); /** * @notice Returns all the queued unstakes for the given account. * @param account The account to return the unstakes for. * @return unstakes All the queued unstakes for the given account. */ function listQueuedUnstakes( address account ) external view returns (Unstakes.UserUnstakeData[] memory unstakes); /** * @notice Returns the delay the user must wait when unstakeing. * @return delay The delay the user must wait when unstakeing. */ function unstakeDelay() external view returns (uint256 delay); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; interface IReferrals { event Registered(address indexed user, bytes32 code); event SetReferral(address indexed user, bytes32 code); event RebateSet(uint256 rebate); event EarningsSet(uint256 earnings); event ReferralEarned(address indexed user, uint256 amount); event RebateEarned(address indexed user, uint256 amount); event EarningsClaimed(address indexed user, uint256 amount); error AlreadyRegistered(); error InvalidCode(); error CodeTaken(); error AlreadyOpen(); error NotChanged(); error InvalidAmount(); /** * @notice Takes the referral earnings from the given fees for the given user. * @param fees The fees to take the earnings from. * @param user The user to take the earnings for. * @return earnings The earnings taken. */ function takeEarnings( uint256 fees, address user ) external returns (uint256 earnings); /** * @notice Claims the referral earnings for the sender. * @return earnings The earnings claimed. */ function claimEarnings() external returns (uint256 earnings); /** * @notice Registers the given code for the sender. * @param code The code to register. */ function register(address referrer, bytes32 code) external; /** * @notice Sets the referral code for the sender. * @dev Reverts if the user has already set a code. * @param code The code to use. */ function setReferral(bytes32 code) external; /** * @notice Sets the rebate percent. * @dev Can only be called by the owner. * @param rebatePercent The rebate percent to set. */ function setRebatePercent(uint256 rebatePercent) external; /** * @notice Sets the referral percent. * @dev Can only be called by the owner. * @param referralPercent The referral percent to set. */ function setReferralPercent(uint256 referralPercent) external; /** * @notice Returns the reabate for the given code. * @param code The code to get the rebate for. * @return rebate The rebate for the given code. */ function codeRebate(bytes32 code) external view returns (uint256 rebate); /** * @notice Returns the rebate for the given user. * @param user The user to get the rebate for. * @return rebate The rebate for the given user. */ function userRebate(address user) external view returns (uint256 rebate); /** * @notice Returns the referrer for the given code. * @param code The code to get the referrer for. * @return referrer The referrer for the given code. */ function referrer(bytes32 code) external view returns (address referrer); /** * @notice Returns the code for the given referrer * @param referrer The referrer to get the code for. * @return code The code for the given referrer. */ function code(address referrer) external view returns (bytes32 code); /** * @notice Returns the code for the given user. * @param user The user to get the code for. * @return code The code for the given user. */ function referral(address user) external view returns (bytes32 code); /** * @notice Returns the earnings for the given referrer. * @param referrer The referrer to get the earnings for. * @return earned The earnings for the given referrer. */ function earned(address referrer) external view returns (uint256 earned); /** * @notice Returns the rebate percent. * @dev As a percent of fees, e.g 10% as 0.1e18. * @return rebatePercent The rebate percent. */ function rebatePercent() external view returns (uint256 rebatePercent); /** * @notice Returns the referral percent. * @dev As a percent of fees, e.g 10% as 0.1e18. * @return referralPercent The referral percent. */ function referralPercent() external view returns (uint256 referralPercent); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; interface ISynthetixHandler { error ErrorGettingPnl(); error ErrorGettingOrderFee(); error ErrorGettingIsLong(); error ErrorGettingFillPrice(); error ErrorGettingAssetPrice(); error NoMargin(); /** * @notice Deposit `amount` of margin to Synthetix for the `market`. * @dev Should be called with delegatecall. * @param market The market to deposit margin for. * @param amount The amount of margin to deposit. */ function depositMargin(address market, uint256 amount) external; /** * @notice Withdraw `amount` of margin from Synthetix for the `market`. * @dev Should be called with delegatecall. * @param market The market to withdraw margin for. * @param amount The amount of margin to withdraw. */ function withdrawMargin(address market, uint256 amount) external; /** * @notice Submit a leverage update for the `market`. * @dev Should be called with delegatecall. * @param market The market to submit a leverage update for. * @param leverage The new leverage to target. * @param isLong Whether the position is long or short. */ function submitLeverageUpdate( address market, uint256 leverage, bool isLong ) external; /** * @notice Computes expected price impact for a position adjustment at current prices. * @param market The market for which to compute price impact for. * @param leverage The leverage to target. * @param baseAmount The margin amount to compute price impact for. * @param isLong Whether the position is long or short. * @param isDeposit Whether the adjustment is a deposit. * @return slippage The expected slippage for the position adjustment. * @return isLoss Whether the expected slippage is a loss. */ function computePriceImpact( address market, uint256 leverage, uint256 baseAmount, bool isLong, bool isDeposit ) external view returns (uint256 slippage, bool isLoss); /** * @notice Returns the address for the market of the `targetAsset`. * @param targetAsset The asset to return the market for. * @return market The address for the market of the `targetAsset`. */ function market( string calldata targetAsset ) external view returns (address market); /** * @notice Returns if the `account` has a pending leverage update. * @param market The market to check if the `account` has a pending leverage update for. * @param account The account to check if they have a pending leverage update. * @return hasPendingLeverageUpdate Whether the `account` has a pending leverage update. */ function hasPendingLeverageUpdate( address market, address account ) external view returns (bool hasPendingLeverageUpdate); /** * @notice Returns if the `account` has an open position for the `market`. * @param market The market to check if the `account` has an open position for. * @param account The account to check if they have an open position for the `market`. * @return hasOpenPosition Whether the `acccount` has an open position for the `market`. */ function hasOpenPosition( address market, address account ) external view returns (bool hasOpenPosition); /** * @notice Returns the total value of the `account`'s position for the `market` in the Base Asset. * @param market The market to get the total value of the `account`'s position for. * @param account The account to get the total value of the `account`'s position for the `market`. * @return totalValue The total value of the `account`'s position for the `market` in the Base Asset. */ function totalValue( address market, address account ) external view returns (uint256 totalValue); /** * @notice Returns the deviation factor from our target leverage. * @dev Used for rebalances, if |1 - leverageDeviationFactor| exceeds our `rebalanceThreshold` then a rebalance is triggered. * When this factoris below 1, it means we are underleveraged, when it is above 1, it means we are overleveraged. * @param market The market to get the leverage of the `account`'s position for. * @param account The account to get the leverage of the `account`'s position for the `market`. * @return leverageDeviationFactor The deviation factor from our target leverage. */ function leverageDeviationFactor( address market, address account, uint256 targetLeverage ) external view returns (uint256 leverageDeviationFactor); /** * @notice Returns the leverage of the `account`'s position for the `market`. * @param market The market to get the leverage of the `account`'s position for. * @param account The account to get the leverage of the `account`'s position for the `market`. * @return leverage The leverage of the `account`'s position for the `market`. */ function leverage( address market, address account ) external view returns (uint256 leverage); /** * @notice Returns the notional value of the `account`'s position for the `market` in the Base Asset. * @param market The market to get the notional value of the `account`'s position for. * @param account The account to get the notional value of the `account`'s position for the `market`. * @return notionalValue The notional value of the `account`'s position for the `market` in the Base Asset. */ function notionalValue( address market, address account ) external view returns (uint256); /** * @notice Returns if the `account`'s position for the `m` is long. * @dev Reverts if the `account` does not have an open position for the `targetAsset`. * @param market The market to check if the `account`'s position for is long. * @param account The account to check if the `account`'s position for the `targetAsset` is long. * @return isLong Whether the `account`'s position for the `market` is long. */ function isLong( address market, address account ) external view returns (bool isLong); /** * @notice Returns the initial margin of the `account`'s position for the `market`. * This does not take into account any profit or loss * @param market The market to get the remaining margin of the `account`'s position for. * @param account The account to get the remaining margin of the `account`'s position for the `market`. * @return initialMargin The initial margin of the `account`'s position for the `market`. */ function initialMargin( address market, address account ) external view returns (uint256 initialMargin); /** * @notice Returns the remaining margin of the `account`'s position for the `market`. * @param market The market to get the remaining margin of the `account`'s position for. * @param account The account to get the remaining margin of the `account`'s position for the `market`. * @return remainingMargin The remaining margin of the `account`'s position for the `market`. */ function remainingMargin( address market, address account ) external view returns (uint256 remainingMargin); /** * @notice Returns the fill price of the `market` for a trade of `sizeDelta` tokens. * @param market The market to get the fill price of. * @param sizeDelta The amount of tokens to get the fill price for. * @return fillPrice The fill price of the `market` for a trade of `sizeDelta` tokens. */ function fillPrice( address market, int256 sizeDelta ) external view returns (uint256 fillPrice); /** * @notice Returns the price of the `market`. * @param market The market to return the price for. * @return assetPrice The price of the `market`. */ function assetPrice( address market ) external view returns (uint256 assetPrice); /** * @notice Returns if the `targetAsset` is supported. * @param targetAsset The asset to check if it is supported. * @return isSupported Whether the `targetAsset` is supported. */ function isAssetSupported( string calldata targetAsset ) external view returns (bool isSupported); /** * @notice Returns the Maximum Market value for the `targetAsset`. * @param targetAsset The asset to get the Maximum Market value for. * @param market The market to get the Maximum Market value for. * @return maxMarketValue The Maximum Market value for the `targetAsset`. */ function maxMarketValue( string calldata targetAsset, address market ) external view returns (uint256 maxMarketValue); /** * @notice Returns the maximum leverage allowed for the `targetAsset`. * @param targetAsset The asset to check the maximum leverage allowed for. * @return maxLeverage The maximum leverage allowed for the `targetAsset`. */ function maxLeverage( string calldata targetAsset ) external view returns (uint256 maxLeverage); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (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.20; /** * @dev Collection of common custom errors used in multiple contracts * * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. * It is recommended to avoid relying on the error API for critical functionality. */ library Errors { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error InsufficientBalance(uint256 balance, uint256 needed); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedCall(); /** * @dev The deployment failed. */ error FailedDeployment(); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; interface ILeveragedTokenFactory { event NewLeveragedToken(address indexed token); error ZeroLeverage(); error MaxLeverage(); error MaxOfTwoDecimals(); error AssetNotSupported(); error NotInactive(); /** * @notice Creates a new Long and Short Leveraged Token for the given target asset and leverage. * @dev Reverts if a Leveraged Token for the given target asset and leverage already exists. * @param targetAsset The target asset of the Leveraged Token. * @param targetLeverage The target leverage of the Leveraged Token (18 decimals). * @param rebalanceThreshold The threshold for rebalancing (18 decimals). * @return longToken The address of the Long Leveraged Token. * @return shortToken The address of the Short Leveraged Token. */ function createLeveragedTokens( string calldata targetAsset, uint256 targetLeverage, uint256 rebalanceThreshold ) external returns (address longToken, address shortToken); /** * @notice Redeploys a Leveraged Token when the old one has been liquidated and is inactive. * @dev Reverts if the Leveraged Token doesn't exist or is not inactive. * @param tokenAddress The address of the Leveraged Token that has been liquidated and is inactive. * @return newToken The address of the new Leveraged Token. */ function redeployInactiveToken( address tokenAddress ) external returns (address newToken); /** * @notice Returns all Leveraged Tokens. * @return tokens The addresses of all Leveraged Tokens. */ function allTokens() external view returns (address[] memory tokens); /** * @notice Returns all Long Leveraged Tokens. * @return tokens The addresses of all Long Leveraged Tokens. */ function longTokens() external view returns (address[] memory tokens); /** * @notice Returns all Short Leveraged Tokens. * @return tokens The addresses of all Short Leveraged Tokens. */ function shortTokens() external view returns (address[] memory tokens); /** * @notice Returns all Leveraged Tokens for the given target asset. * @param targetAsset The target asset of the Leveraged Tokens. * @return tokens The addresses of all Leveraged Tokens for the given target asset. */ function allTokens( string calldata targetAsset ) external view returns (address[] memory tokens); /** * @notice Returns all Long Leveraged Tokens for the given target asset. * @param targetAsset The target asset of the Long Leveraged Tokens. * @return tokens The addresses of all Long Leveraged Tokens for the given target asset. */ function longTokens( string calldata targetAsset ) external view returns (address[] memory tokens); /** * @notice Returns all Short Leveraged Tokens for the given target asset. * @param targetAsset The target asset of the Short Leveraged Tokens. * @return tokens The addresses of all Short Leveraged Tokens for the given target asset. */ function shortTokens( string calldata targetAsset ) external view returns (address[] memory tokens); /** * @notice Returns the Leveraged Token for the given target asset and leverage. * @param targetAsset The target asset of the Leveraged Token. * @param targetLeverage The target leverage of the Leveraged Token (2 decimals). * @param isLong If the Leveraged Token is long or short. * @return token The address of the Leveraged Token. */ function token( string calldata targetAsset, uint256 targetLeverage, bool isLong ) external view returns (address token); /** * @notice Returns if the Leveraged Token for the given target asset and leverage exists. * @param targetAsset The target asset of the Leveraged Token. * @param targetLeverage The target leverage of the Leveraged Token (2 decimals). * @param isLong If the Leveraged Token is long or short. * @return exists If the Leveraged Token exists. */ function tokenExists( string calldata targetAsset, uint256 targetLeverage, bool isLong ) external view returns (bool exists); /** * @notice Returns the Leveraged Tokens inverse pair (e.g. ETH3L -> ETH3S). * @param token The address of the Leveraged Token. * @return pair The address of the Leveraged Tokens inverse pair. */ function pair(address token) external view returns (address pair); /** * @notice Returns if the given token is a Leveraged Token. * @param token The address of the token. * @return isLeveragedToken If the given token is a Leveraged Token. */ function isLeveragedToken( address token ) external view returns (bool isLeveragedToken); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; interface IAirdrop { event MerkleRootUpdated(bytes32 merkleRoot); event Claimed(address indexed account, uint256 amount); event UnclaimedRecovered(uint256 amount); error ClaimPeriodOver(); error InvalidMerkleProof(); error AlreadyClaimed(); error AirdropCompleted(); error EverythingClaimed(); error ClaimStillOngoing(); /** * @notice Claim tokens from the airdrop. * @param amount The amount of tokens to claim. * @param merkleProof The merkle proof for the account. */ function claim(uint256 amount, bytes32[] calldata merkleProof) external; /** * @notice Update the merkle root for the airdrop. * @param merkleRoot_ The new merkle root. */ function updateMerkleRoot(bytes32 merkleRoot_) external; /** * @notice Recover unclaimed tokens to the treasury. */ function recoverUnclaimed() external; /** * @notice Returns the merkle root for the airdrop. * @return merkleRoot The merkle root for the airdrop. */ function merkleRoot() external view returns (bytes32 merkleRoot); /** * @notice Returns if the `account` has claimed their airdrop. * @param account The account to check. * @return hasClaimed If the `account` has claimed their airdrop. */ function hasClaimed( address account ) external view returns (bool hasClaimed); /** * @notice Returns the deadline for the airdrop. * @return deadline The deadline for the airdrop. */ function deadline() external view returns (uint256 deadline); /** * @notice Returns the total amount of tokens claimed. * @return totalClaimed The total amount of tokens claimed. */ function totalClaimed() external view returns (uint256 totalClaimed); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; interface IBonding { event Bonded( address indexed account, address indexed leveragedToken, uint256 leveragedTokenAmount, uint256 tlxTokensReceived ); event Migrated(uint256 amount); event BaseForAllTlxSet(uint256 value); event Launched(); error MinTlxNotReached(); error ExceedsAvailable(); error BondingNotLive(); error AmountIsZero(); error BondingAlreadyLive(); error AlreadyMigrated(); error InactiveToken(); /** * @notice Bond leveraged tokens for TLX. * @param leveragedToken The address of the leveraged token to bond. * @param leveragedTokenAmount The amount of leveraged tokens to bond. * @param minTlxTokensReceived The minimum amount of TLX tokens to receive. * @return tlxTokensReceived The amount of TLX tokens received. */ function bond( address leveragedToken, uint256 leveragedTokenAmount, uint256 minTlxTokensReceived ) external returns (uint256 tlxTokensReceived); /** * @notice Sets the base for all TLX. * @dev Reverts if the caller is not the owner. * @param baseForAllTlx The new base for all TLX. */ function setBaseForAllTlx(uint256 baseForAllTlx) external; /** * @notice Sets the bonding to live. * @dev Reverts if the caller is not the owner. */ function launch() external; /** * @notice Migrate the TLX tokens to the new bonding contract. * @dev Reverts if the caller is not the owner. */ function migrate() external; /** * @notice Returns if the bonding is live. * @return isLive If the bonding is live. */ function isLive() external view returns (bool isLive); /** * @notice Returns the exchange rate between leveraged tokens baseAsset value and TLX. * @return exchangeRate The exchange rate between leveraged tokens baseAsset value and TLX. */ function exchangeRate() external view returns (uint256 exchangeRate); /** * @notice Returns the amount of TLX tokens that can be bonded. * @return availableTlx The amount of TLX tokens that can be bonded. */ function availableTlx() external view returns (uint256 availableTlx); /** * @notice Returns the total amount of TLX tokens bonded. * @return totalTlxBonded The total amount of TLX tokens bonded. */ function totalTlxBonded() external view returns (uint256 totalTlxBonded); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; interface IVesting { struct VestingAmount { address account; uint256 amount; } struct VestingData { uint256 amount; uint256 claimed; } event Claimed(address indexed account, address indexed to, uint256 amount); event DelegateAdded(address indexed account, address indexed delegate); event DelegateRemoved(address indexed account, address indexed delegate); error NothingToClaim(); error InvalidDuration(); error NotAuthorized(); /** * @notice Claim vested tokens. */ function claim() external; /** * @notice Claim vested tokens for 'account' and send to 'to'. * @param account The address to claim the vested tokens for. * @param to The address to send the claimed tokens to. */ function claim(address account, address to) external; /** * @notice Adds a delegate for the caller. * @param delegate The address of the delegate to add. */ function addDelegate(address delegate) external; /** * @notice Removes a delegate for the caller. * @param delegate The address of the delegate to remove. */ function removeDelegate(address delegate) external; /** * @notice Get the amount of tokens that were allocated for vesting for `account`. * @param account The address to get the allocated amount for. * @return amount The amount of tokens allocated for vesting for `account`. */ function allocated(address account) external view returns (uint256 amount); /** * @notice Get the amount of tokens that have vested for `account`. * @param account The address to get the vested amount for. * @return amount The amount of tokens vested to `account`. */ function vested(address account) external view returns (uint256 amount); /** * @notice Get the amount of tokens that are vesting for `account`. * @param account The address to get the vesting amount for. * @return amount The amount of tokens vesting for `account`. */ function vesting(address account) external view returns (uint256 amount); /** * @notice Get the amount of tokens that have been claimed for `account`. * @param account The address to get the claimed amount for. * @return amount The amount of tokens claimed for `account`. */ function claimed(address account) external view returns (uint256 amount); /** * @notice Get the amount of tokens that are claimable for `account`. * @dev This is calculated as `vested` - `claimed`. * @param account The address to get the claimable amount for. * @return amount The amount of tokens claimable for `account`. */ function claimable(address account) external view returns (uint256 amount); /** * @notice Check if `delegate` is a delegate for `account`. * @param account The address to check the delegate for. * @param delegate The address to check if it is a delegate. * @return isDelegate True if `delegate` is a delegate for `account`. */ function isDelegate( address account, address delegate ) external view returns (bool isDelegate); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; interface ITlxToken is IERC20Metadata {}
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; interface IParameterProvider { struct Parameter { bytes32 key; uint256 value; } event ParameterUpdated(bytes32 indexed key, uint256 value); event RebalanceThresholdUpdated(address leveragedToken, uint256 value); error InvalidRebalanceThreshold(); error NonExistentParameter(bytes32 key); /** * @notice Updates a parameter for the given key. * @param key The key of the parameter to be updated. * @param value The value of the parameter to be updated. */ function updateParameter(bytes32 key, uint256 value) external; /** * @notice Updates the rebalance threshold for the `leveragedToken`. * @param leveragedToken The address of the leveraged token. * @param value The new rebalance threshold. */ function updateRebalanceThreshold( address leveragedToken, uint256 value ) external; /** * @notice Returns the parameter for a given key. * @param key The key of the parameter to be returned. * @return value The parameter for the given key. */ function parameterOf(bytes32 key) external view returns (uint256 value); /** * @notice Returns the redemption fee parameter. * @return redemptionFee The redemption fee parameter. */ function redemptionFee() external view returns (uint256); /** * @notice Returns the streaming fee parameter. * @return streamingFee The streaming fee parameter. */ function streamingFee() external view returns (uint256); /** * @notice Returns the rebalance fee charged for rebalances in baseAsset. * @return rebalanceFee The rebalance fee. */ function rebalanceFee() external view returns (uint256 rebalanceFee); /** * @notice Returns the percent buffer applied on the `maxBaseAssetAmount`. * @return maxBaseAssetAmountBuffer The percent buffer applied on the `maxBaseAssetAmount`. */ function maxBaseAssetAmountBuffer() external view returns (uint256 maxBaseAssetAmountBuffer); /** * @notice Returns all parameters. * @return parameters All parameters. */ function parameters() external view returns (Parameter[] memory parameters); /** * @notice Returns the rebalance threshold for the `leveragedToken`. * @param leveragedToken The address of the leveraged token. * @return rebalanceThreshold The rebalance threshold of the `leveragedToken`. */ function rebalanceThreshold( address leveragedToken ) external view returns (uint256 rebalanceThreshold); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; interface IZapSwap { struct SwapData { bool supported; bool direct; address bridgeAsset; bool zapAssetSwapStable; bool baseAssetSwapStable; address zapAssetFactory; address baseAssetFactory; bool swapZapAssetOnUni; uint24 uniPoolFee; } event Minted( address indexed account, address indexed leveragedToken, address assetIn, uint256 amountIn, uint256 leveragedTokenAmountOut ); event Redeemed( address indexed account, address indexed leveragedToken, uint256 leveragedTokenAmountIn, address assetOut, uint256 amountOut ); event AssetSwapDataUpdated(address indexed zapAsset, SwapData swapData); event AssetSwapDataRemoved(address indexed zapAsset); error UnsupportedAsset(); error BridgeAssetNotSupported(); error BridgeAssetDependency(address dependentZapAsset); /** * @notice Sets the swap data for a zap asset. * @param zapAsset The address of the new zap asset. * @param swapData The swap data describing the swap route. */ function setAssetSwapData( address zapAsset, SwapData memory swapData ) external; /** * @notice Removes an asset from supported zap assets. * @param zapAsset The address of the zap asset to be removed. */ function removeAssetSwapData(address zapAsset) external; /** * @notice Returns the swap data of a zap asset. * @param zapAsset The address of the zap asset. * @return swapData The swap data of the zap asset. */ function swapData( address zapAsset ) external returns (SwapData memory swapData); /** * @notice Returns all assets supported by the zap. * @return assets An array of all assets supported by the zap. */ function supportedZapAssets() external returns (address[] memory assets); /** * @notice Swaps the zap asset for the base asset and mints the target leveraged tokens for the caller. * @param zapAssetAddress The address of the asset used for minting. * @param leveragedTokenAddress Address of target leveraged token to mint. * @param zapAssetAmountIn The amount of the zap asset to mint with. * @param minLeveragedTokenAmountOut The minimum amount of leveraged tokens to receive (reverts otherwise). * @return leveragedTokenAmountOut The amount of leveraged tokens minted. */ function mint( address zapAssetAddress, address leveragedTokenAddress, uint256 zapAssetAmountIn, uint256 minLeveragedTokenAmountOut ) external returns (uint256 leveragedTokenAmountOut); /** * @notice Redeems the target leveraged tokens, swaps the base asset for the zap asset and returns the zap asset to the caller. * @param zapAssetAddress The address of the asset received upon redeeming. * @param leveragedTokenAddress The address of the target leveraged token to redeem. * @param leveragedTokenAmountIn The amount of the leveraged tokens to redeem. * @param minZapAssetAmountOut The minimum amount of the zap asset to receive (reverts otherwise). * @return zapAssetAmountOut The amount of zap asset received. */ function redeem( address zapAssetAddress, address leveragedTokenAddress, uint256 leveragedTokenAmountIn, uint256 minZapAssetAmountOut ) external returns (uint256 zapAssetAmountOut); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; interface IRewardsStreaming { event Claimed(address indexed account, uint256 amount); event DonatedRewards(address indexed account, uint256 amount); error ZeroAmount(); error InsufficientBalance(); /** * @notice Claims the caller's rewards. */ function claim() external; /** * @notice Donates an amount of the reward token to the staker. */ function donateRewards(uint256 amount) external; /** * @notice Returns the amount of TLX tokens staked for the given account. * @param account The account to return the staked TLX tokens for. * @return amount The amount of TLX tokens staked for the given account. */ function balanceOf(address account) external view returns (uint256 amount); /** * @notice Returns the amount of TLX tokens staked for the given account * minus the amount queued for withdrawal. * @param account The account to return the staked TLX tokens for. * @return amount The amount of TLX tokens staked and not queued for the given account. */ function activeBalanceOf( address account ) external view returns (uint256 amount); /** * @notice Returns the total amount of TLX tokens staked. * @return amount The total amount of TLX tokens staked. */ function totalStaked() external view returns (uint256 amount); /** * @notice Returns the amount of reward tokens claimable for the given account. * @param account The account to return the claimable reward tokens for. * @return amount The amount of reward tokens claimable for the given account. */ function claimable(address account) external view returns (uint256 amount); /** * @notice Returns the number of decimals the Staker's token uses. * @return decimals The number of decimals the Staker's token uses. */ function decimals() external view returns (uint8 decimals); /** * @notice Returns the address of the reward token. * @return rewardToken The address of the reward token. */ function rewardToken() external view returns (address rewardToken); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; import {EnumerableSet} from "openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol"; import {Errors} from "./Errors.sol"; library Unstakes { using EnumerableSet for EnumerableSet.UintSet; struct UserUnstakeData { uint256 id; uint256 amount; uint256 unstakeTime; } struct UserUnstake { uint192 amount; uint64 unstakeTime; } struct UserUnstakes { mapping(uint256 => UserUnstake) withdrawals; EnumerableSet.UintSet ids; uint64 nextId; uint192 totalQueued; } function queue( UserUnstakes storage self_, uint256 amount_, uint256 unstakeTime_ ) internal returns (uint256) { uint256 id = self_.nextId; self_.withdrawals[id] = UserUnstake({ amount: uint192(amount_), unstakeTime: uint64(unstakeTime_) }); self_.ids.add(id); self_.nextId++; self_.totalQueued += uint192(amount_); return id; } function remove( UserUnstakes storage self_, uint256 id_ ) internal returns (UserUnstake memory withdrawal) { if (!self_.ids.remove(id_)) revert Errors.DoesNotExist(); withdrawal = self_.withdrawals[id_]; self_.totalQueued -= withdrawal.amount; delete self_.withdrawals[id_]; } function list( UserUnstakes storage self_ ) internal view returns (UserUnstakeData[] memory withdrawals) { uint256 length_ = self_.ids.length(); withdrawals = new UserUnstakeData[](length_); for (uint256 i_; i_ < length_; i_++) { uint256 id_ = self_.ids.at(i_); UserUnstake memory withdrawal = self_.withdrawals[id_]; withdrawals[i_] = UserUnstakeData({ id: id_, amount: withdrawal.amount, unstakeTime: withdrawal.unstakeTime }); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.20; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position is the index of the value in the `values` array plus 1. // Position 0 is used to mean a value is not in the set. mapping(bytes32 value => uint256) _positions; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._positions[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We cache the value's position to prevent multiple reads from the same storage slot uint256 position = set._positions[value]; if (position != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 valueIndex = position - 1; uint256 lastIndex = set._values.length - 1; if (valueIndex != lastIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the lastValue to the index where the value to delete is set._values[valueIndex] = lastValue; // Update the tracked position of the lastValue (that was just moved) set._positions[lastValue] = position; } // Delete the slot where the moved value was stored set._values.pop(); // Delete the tracked position for the deleted slot delete set._positions[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._positions[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
{ "remappings": [ "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "chainlink/=lib/chainlink/contracts/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "pyth-sdk-solidity/=lib/pyth-sdk-solidity/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"string","name":"targetAsset_","type":"string"},{"internalType":"uint256","name":"targetLeverage_","type":"uint256"},{"internalType":"bool","name":"isLong_","type":"bool"},{"internalType":"address","name":"addressProvider_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[],"name":"CannotRebalance","type":"error"},{"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":"ExceedsLimit","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[],"name":"Inactive","type":"error"},{"inputs":[],"name":"InsufficientAmount","type":"error"},{"inputs":[],"name":"LeverageUpdatePending","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"NotOwner","type":"error"},{"inputs":[],"name":"Paused","type":"error"},{"inputs":[],"name":"SameAsCurrent","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"leveragedTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"baseAssetAmount","type":"uint256"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isPaused","type":"bool"}],"name":"PausedSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"currentLeverage","type":"uint256"}],"name":"Rebalanced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"leveragedTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"baseAssetAmount","type":"uint256"}],"name":"Redeemed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"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":"canRebalance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chargeStreamingFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseAmount_","type":"uint256"},{"internalType":"bool","name":"isDeposit_","type":"bool"}],"name":"computePriceImpact","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exchangeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isLong","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseAmountIn_","type":"uint256"},{"internalType":"uint256","name":"minLeveragedTokenAmountOut_","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rebalanceThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"leveragedTokenAmount_","type":"uint256"},{"internalType":"uint256","name":"minBaseAmountReceived_","type":"uint256"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isPaused_","type":"bool"}],"name":"setIsPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"targetAsset","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"targetLeverage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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"}]
Contract Creation Code
61010060405234620005bd5762003a88803803806200001e81620005c2565b92833981019060c081830312620005bd5780516001600160401b0390818111620005bd578362000050918401620005e8565b60209182840151818111620005bd57856200006d918601620005e8565b94604085015190828211620005bd5762000089918601620005e8565b946060850151936080860151958615158703620005bd5760a001516001600160a01b0381169790889003620005bd57845191848311620004bd576003938454936001978886811c96168015620005b2575b848710146200059c578190601f9687811162000546575b508490878311600114620004df57600092620004d3575b505060001982881b1c191690881b1785555b8051868111620004bd5760049182548981811c91168015620004b2575b858210146200049d5790818784931162000447575b508490878311600114620003e057600092620003d4575b505060001982881b1c191690881b1781555b896080528251958611620003bf57600654908782811c92168015620003b4575b838310146200039f575083811162000353575b5080928511600114620002e35750938394918492600095620002d7575b50501b92600019911b1c1916176006555b60c05260e05260a05260405161342d90816200065b823960805181610c29015260a0518181816102370152818161045d0152818161064201528181610a9201528181611304015281816117f1015281816118d1015281816119a701528181611eb5015281816120690152818161217f015281816122d30152818161259b0152818161285301528181612b5e01528181612c1101528181612dab015261327a015260c051818181610184015281816102e50152818161079b015281816113cc01528181611a740152818161240d01526125f7015260e051818181610311015281816107c101528181610e26015281816113f601528181611ab6015261261d0152f35b015193503880620001c5565b92919084601f198116600660005285600020956000905b898383106200033857505050106200031d575b50505050811b01600655620001d6565b01519060f884600019921b161c19169055388080806200030d565b858701518955909701969485019488935090810190620002fa565b6006600052816000208480880160051c82019284891062000395575b0160051c019087905b82811062000388575050620001a8565b6000815501879062000378565b925081926200036f565b602290634e487b7160e01b6000525260246000fd5b91607f169162000195565b604190634e487b7160e01b6000525260246000fd5b01519050388062000163565b908a9350601f1983169185600052866000209260005b8882821062000430575050841162000417575b505050811b01815562000175565b0151600019838a1b60f8161c1916905538808062000409565b8385015186558e97909501949384019301620003f6565b90915083600052846000208780850160051c82019287861062000493575b918c91869594930160051c01915b828110620004835750506200014c565b600081558594508c910162000473565b9250819262000465565b602284634e487b7160e01b6000525260246000fd5b90607f169062000137565b634e487b7160e01b600052604160045260246000fd5b01519050388062000108565b908a9350601f1983169189600052866000209260005b888282106200052f575050841162000516575b505050811b0185556200011a565b0151600019838a1b60f8161c1916905538808062000508565b8385015186558e97909501949384019301620004f5565b90915087600052846000208780850160051c82019287861062000592575b918c91869594930160051c01915b82811062000582575050620000f1565b600081558594508c910162000572565b9250819262000564565b634e487b7160e01b600052602260045260246000fd5b95607f1695620000da565b600080fd5b6040519190601f01601f191682016001600160401b03811183821017620004bd57604052565b919080601f84011215620005bd5782516001600160401b038111620004bd576020906200061e601f8201601f19168301620005c2565b92818452828287010111620005bd5760005b8181106200064657508260009394955001015290565b85810183015184820184015282016200063056fe608060408181526004918236101561001657600080fd5b600092833560e01c91826306fdde0314610f3057508163095ea7b314610e8657816318160ddd14610e675781631b2ef1ca14610e4b578163202a61a114610e0e57816322f3e2d414610de857816323b872dd14610cf4578163240976bf14610bed578163313ce56714610bd15781633ba0b9a914610bb45781633d4403ac14610b885781633dfe9f6a14610b6b578163603d68e214610a6257816370a0823114610a2b5781637cbc237314610a085781637d7c2a1c1461061157816395d89b411461052c578163a06880c01461042c578163a7c658e8146101fa57508063a9059cbb146101ca578063b187bd26146101a7578063d6c946ea1461016d5763dd62ed3e1461012257600080fd5b346101695780600319360112610169578060209261013e61104c565b610146611067565b6001600160a01b0391821683526001865283832091168252845220549051908152f35b5080fd5b5034610169578160031936011261016957602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b503461016957816003193601126101695760209060ff6007541690519015158152f35b50346101695780600319360112610169576020906101f36101e961104c565b6024359033612755565b5160018152f35b8391503461016957826003193601126101695760243590811515809203610428578351633a34e39960e11b8082526020936001600160a01b0392917f00000000000000000000000000000000000000000000000000000000000000008416919086848781865afa9384156103ff578894610409575b50868951809563ec697e1360e01b82528289830152818881610293602482016110cd565b0392165afa9384156103ff5790879189956103e0575b50868a518095819382525afa9182156103d6579360a4928194928a968a926103a7575b508651978896879563062f69dd60e51b875216818601527f000000000000000000000000000000000000000000000000000000000000000060248601523560448501527f0000000000000000000000000000000000000000000000000000000000000000151560648501526084840152165afa90811561039d5783809261035d575b50508351928352151590820152f35b915092508383813d8311610396575b6103768183611255565b81010312610393575061038c81835193016112b9565b848061034e565b80fd5b503d61036c565b84513d85823e3d90fd5b6103c8919250893d8b116103cf575b6103c08183611255565b810190611277565b908b6102cc565b503d6103b6565b88513d89823e3d90fd5b6103f8919550823d84116103cf576103c08183611255565b938a6102a9565b89513d8a823e3d90fd5b610421919450873d89116103cf576103c08183611255565b928961026f565b8280fd5b8284346103935780600319360112610393578151633a34e39960e11b81526020936001600160a01b039190858282817f000000000000000000000000000000000000000000000000000000000000000087165afa918215610522579186929183928692610503575b508651948593849263ec697e1360e01b8452830152816104b6602482016110cd565b0392165afa9182156104f857906104d2926104db575b506122b3565b90519015158152f35b6104f29150843d86116103cf576103c08183611255565b846104cc565b8351903d90823e3d90fd5b61051b919250833d85116103cf576103c08183611255565b9088610494565b85513d86823e3d90fd5b839150346101695781600319360112610169578251918091805461054f81611093565b808652926020926001928084169081156105e2575060011461058b575b610587878961057d828a0383611255565b5191829182611003565b0390f35b815293507f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b8385106105cf5750505050810160200161057d82610587868061056c565b80548686018401529382019381016105b1565b9150506105879795508693506020925061057d94915060ff191682840152151560051b8201019294868061056c565b905034610428578260031936011261042857815163467c9eff60e01b81523382820152602091906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116918481602481865afa9081156108e65787916109cf575b50156109bf57845190633a34e39960e11b80835285838681875afa9283156109965788936109a0575b50858751809463ec697e1360e01b825282888301528185816106c7602482016110cd565b0392165afa928315610996578893610977575b506106e4836122b3565b1561096757865163e9b14a6960e01b815286818781885afa90811561090d57839188918b9161094a575b50878a518094819363171ade6560e11b8352165afa801561090d578990610917575b61075f915061075a61074186612833565b9161075587610750838661255a565b612b3f565b613256565b612bf2565b86519080825286828781885afa91821561090d5787926107fa918b916108f0575b50848a51916319d04c0760e11b8684015281881660248401527f000000000000000000000000000000000000000000000000000000000000000060448401527f000000000000000000000000000000000000000000000000000000000000000015156064840152606483526107f483611239565b166131e0565b508588518096819382525afa9283156108e6579185939161085197959389936108c7575b508551630707bdd360e11b81526001600160a01b0390921693820193845230602085015290968793849291839160400190565b0392165afa9081156108be57849161087d575b6000805160206133d8833981519152935051908152a180f35b90508183813d83116108b7575b6108948183611255565b810103126108b3576000805160206133d8833981519152925190610864565b8380fd5b503d61088a565b513d85823e3d90fd5b6108df919350853d87116103cf576103c08183611255565b913861081e565b86513d89823e3d90fd5b6109079150843d86116103cf576103c08183611255565b38610780565b88513d8b823e3d90fd5b508681813d8311610943575b61092d8183611255565b8101031261093f5761075f9051610730565b8880fd5b503d610923565b6109619150823d84116103cf576103c08183611255565b3861070e565b8651631815312560e11b81528590fd5b61098f919350863d88116103cf576103c08183611255565b91386106da565b87513d8a823e3d90fd5b6109b8919350863d88116103cf576103c08183611255565b91386106a3565b845163ea8e4eb560e01b81528390fd5b90508481813d8311610a01575b6109e68183611255565b810103126109fd576109f7906112b9565b3861067a565b8680fd5b503d6109dc565b50503461016957602090610a24610a1e3661107d565b9061197b565b9051908152f35b5050346101695760203660031901126101695760209181906001600160a01b03610a5361104c565b16815280845220549051908152f35b9050346104285782600319360112610428578151633a34e39960e11b81526020916001600160a01b0391838183817f000000000000000000000000000000000000000000000000000000000000000087165afa8015610b6157849283928892610b42575b508651948593849263ec697e1360e01b845283015281610ae8602482016110cd565b0392165afa918215610b3557610b1593508492610b18575b505061075a610b0e82612833565b9182612b3f565b80f35b610b2e9250803d106103cf576103c08183611255565b3880610b00565b50505051903d90823e3d90fd5b610b5a919250833d85116103cf576103c08183611255565b9038610ac6565b85513d88823e3d90fd5b505034610169578160031936011261016957602090610a246118b1565b50503461016957816003193601126101695780516105879161057d82610bad816110cd565b0383611255565b505034610169578160031936011261016957602090610a246117d1565b5050346101695781600319360112610169576020905160128152f35b91905034610428576020366003190112610428578135918215158093036108b3578151638da5cb5b60e01b81526001600160a01b0360208284817f000000000000000000000000000000000000000000000000000000000000000085165afa918215610cea578692610cc9575b5033911603610cbb57600754908360ff8316151514610cad575060ff191660ff831617600755519081527f40db37ff5c0bdc2c427fbb2078c8f24afea940abac0e3c23bb4ea3bf2da2b21290602090a180f35b825163fbbfd28f60e01b8152fd5b90516330cd747160e01b8152fd5b610ce391925060203d6020116103cf576103c08183611255565b9038610c5a565b84513d88823e3d90fd5b9050823461039357606036600319011261039357610d1061104c565b610d18611067565b916044359360018060a01b038316808352600160205286832033845260205286832054916000198303610d54575b6020886101f3898989612755565b868310610dbc578115610da5573315610d8e575082526001602090815286832033845281529186902090859003905582906101f387610d46565b8751634a1406b160e11b8152908101849052602490fd5b875163e602df0560e01b8152908101849052602490fd5b8751637dc7a0d960e11b8152339181019182526020820193909352604081018790528291506060010390fd5b505034610169578160031936011261016957602090610e056117d1565b15159051908152f35b505034610169578160031936011261016957602090517f000000000000000000000000000000000000000000000000000000000000000015158152f35b50503461016957602090610a24610e613661107d565b906112c6565b5050346101695781600319360112610169576020906002549051908152f35b905034610428578160031936011261042857610ea061104c565b602435903315610f19576001600160a01b0316918215610f0257508083602095338152600187528181208582528752205582519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b8351634a1406b160e11b8152908101859052602490fd5b835163e602df0560e01b8152808401869052602490fd5b8390853461039357806003193601126103935760035481610f5082611093565b80855291602091600191828116908115610fd65750600114610f7e575b610587868861057d82890383611255565b9350600384527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b838510610fc35750505050810160200161057d8261058786610f6d565b8054868601840152938201938101610fa6565b90506105879795508693506020925061057d94915060ff191682840152151560051b820101929486610f6d565b6020808252825181830181905290939260005b82811061103857505060409293506000838284010152601f8019910116010190565b818101860151848201604001528501611016565b600435906001600160a01b038216820361106257565b600080fd5b602435906001600160a01b038216820361106257565b6040906003190112611062576004359060243590565b90600182811c921680156110c3575b60208310146110ad57565b634e487b7160e01b600052602260045260246000fd5b91607f16916110a2565b600654600092916110dd82611093565b8082529160209060019081811690811561115c5750600114611100575b50505050565b9293945060066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f926000935b8585106111495750505060209250010190388080806110fa565b805485850184015293820193810161112f565b92505050602093945060ff929192191683830152151560051b010190388080806110fa565b6006546000929161119182611093565b8082529160209060019081811690811561115c57506001146111b35750505050565b9293945060066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f926000935b8585106111fc5750505060209250010190388080806110fa565b80548585018401529382019381016111e2565b67ffffffffffffffff811161122357604052565b634e487b7160e01b600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761122357604052565b90601f8019910116810190811067ffffffffffffffff82111761122357604052565b9081602091031261106257516001600160a01b03811681036110625790565b919082039182116112a357565b634e487b7160e01b600052601160045260246000fd5b5190811515820361106257565b80156117ca5760ff600754166117b8576112de6117d1565b156117a65760408051633a34e39960e11b80825292919060209060046001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169084848481855afa93841561162757600094611787575b5085519763ec697e1360e01b8952858960249682878301528185816113628b8201611181565b0392165afa98891561177c5760009961175d575b5061138089611e96565b881161174d5761138f89612049565b865181815286818681875afa908115611667578360a48c828d958d95600091611730575b508551968795869463062f69dd60e51b8652168c8501527f00000000000000000000000000000000000000000000000000000000000000008d85015260448401527f00000000000000000000000000000000000000000000000000000000000000001515606484015260016084840152165afa8015611667576000916000916116f5575b506114418b612156565b91600091156116b35761145591508a611296565b670de0b6b3a76400009081810291818304149015171561169f579061147991612293565b995b8a1061168f57865163cdf456e160e01b815286818681875afa908115611667576114dd84928992600091611672575b508a516323b872dd60e01b815233898201908152306020820152604081018e905290948593849260009291849160600190565b0393165af180156116675790879291611632575b508488518095819382525afa91821561162757906115529291600092611608575b50865162343d1360e01b878201526001600160a01b038a16868201908152602081018a90529092906107f49084906040015b03601f198101855284611255565b5033156115f457505090847f25b428dfde728ccfaddad7e29e4ac23c24ed7fd1a6e3e3f91894a9a073f5dfff9261158b8260025461255a565b600255336000526000815282600020828154019055825182815260007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef833393a382519485528401523392a26115e0816122b3565b6115e8575090565b6115f190612567565b90565b600084519163ec442f0560e01b8352820152fd5b611620919250863d88116103cf576103c08183611255565b9038611512565b86513d6000823e3d90fd5b9182813d8311611660575b6116478183611255565b810103126110625761165987926112b9565b50386114f1565b503d61163d565b88513d6000823e3d90fd5b6116899150833d85116103cf576103c08183611255565b386114aa565b8651632ca2f52b60e11b81528490fd5b86601187634e487b7160e01b600052526000fd5b50670de0b6b3a76400008a0290670de0b6b3a763ffff198b8304016116e35750906116dd91612293565b9961147b565b634e487b7160e01b8152601187528790fd5b809250898092503d8311611729575b61170e8183611255565b810103126110625761172387825192016112b9565b38611437565b503d611704565b61174791508d803d106103cf576103c08183611255565b386113b3565b8651632795088960e11b81528490fd5b611775919950863d88116103cf576103c08183611255565b9738611376565b87513d6000823e3d90fd5b61179f919450853d87116103cf576103c08183611255565b923861133c565b604051632e8acb0d60e01b8152600490fd5b6040516313d0ff5960e31b8152600490fd5b5050600090565b604051633a34e39960e11b81526020906001600160a01b039082816004817f000000000000000000000000000000000000000000000000000000000000000086165afa918215611886578391600093611892575b506040519283809263ec697e1360e01b82528460048301528161184a60248201611181565b0392165afa908115611886576115f192600092611869575b5050612156565b61187f9250803d106103cf576103c08183611255565b3880611862565b6040513d6000823e3d90fd5b6118aa919350823d84116103cf576103c08183611255565b9138611825565b60405163e9b14a6960e01b81526020906001600160a01b039082816004817f000000000000000000000000000000000000000000000000000000000000000086165afa801561188657839160009161195e575b50602460405180948193632f5a221b60e01b8352306004840152165afa9182156118865760009261193457505090565b90809250813d8311611957575b61194b8183611255565b81010312611062575190565b503d611941565b6119759150823d84116103cf576103c08183611255565b38611904565b9081156117ca5760408051633a34e39960e11b80825293909260209291906004906001600160a01b03907f000000000000000000000000000000000000000000000000000000000000000082169086888581855afa97881561162757600098611e77575b50868651809963ec697e1360e01b82528287830152818681611a0360248201611181565b0392165afa97881561162757600098611e58575b50611a2188612049565b670de0b6b3a76400009081611a3e611a388b612156565b88612280565b0491611a498a611e96565b8311611e485787519a8b52888b8781875afa9a8b156116675760009b611e23575b5090849291888b857f00000000000000000000000000000000000000000000000000000000000000009e8f845198899463062f69dd60e51b8652168c85015260248401528660448401527f000000000000000000000000000000000000000000000000000000000000000015156064840152608483016000905216815a9160a492fa9b8c15611e185760009460009d611ddb575b50895163e9b14a6960e01b81528b818a818a5afa908115611db35788918d91600091611dbe575b508a8d518094819363458f581560e01b8352165afa908115611db3578390600092611d7f575b50611b59611b5f9387612280565b04612280565b0492611b6b8484611296565b9b611d6e575b508a10611d5e5790611b8689611b8b93612b3f565b612d93565b3315611d475733600052600086528460002054848110611d1b5783929185889233600052600084520387600020558560025403600255600087518781527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef843392a3865163cdf456e160e01b815294859182905afa928315611d10579286928992611c47979695600093611cee575b50865163a9059cbb60e01b8152339281019283526020830194909452929687938492600092849160400190565b0393165af18015611ce357611c8f575b7ff3a670cd3af7d64b488926880889d08a8585a138ff455227af6737339a1ec26292508151938685528401523392a26115e0816122b3565b8383813d8311611cdc575b611ca48183611255565b8101031261106257611cd67ff3a670cd3af7d64b488926880889d08a8585a138ff455227af6737339a1ec262936112b9565b50611c57565b503d611c9a565b82513d6000823e3d90fd5b6000919350611d0990863d88116103cf576103c08183611255565b9290611c1a565b85513d6000823e3d90fd5b855163391434e360e21b8152338186019081526020810192909252604082018690529081906060010390fd5b8451634b637e8f60e11b8152600081850152602490fd5b8651632ca2f52b60e11b81528590fd5b611d78919b611296565b9938611b71565b809392508d8092503d8311611dac575b611d998183611255565b8101031261106257905182611b59611b4b565b503d611d8f565b8b513d6000823e3d90fd5b611dd59150823d84116103cf576103c08183611255565b38611b25565b8a80929e508196503d8311611e11575b611df58183611255565b8101031261106257611e0a8a855195016112b9565b9b38611afe565b503d611deb565b89513d6000823e3d90fd5b859392919b50611e3f908a3d8c116103cf576103c08183611255565b9a909192611a6a565b8751632795088960e11b81528690fd5b611e70919850873d89116103cf576103c08183611255565b9638611a17565b611e8f919850873d89116103cf576103c08183611255565b96386119df565b60408051633a34e39960e11b81529192916001600160a01b03906020907f00000000000000000000000000000000000000000000000000000000000000008316908281600481855afa908115611d10579683918596979860009161202c575b5087518097818094635317f10960e01b82528b600483015282611f1a60448401611181565b911660248301520392165afa938415611d1057600094611ffd575b508160049186519283809263e9b14a6960e01b82525afa908115611d1057908291600091611fe0575b50600486518095819363dd7090f760e01b8352165afa938415611fd65750600093611fa6575b5050670de0b6b3a76400009182038281116112a357611fa291612280565b0490565b9080929350813d8311611fcf575b611fbe8183611255565b810103126110625751903880611f84565b503d611fb4565b513d6000823e3d90fd5b611ff79150823d84116103cf576103c08183611255565b38611f5e565b9093508181813d8311612025575b6120158183611255565b8101031261106257519281611f35565b503d61200b565b6120439150833d85116103cf576103c08183611255565b38611ef5565b604051633a34e39960e11b81526020916001600160a01b039183816004817f000000000000000000000000000000000000000000000000000000000000000087165afa80156118865784926120d392600092612137575b5060405163890914cf60e01b81526001600160a01b03909116600482015230602482015293849283919082906044820190565b0392165afa91821561188657600092612101575b50506120ef57565b60405163609a5b9960e11b8152600490fd5b90809250813d8311612130575b6121188183611255565b8101031261106257612129906112b9565b38806120e7565b503d61210e565b61214f919250843d86116103cf576103c08183611255565b90386120a0565b600254801561227257604051633a34e39960e11b81526020926001600160a01b039184816004817f000000000000000000000000000000000000000000000000000000000000000087165afa80156118865785926121e992600092612253575b50604051630b22635560e31b81526001600160a01b03909116600482015230602482015293849283919082906044820190565b0392165afa92831561188657600093612222575b5050670de0b6b3a7640000918281029281840414901517156112a3576115f191612293565b8181949293943d831161224c575b61223a8183611255565b810103126103935750519038806121fd565b503d612230565b61226b919250843d86116103cf576103c08183611255565b90386121b6565b5050670de0b6b3a764000090565b818102929181159184041417156112a357565b811561229d570490565b634e487b7160e01b600052601260045260246000fd5b60408051633a34e39960e11b808252919260209290916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169260049286818581885afa9081156116675760009161253d575b508751632e86556160e21b81526001600160a01b0387168582019081523060208201529091889183919082900360400190829087165afa90811561166757600091612510575b50156124b257865181815286818581885afa908115611667576000916124f3575b50875163890914cf60e01b81526001600160a01b0387168582019081523060208201529091889183919082900360400190829087165afa908115611667576000916124be575b506124b25785908388518096819382525afa928315611627579185949291612441969492600093612493575b5087516303bf450b60e01b81526001600160a01b039094169184019182523060208301527f000000000000000000000000000000000000000000000000000000000000000060408301529295869384929091839160600190565b0392165afa928315611fd65750600092612465575b50506124606118b1565b111590565b90809250813d831161248c575b61247c8183611255565b8101031261106257513880612456565b503d612472565b6124ab919350853d87116103cf576103c08183611255565b91386123e7565b50505050505050600090565b90508681813d83116124ec575b6124d58183611255565b81010312611062576124e6906112b9565b386123bb565b503d6124cb565b61250a9150873d89116103cf576103c08183611255565b38612375565b90508681813d8311612536575b6125278183611255565b81010312611062575138612354565b503d61251d565b6125549150873d89116103cf576103c08183611255565b3861230e565b919082018092116112a357565b61257d61257382612833565b61075a8382612b3f565b60408051633a34e39960e11b8082526001600160a01b0393602093927f0000000000000000000000000000000000000000000000000000000000000000861692908581600481875afa908115611d105786929161265091600091612738575b50888751916319d04c0760e11b8684015281871660248401527f000000000000000000000000000000000000000000000000000000000000000060448401527f000000000000000000000000000000000000000000000000000000000000000015156064840152606483526107f483611239565b50600485518095819382525afa91821561272d57916126a591859360009261270e575b508451630707bdd360e11b81526001600160a01b03909116600482015230602482015295869283919082906044820190565b0392165afa908115611fd6576000916126d1575b6000805160206133d8833981519152935051908152a1565b90508183813d8311612707575b6126e88183611255565b81010312611062576000805160206133d88339815191529251906126b9565b503d6126de565b612726919250843d86116103cf576103c08183611255565b9038612673565b83513d6000823e3d90fd5b61274f9150843d86116103cf576103c08183611255565b386125dc565b916001600160a01b0380841692831561281a571692831561280157600090838252816020526040822054908382106127cf575091604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652828652038282205586815220818154019055604051908152a3565b60405163391434e360e21b81526001600160a01b03919091166004820152602481019190915260448101839052606490fd5b60405163ec442f0560e01b815260006004820152602490fd5b604051634b637e8f60e11b815260006004820152602490fd5b60055415612b35576040805163e9b14a6960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116936020926004929190848185818a5afa908115611627578392918691600091612b18575b50858851809581936332d514d960e21b8352165afa91821561162757600092612ae9575b508551633a34e39960e11b815290858286818b5afa91821561177c57849392879261291d92600092612aca575b50895163756a2b2960e01b81526001600160a01b039091168882019081523060208201529095869384928391604090910190565b0392165afa91821561162757600092612a99575b5061295f61294c92670de0b6b3a76400009384938492612280565b0461295960055442611296565b90612280565b04818102918183041490151715612a84576301e133809004948515612a7957838391865192838092635ebaf1db60e01b82525afa908115611d1057600091612a5c575b5084516340bd8e6960e11b815293911681848481845afa938415611d1057600094612a2d575b50819085519384809263149ee6a560e01b82525afa938415611fd657506000936129fd575b5050146129f75790565b50600090565b9080929350813d8311612a26575b612a158183611255565b8101031261106257519038806129ed565b503d612a0b565b9093508181813d8311612a55575b612a458183611255565b81010312611062575192816129c8565b503d612a3b565b612a739150843d86116103cf576103c08183611255565b386129a2565b505050505050600090565b601183634e487b7160e01b6000525260246000fd5b91508482813d8311612ac3575b612ab08183611255565b810103126110625790519061295f612931565b503d612aa6565b612ae2919250843d86116103cf576103c08183611255565b90386128e9565b9091508481813d8311612b11575b612b018183611255565b81010312611062575190386128bc565b503d612af7565b612b2f9150823d84116103cf576103c08183611255565b38612898565b5042600555600090565b604051633a34e39960e11b8152916001600160a01b03906020846004817f000000000000000000000000000000000000000000000000000000000000000086165afa90811561188657612bca94600092612bcd575b50604051633a5271f960e01b60208201526001600160a01b03909116602482015260448101939093526107f48360648101611544565b50565b6107f4919250612beb9060203d6020116103cf576103c08183611255565b9190612b94565b908115612d8f5760408051635ebaf1db60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811694916020919082816004818a5afa908115611d1057600496978491600093612d70575b50865163cdf456e160e01b815297889182905afa958615611d1057600096612d46575b50845163095ea7b360e01b81529082166001600160a01b03811660048301526024820185905295909291829184916044918391600091165af18015612d3b57612d07575b5050823b1561106257600092602484928451958693849263decb7bcb60e01b845260048401525af1908115611fd65750612cf8575b5042600555565b612d019061120f565b38612cf1565b81813d8311612d34575b612d1b8183611255565b8101031261106257612d2c906112b9565b503880612cbc565b503d612d11565b84513d6000823e3d90fd5b839283929750612d6581926000963d86116103cf576103c08183611255565b979250929350612c78565b612d88919350823d84116103cf576103c08183611255565b9138612c55565b9050565b6040805163d3dc753960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116936004929091602090818386818a5afa928315611627576000936131a6575b50855163cdf456e160e01b8152828187818b5afa90811561177c5782918291600091613189575b501693169086519163095ea7b360e01b92838152848180612e4b8a868d840160209093929193604081019460018060a01b031681520152565b038160008a5af18015611e1857908591613151575b5060009160448a51809481936353617a2d60e01b83528b8d8401523360248401525af190811561166757600091613124575b508751635ebaf1db60e01b815295848789818d5afa968715611e18576000976130ff575b5090612ec191611296565b9485156130f457169686516340bd8e6960e11b8152838188818c5afa908115611667576000916130c7575b50875163149ee6a560e01b815290848289818d5afa918215611e1857600092613098575b5014612fc6575085519081526001600160a01b03871685820190815260208101859052909282918491908290600090829060400103925af18015611d1057612f92575b5050833b15611062576024600092838551968794859363decb7bcb60e01b85528401525af1908115611fd65750612f875750565b612f909061120f565b565b81813d8311612fbf575b612fa68183611255565b8101031261106257612fb7906112b9565b503880612f53565b503d612f9c565b8683979998508694959693925051938480926361d027b360e01b82525afa91821561177c579185939161303697989593600092613076575b50855163a9059cbb60e01b81526001600160a01b03909216908201908152602081019390935295869283916000918391604090910190565b03925af1908115611fd6575061304a575050565b81813d831161306f575b61305e8183611255565b8101031261106257612bca906112b9565b503d613054565b600091925061309190863d88116103cf576103c08183611255565b9190612ffe565b9091508481813d83116130c0575b6130b08183611255565b8101031261106257519038612f10565b503d6130a6565b90508381813d83116130ed575b6130de8183611255565b81010312611062575138612eec565b503d6130d4565b505050505050505050565b612ec19291975061311c90863d88116103cf576103c08183611255565b969091612eb6565b90508381813d831161314a575b61313b8183611255565b81010312611062575138612e92565b503d613131565b9081813d8311613182575b6131668183611255565b810103126110625760009161317b86926112b9565b5091612e60565b503d61315c565b6131a09150853d87116103cf576103c08183611255565b38612e12565b8281819593953d83116131d9575b6131be8183611255565b81010312610169575190838216820361039357509138612deb565b503d6131b4565b91906000808260208294519101865af43d15613247573d9367ffffffffffffffff8511613233576115f19394604051906132246020601f19601f8401160183611255565b8152809360203d92013e613374565b634e487b7160e01b83526041600452602483fd5b6115f192939150606091613374565b908115612d8f5760408051633c9c616560e01b815290926020916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811691908482600481865afa91821561177c576004938691600094613355575b50885163cdf456e160e01b815294859182905afa92831561177c579185939161331e97989593600093613333575b50855163a9059cbb60e01b81526001600160a01b039092166004830152602482019390935295869283916000919083906044820190565b0393165af1908115611fd6575061304a575050565b600091935061334e90863d88116103cf576103c08183611255565b92906132e7565b61336d919450823d84116103cf576103c08183611255565b92386132b9565b9061339b575080511561338957805190602001fd5b60405163d6bda27560e01b8152600490fd5b815115806133ce575b6133ac575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b156133a456fec306af072396b02bf3a9782c10065cc7ff4aa842934a43f0b76f997b291237c8a2646970667358221220737c6a33c29a811c1c1b114975c89f51ab89006c63bc9e39864e6eaac42f0e9e64736f6c6343000818003300000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e2000000000000000000000000000000000000000000000000000000000000000b425443203578204c6f6e670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005425443354c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034254430000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060408181526004918236101561001657600080fd5b600092833560e01c91826306fdde0314610f3057508163095ea7b314610e8657816318160ddd14610e675781631b2ef1ca14610e4b578163202a61a114610e0e57816322f3e2d414610de857816323b872dd14610cf4578163240976bf14610bed578163313ce56714610bd15781633ba0b9a914610bb45781633d4403ac14610b885781633dfe9f6a14610b6b578163603d68e214610a6257816370a0823114610a2b5781637cbc237314610a085781637d7c2a1c1461061157816395d89b411461052c578163a06880c01461042c578163a7c658e8146101fa57508063a9059cbb146101ca578063b187bd26146101a7578063d6c946ea1461016d5763dd62ed3e1461012257600080fd5b346101695780600319360112610169578060209261013e61104c565b610146611067565b6001600160a01b0391821683526001865283832091168252845220549051908152f35b5080fd5b5034610169578160031936011261016957602090517f0000000000000000000000000000000000000000000000004563918244f400008152f35b503461016957816003193601126101695760209060ff6007541690519015158152f35b50346101695780600319360112610169576020906101f36101e961104c565b6024359033612755565b5160018152f35b8391503461016957826003193601126101695760243590811515809203610428578351633a34e39960e11b8082526020936001600160a01b0392917f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e28416919086848781865afa9384156103ff578894610409575b50868951809563ec697e1360e01b82528289830152818881610293602482016110cd565b0392165afa9384156103ff5790879189956103e0575b50868a518095819382525afa9182156103d6579360a4928194928a968a926103a7575b508651978896879563062f69dd60e51b875216818601527f0000000000000000000000000000000000000000000000004563918244f4000060248601523560448501527f0000000000000000000000000000000000000000000000000000000000000001151560648501526084840152165afa90811561039d5783809261035d575b50508351928352151590820152f35b915092508383813d8311610396575b6103768183611255565b81010312610393575061038c81835193016112b9565b848061034e565b80fd5b503d61036c565b84513d85823e3d90fd5b6103c8919250893d8b116103cf575b6103c08183611255565b810190611277565b908b6102cc565b503d6103b6565b88513d89823e3d90fd5b6103f8919550823d84116103cf576103c08183611255565b938a6102a9565b89513d8a823e3d90fd5b610421919450873d89116103cf576103c08183611255565b928961026f565b8280fd5b8284346103935780600319360112610393578151633a34e39960e11b81526020936001600160a01b039190858282817f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e287165afa918215610522579186929183928692610503575b508651948593849263ec697e1360e01b8452830152816104b6602482016110cd565b0392165afa9182156104f857906104d2926104db575b506122b3565b90519015158152f35b6104f29150843d86116103cf576103c08183611255565b846104cc565b8351903d90823e3d90fd5b61051b919250833d85116103cf576103c08183611255565b9088610494565b85513d86823e3d90fd5b839150346101695781600319360112610169578251918091805461054f81611093565b808652926020926001928084169081156105e2575060011461058b575b610587878961057d828a0383611255565b5191829182611003565b0390f35b815293507f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b8385106105cf5750505050810160200161057d82610587868061056c565b80548686018401529382019381016105b1565b9150506105879795508693506020925061057d94915060ff191682840152151560051b8201019294868061056c565b905034610428578260031936011261042857815163467c9eff60e01b81523382820152602091906001600160a01b037f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e28116918481602481865afa9081156108e65787916109cf575b50156109bf57845190633a34e39960e11b80835285838681875afa9283156109965788936109a0575b50858751809463ec697e1360e01b825282888301528185816106c7602482016110cd565b0392165afa928315610996578893610977575b506106e4836122b3565b1561096757865163e9b14a6960e01b815286818781885afa90811561090d57839188918b9161094a575b50878a518094819363171ade6560e11b8352165afa801561090d578990610917575b61075f915061075a61074186612833565b9161075587610750838661255a565b612b3f565b613256565b612bf2565b86519080825286828781885afa91821561090d5787926107fa918b916108f0575b50848a51916319d04c0760e11b8684015281881660248401527f0000000000000000000000000000000000000000000000004563918244f4000060448401527f000000000000000000000000000000000000000000000000000000000000000115156064840152606483526107f483611239565b166131e0565b508588518096819382525afa9283156108e6579185939161085197959389936108c7575b508551630707bdd360e11b81526001600160a01b0390921693820193845230602085015290968793849291839160400190565b0392165afa9081156108be57849161087d575b6000805160206133d8833981519152935051908152a180f35b90508183813d83116108b7575b6108948183611255565b810103126108b3576000805160206133d8833981519152925190610864565b8380fd5b503d61088a565b513d85823e3d90fd5b6108df919350853d87116103cf576103c08183611255565b913861081e565b86513d89823e3d90fd5b6109079150843d86116103cf576103c08183611255565b38610780565b88513d8b823e3d90fd5b508681813d8311610943575b61092d8183611255565b8101031261093f5761075f9051610730565b8880fd5b503d610923565b6109619150823d84116103cf576103c08183611255565b3861070e565b8651631815312560e11b81528590fd5b61098f919350863d88116103cf576103c08183611255565b91386106da565b87513d8a823e3d90fd5b6109b8919350863d88116103cf576103c08183611255565b91386106a3565b845163ea8e4eb560e01b81528390fd5b90508481813d8311610a01575b6109e68183611255565b810103126109fd576109f7906112b9565b3861067a565b8680fd5b503d6109dc565b50503461016957602090610a24610a1e3661107d565b9061197b565b9051908152f35b5050346101695760203660031901126101695760209181906001600160a01b03610a5361104c565b16815280845220549051908152f35b9050346104285782600319360112610428578151633a34e39960e11b81526020916001600160a01b0391838183817f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e287165afa8015610b6157849283928892610b42575b508651948593849263ec697e1360e01b845283015281610ae8602482016110cd565b0392165afa918215610b3557610b1593508492610b18575b505061075a610b0e82612833565b9182612b3f565b80f35b610b2e9250803d106103cf576103c08183611255565b3880610b00565b50505051903d90823e3d90fd5b610b5a919250833d85116103cf576103c08183611255565b9038610ac6565b85513d88823e3d90fd5b505034610169578160031936011261016957602090610a246118b1565b50503461016957816003193601126101695780516105879161057d82610bad816110cd565b0383611255565b505034610169578160031936011261016957602090610a246117d1565b5050346101695781600319360112610169576020905160128152f35b91905034610428576020366003190112610428578135918215158093036108b3578151638da5cb5b60e01b81526001600160a01b0360208284817f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e285165afa918215610cea578692610cc9575b5033911603610cbb57600754908360ff8316151514610cad575060ff191660ff831617600755519081527f40db37ff5c0bdc2c427fbb2078c8f24afea940abac0e3c23bb4ea3bf2da2b21290602090a180f35b825163fbbfd28f60e01b8152fd5b90516330cd747160e01b8152fd5b610ce391925060203d6020116103cf576103c08183611255565b9038610c5a565b84513d88823e3d90fd5b9050823461039357606036600319011261039357610d1061104c565b610d18611067565b916044359360018060a01b038316808352600160205286832033845260205286832054916000198303610d54575b6020886101f3898989612755565b868310610dbc578115610da5573315610d8e575082526001602090815286832033845281529186902090859003905582906101f387610d46565b8751634a1406b160e11b8152908101849052602490fd5b875163e602df0560e01b8152908101849052602490fd5b8751637dc7a0d960e11b8152339181019182526020820193909352604081018790528291506060010390fd5b505034610169578160031936011261016957602090610e056117d1565b15159051908152f35b505034610169578160031936011261016957602090517f000000000000000000000000000000000000000000000000000000000000000115158152f35b50503461016957602090610a24610e613661107d565b906112c6565b5050346101695781600319360112610169576020906002549051908152f35b905034610428578160031936011261042857610ea061104c565b602435903315610f19576001600160a01b0316918215610f0257508083602095338152600187528181208582528752205582519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b8351634a1406b160e11b8152908101859052602490fd5b835163e602df0560e01b8152808401869052602490fd5b8390853461039357806003193601126103935760035481610f5082611093565b80855291602091600191828116908115610fd65750600114610f7e575b610587868861057d82890383611255565b9350600384527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b838510610fc35750505050810160200161057d8261058786610f6d565b8054868601840152938201938101610fa6565b90506105879795508693506020925061057d94915060ff191682840152151560051b820101929486610f6d565b6020808252825181830181905290939260005b82811061103857505060409293506000838284010152601f8019910116010190565b818101860151848201604001528501611016565b600435906001600160a01b038216820361106257565b600080fd5b602435906001600160a01b038216820361106257565b6040906003190112611062576004359060243590565b90600182811c921680156110c3575b60208310146110ad57565b634e487b7160e01b600052602260045260246000fd5b91607f16916110a2565b600654600092916110dd82611093565b8082529160209060019081811690811561115c5750600114611100575b50505050565b9293945060066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f926000935b8585106111495750505060209250010190388080806110fa565b805485850184015293820193810161112f565b92505050602093945060ff929192191683830152151560051b010190388080806110fa565b6006546000929161119182611093565b8082529160209060019081811690811561115c57506001146111b35750505050565b9293945060066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f926000935b8585106111fc5750505060209250010190388080806110fa565b80548585018401529382019381016111e2565b67ffffffffffffffff811161122357604052565b634e487b7160e01b600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761122357604052565b90601f8019910116810190811067ffffffffffffffff82111761122357604052565b9081602091031261106257516001600160a01b03811681036110625790565b919082039182116112a357565b634e487b7160e01b600052601160045260246000fd5b5190811515820361106257565b80156117ca5760ff600754166117b8576112de6117d1565b156117a65760408051633a34e39960e11b80825292919060209060046001600160a01b037f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e281169084848481855afa93841561162757600094611787575b5085519763ec697e1360e01b8952858960249682878301528185816113628b8201611181565b0392165afa98891561177c5760009961175d575b5061138089611e96565b881161174d5761138f89612049565b865181815286818681875afa908115611667578360a48c828d958d95600091611730575b508551968795869463062f69dd60e51b8652168c8501527f0000000000000000000000000000000000000000000000004563918244f400008d85015260448401527f00000000000000000000000000000000000000000000000000000000000000011515606484015260016084840152165afa8015611667576000916000916116f5575b506114418b612156565b91600091156116b35761145591508a611296565b670de0b6b3a76400009081810291818304149015171561169f579061147991612293565b995b8a1061168f57865163cdf456e160e01b815286818681875afa908115611667576114dd84928992600091611672575b508a516323b872dd60e01b815233898201908152306020820152604081018e905290948593849260009291849160600190565b0393165af180156116675790879291611632575b508488518095819382525afa91821561162757906115529291600092611608575b50865162343d1360e01b878201526001600160a01b038a16868201908152602081018a90529092906107f49084906040015b03601f198101855284611255565b5033156115f457505090847f25b428dfde728ccfaddad7e29e4ac23c24ed7fd1a6e3e3f91894a9a073f5dfff9261158b8260025461255a565b600255336000526000815282600020828154019055825182815260007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef833393a382519485528401523392a26115e0816122b3565b6115e8575090565b6115f190612567565b90565b600084519163ec442f0560e01b8352820152fd5b611620919250863d88116103cf576103c08183611255565b9038611512565b86513d6000823e3d90fd5b9182813d8311611660575b6116478183611255565b810103126110625761165987926112b9565b50386114f1565b503d61163d565b88513d6000823e3d90fd5b6116899150833d85116103cf576103c08183611255565b386114aa565b8651632ca2f52b60e11b81528490fd5b86601187634e487b7160e01b600052526000fd5b50670de0b6b3a76400008a0290670de0b6b3a763ffff198b8304016116e35750906116dd91612293565b9961147b565b634e487b7160e01b8152601187528790fd5b809250898092503d8311611729575b61170e8183611255565b810103126110625761172387825192016112b9565b38611437565b503d611704565b61174791508d803d106103cf576103c08183611255565b386113b3565b8651632795088960e11b81528490fd5b611775919950863d88116103cf576103c08183611255565b9738611376565b87513d6000823e3d90fd5b61179f919450853d87116103cf576103c08183611255565b923861133c565b604051632e8acb0d60e01b8152600490fd5b6040516313d0ff5960e31b8152600490fd5b5050600090565b604051633a34e39960e11b81526020906001600160a01b039082816004817f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e286165afa918215611886578391600093611892575b506040519283809263ec697e1360e01b82528460048301528161184a60248201611181565b0392165afa908115611886576115f192600092611869575b5050612156565b61187f9250803d106103cf576103c08183611255565b3880611862565b6040513d6000823e3d90fd5b6118aa919350823d84116103cf576103c08183611255565b9138611825565b60405163e9b14a6960e01b81526020906001600160a01b039082816004817f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e286165afa801561188657839160009161195e575b50602460405180948193632f5a221b60e01b8352306004840152165afa9182156118865760009261193457505090565b90809250813d8311611957575b61194b8183611255565b81010312611062575190565b503d611941565b6119759150823d84116103cf576103c08183611255565b38611904565b9081156117ca5760408051633a34e39960e11b80825293909260209291906004906001600160a01b03907f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e282169086888581855afa97881561162757600098611e77575b50868651809963ec697e1360e01b82528287830152818681611a0360248201611181565b0392165afa97881561162757600098611e58575b50611a2188612049565b670de0b6b3a76400009081611a3e611a388b612156565b88612280565b0491611a498a611e96565b8311611e485787519a8b52888b8781875afa9a8b156116675760009b611e23575b5090849291888b857f0000000000000000000000000000000000000000000000004563918244f400009e8f845198899463062f69dd60e51b8652168c85015260248401528660448401527f000000000000000000000000000000000000000000000000000000000000000115156064840152608483016000905216815a9160a492fa9b8c15611e185760009460009d611ddb575b50895163e9b14a6960e01b81528b818a818a5afa908115611db35788918d91600091611dbe575b508a8d518094819363458f581560e01b8352165afa908115611db3578390600092611d7f575b50611b59611b5f9387612280565b04612280565b0492611b6b8484611296565b9b611d6e575b508a10611d5e5790611b8689611b8b93612b3f565b612d93565b3315611d475733600052600086528460002054848110611d1b5783929185889233600052600084520387600020558560025403600255600087518781527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef843392a3865163cdf456e160e01b815294859182905afa928315611d10579286928992611c47979695600093611cee575b50865163a9059cbb60e01b8152339281019283526020830194909452929687938492600092849160400190565b0393165af18015611ce357611c8f575b7ff3a670cd3af7d64b488926880889d08a8585a138ff455227af6737339a1ec26292508151938685528401523392a26115e0816122b3565b8383813d8311611cdc575b611ca48183611255565b8101031261106257611cd67ff3a670cd3af7d64b488926880889d08a8585a138ff455227af6737339a1ec262936112b9565b50611c57565b503d611c9a565b82513d6000823e3d90fd5b6000919350611d0990863d88116103cf576103c08183611255565b9290611c1a565b85513d6000823e3d90fd5b855163391434e360e21b8152338186019081526020810192909252604082018690529081906060010390fd5b8451634b637e8f60e11b8152600081850152602490fd5b8651632ca2f52b60e11b81528590fd5b611d78919b611296565b9938611b71565b809392508d8092503d8311611dac575b611d998183611255565b8101031261106257905182611b59611b4b565b503d611d8f565b8b513d6000823e3d90fd5b611dd59150823d84116103cf576103c08183611255565b38611b25565b8a80929e508196503d8311611e11575b611df58183611255565b8101031261106257611e0a8a855195016112b9565b9b38611afe565b503d611deb565b89513d6000823e3d90fd5b859392919b50611e3f908a3d8c116103cf576103c08183611255565b9a909192611a6a565b8751632795088960e11b81528690fd5b611e70919850873d89116103cf576103c08183611255565b9638611a17565b611e8f919850873d89116103cf576103c08183611255565b96386119df565b60408051633a34e39960e11b81529192916001600160a01b03906020907f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e28316908281600481855afa908115611d10579683918596979860009161202c575b5087518097818094635317f10960e01b82528b600483015282611f1a60448401611181565b911660248301520392165afa938415611d1057600094611ffd575b508160049186519283809263e9b14a6960e01b82525afa908115611d1057908291600091611fe0575b50600486518095819363dd7090f760e01b8352165afa938415611fd65750600093611fa6575b5050670de0b6b3a76400009182038281116112a357611fa291612280565b0490565b9080929350813d8311611fcf575b611fbe8183611255565b810103126110625751903880611f84565b503d611fb4565b513d6000823e3d90fd5b611ff79150823d84116103cf576103c08183611255565b38611f5e565b9093508181813d8311612025575b6120158183611255565b8101031261106257519281611f35565b503d61200b565b6120439150833d85116103cf576103c08183611255565b38611ef5565b604051633a34e39960e11b81526020916001600160a01b039183816004817f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e287165afa80156118865784926120d392600092612137575b5060405163890914cf60e01b81526001600160a01b03909116600482015230602482015293849283919082906044820190565b0392165afa91821561188657600092612101575b50506120ef57565b60405163609a5b9960e11b8152600490fd5b90809250813d8311612130575b6121188183611255565b8101031261106257612129906112b9565b38806120e7565b503d61210e565b61214f919250843d86116103cf576103c08183611255565b90386120a0565b600254801561227257604051633a34e39960e11b81526020926001600160a01b039184816004817f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e287165afa80156118865785926121e992600092612253575b50604051630b22635560e31b81526001600160a01b03909116600482015230602482015293849283919082906044820190565b0392165afa92831561188657600093612222575b5050670de0b6b3a7640000918281029281840414901517156112a3576115f191612293565b8181949293943d831161224c575b61223a8183611255565b810103126103935750519038806121fd565b503d612230565b61226b919250843d86116103cf576103c08183611255565b90386121b6565b5050670de0b6b3a764000090565b818102929181159184041417156112a357565b811561229d570490565b634e487b7160e01b600052601260045260246000fd5b60408051633a34e39960e11b808252919260209290916001600160a01b037f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e281169260049286818581885afa9081156116675760009161253d575b508751632e86556160e21b81526001600160a01b0387168582019081523060208201529091889183919082900360400190829087165afa90811561166757600091612510575b50156124b257865181815286818581885afa908115611667576000916124f3575b50875163890914cf60e01b81526001600160a01b0387168582019081523060208201529091889183919082900360400190829087165afa908115611667576000916124be575b506124b25785908388518096819382525afa928315611627579185949291612441969492600093612493575b5087516303bf450b60e01b81526001600160a01b039094169184019182523060208301527f0000000000000000000000000000000000000000000000004563918244f4000060408301529295869384929091839160600190565b0392165afa928315611fd65750600092612465575b50506124606118b1565b111590565b90809250813d831161248c575b61247c8183611255565b8101031261106257513880612456565b503d612472565b6124ab919350853d87116103cf576103c08183611255565b91386123e7565b50505050505050600090565b90508681813d83116124ec575b6124d58183611255565b81010312611062576124e6906112b9565b386123bb565b503d6124cb565b61250a9150873d89116103cf576103c08183611255565b38612375565b90508681813d8311612536575b6125278183611255565b81010312611062575138612354565b503d61251d565b6125549150873d89116103cf576103c08183611255565b3861230e565b919082018092116112a357565b61257d61257382612833565b61075a8382612b3f565b60408051633a34e39960e11b8082526001600160a01b0393602093927f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e2861692908581600481875afa908115611d105786929161265091600091612738575b50888751916319d04c0760e11b8684015281871660248401527f0000000000000000000000000000000000000000000000004563918244f4000060448401527f000000000000000000000000000000000000000000000000000000000000000115156064840152606483526107f483611239565b50600485518095819382525afa91821561272d57916126a591859360009261270e575b508451630707bdd360e11b81526001600160a01b03909116600482015230602482015295869283919082906044820190565b0392165afa908115611fd6576000916126d1575b6000805160206133d8833981519152935051908152a1565b90508183813d8311612707575b6126e88183611255565b81010312611062576000805160206133d88339815191529251906126b9565b503d6126de565b612726919250843d86116103cf576103c08183611255565b9038612673565b83513d6000823e3d90fd5b61274f9150843d86116103cf576103c08183611255565b386125dc565b916001600160a01b0380841692831561281a571692831561280157600090838252816020526040822054908382106127cf575091604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652828652038282205586815220818154019055604051908152a3565b60405163391434e360e21b81526001600160a01b03919091166004820152602481019190915260448101839052606490fd5b60405163ec442f0560e01b815260006004820152602490fd5b604051634b637e8f60e11b815260006004820152602490fd5b60055415612b35576040805163e9b14a6960e01b81526001600160a01b037f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e28116936020926004929190848185818a5afa908115611627578392918691600091612b18575b50858851809581936332d514d960e21b8352165afa91821561162757600092612ae9575b508551633a34e39960e11b815290858286818b5afa91821561177c57849392879261291d92600092612aca575b50895163756a2b2960e01b81526001600160a01b039091168882019081523060208201529095869384928391604090910190565b0392165afa91821561162757600092612a99575b5061295f61294c92670de0b6b3a76400009384938492612280565b0461295960055442611296565b90612280565b04818102918183041490151715612a84576301e133809004948515612a7957838391865192838092635ebaf1db60e01b82525afa908115611d1057600091612a5c575b5084516340bd8e6960e11b815293911681848481845afa938415611d1057600094612a2d575b50819085519384809263149ee6a560e01b82525afa938415611fd657506000936129fd575b5050146129f75790565b50600090565b9080929350813d8311612a26575b612a158183611255565b8101031261106257519038806129ed565b503d612a0b565b9093508181813d8311612a55575b612a458183611255565b81010312611062575192816129c8565b503d612a3b565b612a739150843d86116103cf576103c08183611255565b386129a2565b505050505050600090565b601183634e487b7160e01b6000525260246000fd5b91508482813d8311612ac3575b612ab08183611255565b810103126110625790519061295f612931565b503d612aa6565b612ae2919250843d86116103cf576103c08183611255565b90386128e9565b9091508481813d8311612b11575b612b018183611255565b81010312611062575190386128bc565b503d612af7565b612b2f9150823d84116103cf576103c08183611255565b38612898565b5042600555600090565b604051633a34e39960e11b8152916001600160a01b03906020846004817f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e286165afa90811561188657612bca94600092612bcd575b50604051633a5271f960e01b60208201526001600160a01b03909116602482015260448101939093526107f48360648101611544565b50565b6107f4919250612beb9060203d6020116103cf576103c08183611255565b9190612b94565b908115612d8f5760408051635ebaf1db60e01b81526001600160a01b037f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e2811694916020919082816004818a5afa908115611d1057600496978491600093612d70575b50865163cdf456e160e01b815297889182905afa958615611d1057600096612d46575b50845163095ea7b360e01b81529082166001600160a01b03811660048301526024820185905295909291829184916044918391600091165af18015612d3b57612d07575b5050823b1561106257600092602484928451958693849263decb7bcb60e01b845260048401525af1908115611fd65750612cf8575b5042600555565b612d019061120f565b38612cf1565b81813d8311612d34575b612d1b8183611255565b8101031261106257612d2c906112b9565b503880612cbc565b503d612d11565b84513d6000823e3d90fd5b839283929750612d6581926000963d86116103cf576103c08183611255565b979250929350612c78565b612d88919350823d84116103cf576103c08183611255565b9138612c55565b9050565b6040805163d3dc753960e01b81526001600160a01b037f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e28116936004929091602090818386818a5afa928315611627576000936131a6575b50855163cdf456e160e01b8152828187818b5afa90811561177c5782918291600091613189575b501693169086519163095ea7b360e01b92838152848180612e4b8a868d840160209093929193604081019460018060a01b031681520152565b038160008a5af18015611e1857908591613151575b5060009160448a51809481936353617a2d60e01b83528b8d8401523360248401525af190811561166757600091613124575b508751635ebaf1db60e01b815295848789818d5afa968715611e18576000976130ff575b5090612ec191611296565b9485156130f457169686516340bd8e6960e11b8152838188818c5afa908115611667576000916130c7575b50875163149ee6a560e01b815290848289818d5afa918215611e1857600092613098575b5014612fc6575085519081526001600160a01b03871685820190815260208101859052909282918491908290600090829060400103925af18015611d1057612f92575b5050833b15611062576024600092838551968794859363decb7bcb60e01b85528401525af1908115611fd65750612f875750565b612f909061120f565b565b81813d8311612fbf575b612fa68183611255565b8101031261106257612fb7906112b9565b503880612f53565b503d612f9c565b8683979998508694959693925051938480926361d027b360e01b82525afa91821561177c579185939161303697989593600092613076575b50855163a9059cbb60e01b81526001600160a01b03909216908201908152602081019390935295869283916000918391604090910190565b03925af1908115611fd6575061304a575050565b81813d831161306f575b61305e8183611255565b8101031261106257612bca906112b9565b503d613054565b600091925061309190863d88116103cf576103c08183611255565b9190612ffe565b9091508481813d83116130c0575b6130b08183611255565b8101031261106257519038612f10565b503d6130a6565b90508381813d83116130ed575b6130de8183611255565b81010312611062575138612eec565b503d6130d4565b505050505050505050565b612ec19291975061311c90863d88116103cf576103c08183611255565b969091612eb6565b90508381813d831161314a575b61313b8183611255565b81010312611062575138612e92565b503d613131565b9081813d8311613182575b6131668183611255565b810103126110625760009161317b86926112b9565b5091612e60565b503d61315c565b6131a09150853d87116103cf576103c08183611255565b38612e12565b8281819593953d83116131d9575b6131be8183611255565b81010312610169575190838216820361039357509138612deb565b503d6131b4565b91906000808260208294519101865af43d15613247573d9367ffffffffffffffff8511613233576115f19394604051906132246020601f19601f8401160183611255565b8152809360203d92013e613374565b634e487b7160e01b83526041600452602483fd5b6115f192939150606091613374565b908115612d8f5760408051633c9c616560e01b815290926020916001600160a01b037f000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e2811691908482600481865afa91821561177c576004938691600094613355575b50885163cdf456e160e01b815294859182905afa92831561177c579185939161331e97989593600093613333575b50855163a9059cbb60e01b81526001600160a01b039092166004830152602482019390935295869283916000919083906044820190565b0393165af1908115611fd6575061304a575050565b600091935061334e90863d88116103cf576103c08183611255565b92906132e7565b61336d919450823d84116103cf576103c08183611255565b92386132b9565b9061339b575080511561338957805190602001fd5b60405163d6bda27560e01b8152600490fd5b815115806133ce575b6133ac575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b156133a456fec306af072396b02bf3a9782c10065cc7ff4aa842934a43f0b76f997b291237c8a2646970667358221220737c6a33c29a811c1c1b114975c89f51ab89006c63bc9e39864e6eaac42f0e9e64736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e2000000000000000000000000000000000000000000000000000000000000000b425443203578204c6f6e670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005425443354c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034254430000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : name_ (string): BTC 5x Long
Arg [1] : symbol_ (string): BTC5L
Arg [2] : targetAsset_ (string): BTC
Arg [3] : targetLeverage_ (uint256): 5000000000000000000
Arg [4] : isLong_ (bool): True
Arg [5] : addressProvider_ (address): 0xbaA87EcC5Dd76526b51AB7FD2d0c814EB967E2E2
-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [3] : 0000000000000000000000000000000000000000000000004563918244f40000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [5] : 000000000000000000000000baa87ecc5dd76526b51ab7fd2d0c814eb967e2e2
Arg [6] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [7] : 425443203578204c6f6e67000000000000000000000000000000000000000000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [9] : 425443354c000000000000000000000000000000000000000000000000000000
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [11] : 4254430000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
OP | 100.00% | $0.790584 | 6,816.8847 | $5,389.32 |
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.