Feature Tip: Add private address tag to any address under My Name Tag !
ERC-20
Finance
Overview
Max Total Supply
9,898,878.596953253203803899 stHOPE
Holders
129 (0.00%)
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 18 Decimals)
Balance
0.007902693597715647 stHOPEValue
$0.00Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
StakingHOPE
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: LGPL-3.0 pragma solidity 0.8.17; import "./interfaces/IStaking.sol"; import "./gauges/AbsGauge.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {TransferHelper} from "light-lib/contracts/TransferHelper.sol"; contract StakingHOPE is IStaking, ERC20, AbsGauge { uint256 internal constant _LOCK_TIME = 28; // permit2 contract address public permit2Address; struct UnstakingOrderDetail { uint256 amount; uint256 redeemTime; bool redeemExecuted; } struct UnstakingOrderSummary { uint256 notRedeemAmount; uint256 index; mapping(uint256 => UnstakingOrderDetail) orderMap; } uint256 public totalNotRedeemAmount; mapping(address => UnstakingOrderSummary) public unstakingMap; mapping(uint256 => uint256) public unstakingDayHistory; uint256 private _unstakeTotal; constructor(address _stakedToken, address _minter, address _permit2Address) ERC20("staked HOPE", "stHOPE") { require(_stakedToken != address(0), "CE000"); require(_permit2Address != address(0), "CE000"); _init(_stakedToken, _minter, _msgSender()); permit2Address = _permit2Address; } /*** * @notice Stake HOPE to get stHOPE * * @param amount * @param nonce * @param deadline * @param signature */ function staking(uint256 amount, uint256 nonce, uint256 deadline, bytes memory signature) external override returns (bool) { require(amount != 0, "CE002"); address staker = _msgSender(); // checking amount uint256 balanceOfUser = IERC20(lpToken).balanceOf(staker); require(balanceOfUser >= amount, "CE002"); TransferHelper.doTransferIn(permit2Address, lpToken, amount, staker, nonce, deadline, signature); _checkpoint(staker); _mint(staker, amount); _updateLiquidityLimit(staker, lpBalanceOf(staker), lpTotalSupply()); emit Staking(staker, amount); return true; } /*** * @notice unstaking the staked amount * The unstaking process takes 28 days to complete. During this period, * the unstaked $HOPE cannot be traded, and no staking rewards are accrued. * * @param * @return */ function unstaking(uint256 amount) external { require(amount != 0, "CE002"); address staker = _msgSender(); // checking amount uint256 balanceOfUser = lpBalanceOf(staker); require(balanceOfUser >= amount, "CE002"); _checkpoint(staker); uint256 nextDayTime = ((block.timestamp + _DAY) / _DAY) * _DAY; // lock 28 days uint256 redeemTime = nextDayTime + _DAY * _LOCK_TIME; unstakingDayHistory[nextDayTime] = unstakingDayHistory[nextDayTime] + amount; _unstakeTotal = _unstakeTotal + amount; UnstakingOrderSummary storage summaryMap = unstakingMap[staker]; summaryMap.notRedeemAmount = summaryMap.notRedeemAmount + amount; summaryMap.index = summaryMap.index + 1; summaryMap.orderMap[summaryMap.index] = UnstakingOrderDetail(amount, redeemTime, false); totalNotRedeemAmount += amount; _updateLiquidityLimit(staker, lpBalanceOf(staker), lpTotalSupply()); emit Unstaking(staker, amount); } /*** * @notice get unstaking amount * * @return */ function unstakingBalanceOf(address _addr) public view returns (uint256) { uint256 _unstakingAmount = 0; UnstakingOrderSummary storage summaryMap = unstakingMap[_addr]; for (uint256 _index = summaryMap.index; _index > 0; _index--) { if (summaryMap.orderMap[_index].redeemExecuted) { break; } if (block.timestamp < summaryMap.orderMap[_index].redeemTime) { _unstakingAmount += summaryMap.orderMap[_index].amount; } } return _unstakingAmount; } function unstakingTotal() public view returns (uint256) { uint256 _unstakingTotal = 0; uint256 nextDayTime = ((block.timestamp + _DAY) / _DAY) * _DAY; for (uint256 i = 0; i < _LOCK_TIME; i++) { _unstakingTotal += unstakingDayHistory[nextDayTime - _DAY * i]; } return _unstakingTotal; } /*** * @notice get can redeem amount * * @param * @return */ function unstakedBalanceOf(address _addr) public view returns (uint256) { uint256 amountToRedeem = 0; UnstakingOrderSummary storage summaryMap = unstakingMap[_addr]; for (uint256 _index = summaryMap.index; _index > 0; _index--) { if (summaryMap.orderMap[_index].redeemExecuted) { break; } if (block.timestamp >= summaryMap.orderMap[_index].redeemTime) { amountToRedeem += summaryMap.orderMap[_index].amount; } } return amountToRedeem; } function unstakedTotal() external view returns (uint256) { return _unstakeTotal - unstakingTotal(); } /*** * @notice Redeem all amounts to your account * * @param * @return */ function redeemAll() external override returns (uint256) { address redeemer = _msgSender(); uint256 amountToRedeem = unstakedBalanceOf(redeemer); require(amountToRedeem != 0, "CE002"); _checkpoint(redeemer); UnstakingOrderSummary storage summaryMap = unstakingMap[redeemer]; for (uint256 _index = summaryMap.index; _index > 0; _index--) { if (summaryMap.orderMap[_index].redeemExecuted) { break; } if (block.timestamp >= summaryMap.orderMap[_index].redeemTime) { uint256 amount = summaryMap.orderMap[_index].amount; summaryMap.orderMap[_index].redeemExecuted = true; summaryMap.notRedeemAmount = summaryMap.notRedeemAmount - amount; totalNotRedeemAmount -= amount; } } _burn(redeemer, amountToRedeem); TransferHelper.doTransferOut(lpToken, redeemer, amountToRedeem); _updateLiquidityLimit(redeemer, lpBalanceOf(redeemer), lpTotalSupply()); _unstakeTotal = _unstakeTotal - amountToRedeem; emit Redeem(redeemer, amountToRedeem); return amountToRedeem; } /*** * @notice redeem amount by index(Prevent the number of unstaking too much to redeem) * * @param maxIndex * @return */ function redeemByMaxIndex(uint256 maxIndex) external returns (uint256) { address redeemer = _msgSender(); uint256 allToRedeemAmount = unstakedBalanceOf(redeemer); require(allToRedeemAmount != 0, "CE002"); uint256 amountToRedeem = 0; _checkpoint(redeemer); UnstakingOrderSummary storage summaryMap = unstakingMap[redeemer]; uint256 indexCount = 0; for (uint256 _index = 1; _index <= summaryMap.index; _index++) { if (indexCount >= maxIndex) { break; } if (block.timestamp >= summaryMap.orderMap[_index].redeemTime && !summaryMap.orderMap[_index].redeemExecuted) { uint256 amount = summaryMap.orderMap[_index].amount; amountToRedeem += amount; summaryMap.orderMap[_index].redeemExecuted = true; summaryMap.notRedeemAmount = summaryMap.notRedeemAmount - amount; totalNotRedeemAmount -= amount; indexCount++; } } if (amountToRedeem > 0) { _burn(redeemer, amountToRedeem); TransferHelper.doTransferOut(lpToken, redeemer, amountToRedeem); _updateLiquidityLimit(redeemer, lpBalanceOf(redeemer), lpTotalSupply()); _unstakeTotal = _unstakeTotal - amountToRedeem; emit Redeem(redeemer, amountToRedeem); } return amountToRedeem; } /** * @dev Set permit2 address, onlyOwner * @param newAddress New permit2 address */ function setPermit2Address(address newAddress) external onlyOwner { require(newAddress != address(0), "CE000"); address oldAddress = permit2Address; permit2Address = newAddress; emit SetPermit2Address(oldAddress, newAddress); } function lpBalanceOf(address _addr) public view override returns (uint256) { return super.balanceOf(_addr) - unstakingMap[_addr].notRedeemAmount; } function lpTotalSupply() public view override returns (uint256) { return super.totalSupply() - totalNotRedeemAmount; } /*** * @notice Transfers Gauge deposit (stHOPE) from the caller to _to. * * @param to * @param amount * @return bool */ function transfer(address _to, uint256 _amount) public virtual override returns (bool) { address owner = _msgSender(); uint256 fromBalance = lpBalanceOf(owner); require(fromBalance >= _amount, "CE002"); _checkpoint(owner); _checkpoint(_to); bool result = super.transfer(_to, _amount); _updateLiquidityLimit(owner, lpBalanceOf(owner), lpTotalSupply()); _updateLiquidityLimit(_to, lpBalanceOf(_to), lpTotalSupply()); return result; } /*** * @notice Tansfers a Gauge deposit between _from and _to. * * @param from * @param to * @param amount * @return bool */ function transferFrom(address _from, address _to, uint256 _amount) public override returns (bool) { uint256 fromBalance = lpBalanceOf(_from); require(fromBalance >= _amount, "CE002"); _checkpoint(_from); _checkpoint(_to); bool result = super.transferFrom(_from, _to, _amount); _updateLiquidityLimit(_from, lpBalanceOf(_from), lpTotalSupply()); _updateLiquidityLimit(_to, lpBalanceOf(_to), lpTotalSupply()); return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./Ownable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() external { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.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}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * 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]. * * 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 ERC20 * 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 EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * 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 override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override 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 value {ERC20} uses, unless this function is * 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 override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override 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 `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` 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 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. 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 `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `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. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer( address from, address to, uint256 amount ) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` 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. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 amount ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ 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 v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ 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 amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: LGPL-3.0 pragma solidity 0.8.17; import "@openzeppelin/contracts/access/Ownable2Step.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import "../interfaces/ILT.sol"; import "../interfaces/IGaugeController.sol"; import "../interfaces/IVotingEscrow.sol"; import "../interfaces/IMinter.sol"; import "light-lib/contracts/LibTime.sol"; abstract contract AbsGauge is Ownable2Step { event Deposit(address indexed provider, uint256 value); event Withdraw(address indexed provider, uint256 value); event UpdateLiquidityLimit( address user, uint256 originalBalance, uint256 originalSupply, uint256 workingBalance, uint256 workingSupply, uint256 votingBalance, uint256 votingTotal ); event SetPermit2Address(address oldAddress, address newAddress); uint256 internal constant _TOKENLESS_PRODUCTION = 40; uint256 internal constant _DAY = 86400; uint256 internal constant _WEEK = _DAY * 7; bool public isKilled; // pool lp token address public lpToken; //Contracts IMinter public minter; // lt_token ILT public ltToken; //IERC20 public template; IGaugeController public controller; IVotingEscrow public votingEscrow; uint256 public futureEpochTime; mapping(address => uint256) public workingBalances; uint256 public workingSupply; // The goal is to be able to calculate ∫(rate * balance / totalSupply dt) from 0 till checkpoint // All values are kept in units of being multiplied by 1e18 uint256 public period; //modified from "int256 public period" since it never be minus. // uint256[100000000000000000000000000000] public period_timestamp; mapping(uint256 => uint256) public periodTimestamp; //uint256[100_000_000_000_000_000_000_000_000_000] public periodTimestamp; // 1e18 * ∫(rate(t) / totalSupply(t) dt) from 0 till checkpoint // bump epoch when rate() changes mapping(uint256 => uint256) integrateInvSupply; // 1e18 * ∫(rate(t) / totalSupply(t) dt) from (last_action) till checkpoint mapping(address => uint256) public integrateInvSupplyOf; mapping(address => uint256) public integrateCheckpointOf; // ∫(balance * rate(t) / totalSupply(t) dt) from 0 till checkpoint // Units rate * t = already number of coins per address to issue mapping(address => uint256) public integrateFraction; //Mintable Token amount (include minted amount) uint256 public inflationRate; /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; function _init(address _lpAddr, address _minter, address _owner) internal { require(_lpAddr != address(0), "CE000"); require(_minter != address(0), "CE000"); require(_owner != address(0), "CE000"); require(!_initialized, "Initializable: contract is already initialized"); _initialized = true; _transferOwnership(_owner); lpToken = _lpAddr; minter = IMinter(_minter); address _ltToken = minter.token(); ltToken = ILT(_ltToken); controller = IGaugeController(minter.controller()); votingEscrow = IVotingEscrow(controller.votingEscrow()); periodTimestamp[0] = block.timestamp; inflationRate = ltToken.rate(); futureEpochTime = ltToken.futureEpochTimeWrite(); } /*** * @notice Calculate limits which depend on the amount of lp Token per-user. * Effectively it calculates working balances to apply amplification * of LT production by LT * @param _addr User address * @param _l User's amount of liquidity (LP tokens) * @param _L Total amount of liquidity (LP tokens) */ function _updateLiquidityLimit(address _addr, uint256 _l, uint256 _L) internal { // To be called after totalSupply is updated uint256 _votingBalance = votingEscrow.balanceOfAtTime(_addr, block.timestamp); uint256 _votingTotal = votingEscrow.totalSupplyAtTime(block.timestamp); uint256 _lim = (_l * _TOKENLESS_PRODUCTION) / 100; if (_votingTotal > 0) { // 0.4 * _l + 0.6 * _L * balance/total _lim += (_L * _votingBalance * (100 - _TOKENLESS_PRODUCTION)) / _votingTotal / 100; } _lim = Math.min(_l, _lim); uint256 _oldBal = workingBalances[_addr]; workingBalances[_addr] = _lim; uint256 _workingSupply = workingSupply + _lim - _oldBal; workingSupply = _workingSupply; emit UpdateLiquidityLimit(_addr, _l, _L, _lim, _workingSupply, _votingBalance, _votingTotal); } //to avoid "stack too deep" struct CheckPointParameters { uint256 _period; uint256 _periodTime; uint256 _integrateInvSupply; uint256 rate; uint256 newRate; uint256 prevFutureEpoch; } /*** * @notice Checkpoint for a user * @param _addr User address * *This function does, *1. Calculate Iis for All: Calc and add Iis for every week. Iis only increses over time. *2. Calculate Iu for _addr: Calc by (defferece between Iis(last time) and Iis(this time))* LP deposit amount of _addr(include locking boost) * * working_supply & working_balance = total_supply & total_balance with locking boost。 * Check whitepaper about Iis and Iu. */ function _checkpoint(address _addr) internal { CheckPointParameters memory _st; _st._period = period; _st._periodTime = periodTimestamp[_st._period]; _st._integrateInvSupply = integrateInvSupply[_st._period]; _st.rate = inflationRate; _st.newRate = _st.rate; _st.prevFutureEpoch = futureEpochTime; if (_st.prevFutureEpoch >= _st._periodTime) { //update future_epoch_time & inflation_rate futureEpochTime = ltToken.futureEpochTimeWrite(); _st.newRate = ltToken.rate(); inflationRate = _st.newRate; } controller.checkpointGauge(address(this)); if (isKilled) { // Stop distributing inflation as soon as killed _st.rate = 0; } // Update integral of 1/supply if (block.timestamp > _st._periodTime) { uint256 _workingSupply = workingSupply; uint256 _prevWeekTime = _st._periodTime; uint256 _weekTime = Math.min(LibTime.timesRoundedByWeek(_st._periodTime + _WEEK), block.timestamp); for (uint256 i; i < 500; i++) { uint256 _dt = _weekTime - _prevWeekTime; uint256 _w = controller.gaugeRelativeWeight(address(this), LibTime.timesRoundedByWeek(_prevWeekTime)); if (_workingSupply > 0) { if (_st.prevFutureEpoch >= _prevWeekTime && _st.prevFutureEpoch < _weekTime) { // If we went across one or multiple epochs, apply the rate // of the first epoch until it ends, and then the rate of // the last epoch. // If more than one epoch is crossed - the gauge gets less, // but that'd meen it wasn't called for more than 1 year _st._integrateInvSupply += (_st.rate * _w * (_st.prevFutureEpoch - _prevWeekTime)) / _workingSupply; _st.rate = _st.newRate; _st._integrateInvSupply += (_st.rate * _w * (_weekTime - _st.prevFutureEpoch)) / _workingSupply; } else { _st._integrateInvSupply += (_st.rate * _w * _dt) / _workingSupply; } // On precisions of the calculation // rate ~= 10e18 // last_weight > 0.01 * 1e18 = 1e16 (if pool weight is 1%) // _working_supply ~= TVL * 1e18 ~= 1e26 ($100M for example) // The largest loss is at dt = 1 // Loss is 1e-9 - acceptable } if (_weekTime == block.timestamp) { break; } _prevWeekTime = _weekTime; _weekTime = Math.min(_weekTime + _WEEK, block.timestamp); } } _st._period += 1; period = _st._period; periodTimestamp[_st._period] = block.timestamp; integrateInvSupply[_st._period] = _st._integrateInvSupply; uint256 _workingBalance = workingBalances[_addr]; // Update user-specific integrals // Calc the ΔIu of _addr and add it to Iu. integrateFraction[_addr] += (_workingBalance * (_st._integrateInvSupply - integrateInvSupplyOf[_addr])) / 10 ** 18; integrateInvSupplyOf[_addr] = _st._integrateInvSupply; integrateCheckpointOf[_addr] = block.timestamp; } /*** * @notice Record a checkpoint for `_addr` * @param _addr User address * @return bool success */ function userCheckpoint(address _addr) external returns (bool) { require((msg.sender == _addr) || (msg.sender == address(minter)), "GP000"); _checkpoint(_addr); _updateLiquidityLimit(_addr, lpBalanceOf(_addr), lpTotalSupply()); return true; } /*** * @notice Get the number of claimable tokens per user * @dev This function should be manually changed to "view" in the ABI * @return uint256 number of claimable tokens per user */ function claimableTokens(address _addr) external returns (uint256) { _checkpoint(_addr); return (integrateFraction[_addr] - minter.minted(_addr, address(this))); } /*** * @notice Kick `_addr` for abusing their boost * @dev Only if either they had another voting event, or their voting escrow lock expired * @param _addr Address to kick */ function kick(address _addr) external { uint256 _tLast = integrateCheckpointOf[_addr]; uint256 _tVe = votingEscrow.userPointHistoryTs(_addr, votingEscrow.userPointEpoch(_addr)); uint256 _balance = lpBalanceOf(_addr); require(votingEscrow.balanceOfAtTime(_addr, block.timestamp) == 0 || _tVe > _tLast, "GP001"); require(workingBalances[_addr] > (_balance * _TOKENLESS_PRODUCTION) / 100, "GP001"); _checkpoint(_addr); _updateLiquidityLimit(_addr, lpBalanceOf(_addr), lpTotalSupply()); } function integrateCheckpoint() external view returns (uint256) { return periodTimestamp[period]; } /*** * @notice Set the killed status for this contract * @dev When killed, the gauge always yields a rate of 0 and so cannot mint LT * @param _is_killed Killed status to set */ function setKilled(bool _isKilled) external onlyOwner { isKilled = _isKilled; } /*** * @notice The total amount of LP tokens that are currently deposited into the Gauge. */ function lpBalanceOf(address _addr) public view virtual returns (uint256); /*** * @notice The total amount of LP tokens that are currently deposited into the Gauge. */ function lpTotalSupply() public view virtual returns (uint256); }
// SPDX-License-Identifier: LGPL-3.0 pragma solidity 0.8.17; interface IGaugeController { struct Point { uint256 bias; uint256 slope; } struct VotedSlope { uint256 slope; uint256 power; uint256 end; } struct UserPoint { uint256 bias; uint256 slope; uint256 ts; uint256 blk; } event AddType(string name, int128 type_id); event NewTypeWeight(int128 indexed type_id, uint256 time, uint256 weight, uint256 total_weight); event NewGaugeWeight(address indexed gauge_address, uint256 time, uint256 weight, uint256 total_weight); event VoteForGauge(address indexed user, address indexed gauge_address, uint256 time, uint256 weight); event NewGauge(address indexed gauge_address, int128 gauge_type, uint256 weight); /** * @notice Get gauge type for address * @param _addr Gauge address * @return Gauge type id */ function gaugeTypes(address _addr) external view returns (int128); /** * @notice Add gauge `addr` of type `gauge_type` with weight `weight` * @param addr Gauge address * @param gaugeType Gauge type * @param weight Gauge weight */ function addGauge(address addr, int128 gaugeType, uint256 weight) external; /** * @notice Checkpoint to fill data common for all gauges */ function checkpoint() external; /** * @notice Checkpoint to fill data for both a specific gauge and common for all gauge * @param addr Gauge address */ function checkpointGauge(address addr) external; /** * @notice Get Gauge relative weight (not more than 1.0) normalized to 1e18(e.g. 1.0 == 1e18). Inflation which will be received by * it is inflation_rate * relative_weight / 1e18 * @param gaugeAddress Gauge address * @param time Relative weight at the specified timestamp in the past or present * @return Value of relative weight normalized to 1e18 */ function gaugeRelativeWeight(address gaugeAddress, uint256 time) external view returns (uint256); /** * @notice Get gauge weight normalized to 1e18 and also fill all the unfilled values for type and gauge records * @dev Any address can call, however nothing is recorded if the values are filled already * @param gaugeAddress Gauge address * @param time Relative weight at the specified timestamp in the past or present * @return Value of relative weight normalized to 1e18 */ function gaugeRelativeWeightWrite(address gaugeAddress, uint256 time) external returns (uint256); /** * @notice Add gauge type with name `_name` and weight `weight` * @dev only owner call * @param _name Name of gauge type * @param weight Weight of gauge type */ function addType(string memory _name, uint256 weight) external; /** * @notice Change gauge type `type_id` weight to `weight` * @dev only owner call * @param type_id Gauge type id * @param weight New Gauge weight */ function changeTypeWeight(int128 type_id, uint256 weight) external; /** * @notice Change weight of gauge `addr` to `weight` * @param gaugeAddress `Gauge` contract address * @param weight New Gauge weight */ function changeGaugeWeight(address gaugeAddress, uint256 weight) external; /** * @notice Allocate voting power for changing pool weights * @param gaugeAddress Gauge which `msg.sender` votes for * @param userWeight Weight for a gauge in bps (units of 0.01%). Minimal is 0.01%. Ignored if 0. * example: 10%=1000,3%=300,0.01%=1,100%=10000 */ function voteForGaugeWeights(address gaugeAddress, uint256 userWeight) external; /** * @notice Get current gauge weight * @param addr Gauge address * @return Gauge weight */ function getGaugeWeight(address addr) external view returns (uint256); /** * @notice Get current type weight * @param type_id Type id * @return Type weight */ function getTypeWeight(int128 type_id) external view returns (uint256); /** * @notice Get current total (type-weighted) weight * @return Total weight */ function getTotalWeight() external view returns (uint256); /** * @notice Get sum of gauge weights per type * @param type_id Type id * @return Sum of gauge weights */ function getWeightsSumPreType(int128 type_id) external view returns (uint256); function votingEscrow() external view returns (address); }
// SPDX-License-Identifier: LGPL-3.0 pragma solidity 0.8.17; interface ILT { /** * @dev Emitted when LT inflation rate update * * Note once a year */ event UpdateMiningParameters(uint256 time, uint256 rate, uint256 supply); /** * @dev Emitted when set LT minter,can set the minter only once, at creation */ event SetMinter(address indexed minter); function rate() external view returns (uint256); /** * @notice Update mining rate and supply at the start of the epoch * @dev Callable by any address, but only once per epoch * Total supply becomes slightly larger if this function is called late */ function updateMiningParameters() external; /** * @notice Get timestamp of the next mining epoch start while simultaneously updating mining parameters * @return Timestamp of the next epoch */ function futureEpochTimeWrite() external returns (uint256); /** * @notice Current number of tokens in existence (claimed or unclaimed) */ function availableSupply() external view returns (uint256); /** * @notice How much supply is mintable from start timestamp till end timestamp * @param start Start of the time interval (timestamp) * @param end End of the time interval (timestamp) * @return Tokens mintable from `start` till `end` */ function mintableInTimeframe(uint256 start, uint256 end) external view returns (uint256); /** * @notice Set the minter address * @dev Only callable once, when minter has not yet been set * @param _minter Address of the minter */ function setMinter(address _minter) external; /** * @notice Mint `value` tokens and assign them to `to` * @dev Emits a Transfer event originating from 0x00 * @param to The account that will receive the created tokens * @param value The amount that will be created * @return bool success */ function mint(address to, uint256 value) external returns (bool); /** * @notice Burn `value` tokens belonging to `msg.sender` * @dev Emits a Transfer event with a destination of 0x00 * @param value The amount that will be burned * @return bool success */ function burn(uint256 value) external returns (bool); }
// SPDX-License-Identifier: LGPL-3.0 pragma solidity 0.8.17; interface IMinter { function token() external view returns (address); function controller() external view returns (address); function minted(address user, address gauge) external view returns (uint256); function mint(address gaugeAddress) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; interface IStaking { event Staking(address indexed user, uint256 amount); event Unstaking(address indexed user, uint256 amount); event Redeem(address indexed user, uint256 amount); event RewardsAccrued(address user, uint256 amount); event RewardsClaimed(address indexed user, uint256 amount); function staking(uint256 amount, uint256 nonce, uint256 deadline, bytes memory signature) external returns (bool); function redeemAll() external returns (uint256); }
// SPDX-License-Identifier: LGPL-3.0 pragma solidity 0.8.17; interface IVotingEscrow { struct Point { int256 bias; int256 slope; uint256 ts; uint256 blk; } struct LockedBalance { int256 amount; uint256 end; } event Deposit( address indexed provider, address indexed beneficiary, uint256 value, uint256 afterAmount, uint256 indexed locktime, uint256 _type, uint256 ts ); event Withdraw(address indexed provider, uint256 value, uint256 ts); event Supply(uint256 prevSupply, uint256 supply); event SetSmartWalletChecker(address sender, address indexed newChecker, address oldChecker); event SetPermit2Address(address oldAddress, address newAddress); /*** * @dev Get the most recently recorded rate of voting power decrease for `_addr` * @param _addr Address of the user wallet * @return Value of the slope */ function getLastUserSlope(address _addr) external view returns (int256); /*** * @dev Get the timestamp for checkpoint `_idx` for `_addr` * @param _addr User wallet address * @param _idx User epoch number * @return Epoch time of the checkpoint */ function userPointHistoryTs(address _addr, uint256 _idx) external view returns (uint256); /*** * @dev Get timestamp when `_addr`'s lock finishes * @param _addr User wallet * @return Epoch time of the lock end */ function lockedEnd(address _addr) external view returns (uint256); function createLock(uint256 _value, uint256 _unlockTime, uint256 nonce, uint256 deadline, bytes memory signature) external; function createLockFor( address _beneficiary, uint256 _value, uint256 _unlockTime, uint256 nonce, uint256 deadline, bytes memory signature ) external; function increaseAmount(uint256 _value, uint256 nonce, uint256 deadline, bytes memory signature) external; function increaseAmountFor(address _beneficiary, uint256 _value, uint256 nonce, uint256 deadline, bytes memory signature) external; function increaseUnlockTime(uint256 _unlockTime) external; function checkpointSupply() external; function withdraw() external; function epoch() external view returns (uint256); function getUserPointHistory(address _userAddress, uint256 _index) external view returns (Point memory); function supplyPointHistory(uint256 _index) external view returns (int256 bias, int256 slope, uint256 ts, uint256 blk); /*** * @notice Get the current voting power for `msg.sender` * @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility * @param _addr User wallet address * @param _t Epoch time to return voting power at * @return User voting power * @dev return the present voting power if _t is 0 */ function balanceOfAtTime(address _addr, uint256 _t) external view returns (uint256); function totalSupply() external view returns (uint256); function totalSupplyAtTime(uint256 _t) external view returns (uint256); function userPointEpoch(address _user) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity 0.8.17; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ 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 amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: LGPL-3.0 pragma solidity 0.8.17; interface IPermit2 { /// @notice The token and amount details for a transfer signed in the permit transfer signature struct TokenPermissions { // ERC20 token address address token; // the maximum amount that can be spent uint256 amount; } /// @notice The signed permit message for a single token transfer struct PermitTransferFrom { TokenPermissions permitted; // a unique value for every token owner's signature to prevent signature replays uint256 nonce; // deadline on the permit signature uint256 deadline; } /// @notice Specifies the recipient address and amount for batched transfers. /// @dev Recipients and amounts correspond to the index of the signed token permissions array. /// @dev Reverts if the requested amount is greater than the permitted signed amount. struct SignatureTransferDetails { // recipient address address to; // spender requested amount uint256 requestedAmount; } /// @notice Used to reconstruct the signed permit message for multiple token transfers /// @dev Do not need to pass in spender address as it is required that it is msg.sender /// @dev Note that a user still signs over a spender address struct PermitBatchTransferFrom { // the tokens and corresponding amounts permitted for a transfer TokenPermissions[] permitted; // a unique value for every token owner's signature to prevent signature replays uint256 nonce; // deadline on the permit signature uint256 deadline; } /// @notice A map from token owner address and a caller specified word index to a bitmap. Used to set bits in the bitmap to prevent against signature replay protection /// @dev Uses unordered nonces so that permit messages do not need to be spent in a certain order /// @dev The mapping is indexed first by the token owner, then by an index specified in the nonce /// @dev It returns a uint256 bitmap /// @dev The index, or wordPosition is capped at type(uint248).max function nonceBitmap(address, uint256) external view returns (uint256); /// @notice Transfers a token using a signed permit message /// @dev Reverts if the requested amount is greater than the permitted signed amount /// @param permit The permit data signed over by the owner /// @param owner The owner of the tokens to transfer /// @param transferDetails The spender's requested transfer details for the permitted token /// @param signature The signature to verify function permitTransferFrom( PermitTransferFrom memory permit, SignatureTransferDetails calldata transferDetails, address owner, bytes calldata signature ) external; /// @notice Transfers a token using a signed permit message /// @notice Includes extra data provided by the caller to verify signature over /// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition /// @dev Reverts if the requested amount is greater than the permitted signed amount /// @param permit The permit data signed over by the owner /// @param owner The owner of the tokens to transfer /// @param transferDetails The spender's requested transfer details for the permitted token /// @param witness Extra data to include when checking the user signature /// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash /// @param signature The signature to verify function permitWitnessTransferFrom( PermitTransferFrom memory permit, SignatureTransferDetails calldata transferDetails, address owner, bytes32 witness, string calldata witnessTypeString, bytes calldata signature ) external; /// @notice Transfers multiple tokens using a signed permit message /// @param permit The permit data signed over by the owner /// @param owner The owner of the tokens to transfer /// @param transferDetails Specifies the recipient and requested amount for the token transfer /// @param signature The signature to verify function permitTransferFrom( PermitBatchTransferFrom memory permit, SignatureTransferDetails[] calldata transferDetails, address owner, bytes calldata signature ) external; /// @notice Transfers multiple tokens using a signed permit message /// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition /// @notice Includes extra data provided by the caller to verify signature over /// @param permit The permit data signed over by the owner /// @param owner The owner of the tokens to transfer /// @param transferDetails Specifies the recipient and requested amount for the token transfer /// @param witness Extra data to include when checking the user signature /// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash /// @param signature The signature to verify function permitWitnessTransferFrom( PermitBatchTransferFrom memory permit, SignatureTransferDetails[] calldata transferDetails, address owner, bytes32 witness, string calldata witnessTypeString, bytes calldata signature ) external; /// @notice Invalidates the bits specified in mask for the bitmap at the word position /// @dev The wordPos is maxed at type(uint248).max /// @param wordPos A number to index the nonceBitmap at /// @param mask A bitmap masked against msg.sender's current bitmap at the word position function invalidateUnorderedNonces(uint256 wordPos, uint256 mask) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.17; library LibTime { // 7 * 86400 seconds - all future times are rounded by week uint256 public constant DAY = 86400; uint256 public constant WEEK = DAY * 7; /** * @dev times are rounded by week * @param time time */ function timesRoundedByWeek(uint256 time) internal pure returns (uint256) { return (time / WEEK) * WEEK; } }
// SPDX-License-Identifier: LGPL-3.0 pragma solidity 0.8.17; import "./IERC20.sol"; import "./IPermit2.sol"; library TransferHelper { /** * @dev Similar to EIP20 transfer, except it handles a False result from `transferFrom` and reverts in that case. * This will revert due to insufficient balance or insufficient allowance. * This function returns the actual amount received, * which may be less than `amount` if there is a fee attached to the transfer. * * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value. */ function doTransferFrom(address tokenAddress, address from, address to, uint256 amount) internal returns(uint256) { IERC20 token = IERC20(tokenAddress); uint256 balanceBefore = token.balanceOf(to); safeTransferFrom(token, from, to, amount); uint256 balanceAfter = token.balanceOf(to); uint256 actualAmount = balanceAfter - balanceBefore; assert(actualAmount <= amount); return actualAmount; } /** * @dev transfer with permit2 */ function doTransferIn( address permit2Address, address tokenAddress, uint256 _value, address from, uint256 nonce, uint256 deadline, bytes memory signature ) internal returns (uint256) { IPermit2.PermitTransferFrom memory permit = IPermit2.PermitTransferFrom({ permitted: IPermit2.TokenPermissions({token: tokenAddress, amount: _value}), nonce: nonce, deadline: deadline }); IPermit2.SignatureTransferDetails memory transferDetails = IPermit2.SignatureTransferDetails({ to: address(this), requestedAmount: _value }); // Read from storage once IERC20 token = IERC20(permit.permitted.token); uint256 balanceBefore = token.balanceOf(transferDetails.to); if (nonce == 0 && deadline == 0) { safeTransferFrom(token, from, transferDetails.to, transferDetails.requestedAmount); } else { IPermit2(permit2Address).permitTransferFrom(permit, transferDetails, from, signature); } // Calculate the amount that was *actually* transferred uint256 balanceAfter = IERC20(permit.permitted.token).balanceOf(address(this)); uint256 actualAmount = balanceAfter - balanceBefore; assert(actualAmount <= transferDetails.requestedAmount); return actualAmount; } /** * @dev Similar to EIP20 transfer, except it handles a False success from `transfer` and returns an explanatory * error code rather than reverting. If caller has not called checked protocol's balance, this may revert due to * insufficient cash held in this contract. If caller has checked protocol's balance prior to this call, and verified * it is >= amount, this should not revert in normal conditions. * * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value. */ function doTransferOut(address tokenAddress, address to, uint256 amount) internal returns(uint256) { IERC20 token = IERC20(tokenAddress); uint256 balanceBefore = token.balanceOf(to); safeTransfer(token, to, amount); uint256 balanceAfter = token.balanceOf(to); uint256 actualAmount = balanceAfter - balanceBefore; assert(actualAmount <= amount); return actualAmount; } function doApprove(address tokenAddress, address to, uint256 amount) internal { IERC20 token = IERC20(tokenAddress); safeApprove(token, to, amount); } function safeTransferFrom( IERC20 token, address from, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument. mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 100, 0, 32) ) } require(success, "TRANSFER_FROM_FAILED"); } function safeTransfer( IERC20 token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "TRANSFER_FAILED"); } function safeApprove( IERC20 token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "APPROVE_FAILED"); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "viaIR": true, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_stakedToken","type":"address"},{"internalType":"address","name":"_minter","type":"address"},{"internalType":"address","name":"_permit2Address","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsAccrued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAddress","type":"address"},{"indexed":false,"internalType":"address","name":"newAddress","type":"address"}],"name":"SetPermit2Address","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staking","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unstaking","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"originalBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"originalSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"workingBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"workingSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"votingBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"votingTotal","type":"uint256"}],"name":"UpdateLiquidityLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","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":[{"internalType":"address","name":"_addr","type":"address"}],"name":"claimableTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"controller","outputs":[{"internalType":"contract IGaugeController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"futureEpochTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inflationRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"integrateCheckpoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"integrateCheckpointOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"integrateFraction","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"integrateInvSupplyOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isKilled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"kick","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"lpBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ltToken","outputs":[{"internalType":"contract ILT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minter","outputs":[{"internalType":"contract IMinter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"period","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"periodTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"permit2Address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redeemAll","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxIndex","type":"uint256"}],"name":"redeemByMaxIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isKilled","type":"bool"}],"name":"setKilled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAddress","type":"address"}],"name":"setPermit2Address","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"staking","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalNotRedeemAmount","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":"_amount","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":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"unstakedBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unstakedTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unstaking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"unstakingBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"unstakingDayHistory","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"unstakingMap","outputs":[{"internalType":"uint256","name":"notRedeemAmount","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unstakingTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"userCheckpoint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"votingEscrow","outputs":[{"internalType":"contract IVotingEscrow","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"workingBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"workingSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060409080825234620006db57606081620032de8038038091620000258285620006fc565b833981010312620006db576200003b8162000720565b9060209062000059846200005184840162000720565b920162000720565b928451916200006883620006e0565b600b83526a7374616b656420484f504560a81b848401528551926200008d84620006e0565b60068452657374484f504560d01b8585015280516001600160401b0390818111620005db576003908154906001948583811c93168015620006d0575b8a841014620006ba578190601f9384811162000664575b508a90848311600114620005fd57600092620005f1575b505060001982851b1c191690851b1782555b8651928311620005db5760049687548581811c91168015620005d0575b8a821014620005bb57908183869594931162000561575b5089918411600114620004f657600093620004ea575b505082841b92600019911b1c19161784555b62000170336200076a565b6001600160a01b03928316918390620001a5841515620001908162000735565b6200019f848b16151562000735565b62000735565b1690620001b482151562000735565b620001c133151562000735565b60165460ff8116620004905760ff191617601655620001e0336200076a565b600780546001600160a01b03199081169093179055600880548316821790558651637e062a3560e11b81529085828681845afa908115620004855784879287946000916200043f575b501684600954161760095588519283809263f77c479160e01b82525afa8015620003f1578386918693600091620003fc575b50168084600a541617600a55885192838092634f2bfe5b60e01b82525afa8015620003f1578391600091620003b2575b501690600b541617600b55600080526010835242856000205560095416908451631627391760e11b815283818381865afa908115620003a75760009162000373575b50601555845163277dbafb60e01b815292918291849182906000905af1908115620003685760009162000333575b50600c555060168054610100600160a81b03191660089290921b610100600160a81b031691909117905551612b1f9081620007bf8239f35b82813d831162000360575b6200034a8183620006fc565b810103126200035d5750518038620002fb565b80fd5b503d6200033e565b84513d6000823e3d90fd5b908482813d83116200039f575b6200038c8183620006fc565b810103126200035d5750516000620002cd565b503d62000380565b86513d6000823e3d90fd5b91508582813d8311620003e9575b620003cc8183620006fc565b810103126200035d5750620003e2839162000720565b386200028b565b503d620003c0565b87513d6000823e3d90fd5b935091905082813d831162000437575b620004188183620006fc565b810103126200035d5750848362000430869362000720565b386200025b565b503d6200040c565b9384919395508092503d83116200047d575b6200045d8183620006fc565b810103126200035d575084918462000476889362000720565b3862000229565b503d62000451565b88513d6000823e3d90fd5b885162461bcd60e51b8152808701889052602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b01519150388062000153565b9190859450601f19841692896000528a6000209360005b8c8282106200054a57505085116200052f575b50505050811b01845562000165565b01519060f884600019921b161c191690553880808062000520565b83850151875589989096019593840193016200050d565b909192935088600052896000208380870160051c8201928c8810620005b1575b9188918897969594930160051c01915b828110620005a15750506200013d565b6000815587965088910162000591565b9250819262000581565b602289634e487b7160e01b6000525260246000fd5b90607f169062000126565b634e487b7160e01b600052604160045260246000fd5b015190503880620000f7565b60008681528c8120899550929190601f198516908e5b8282106200064c575050841162000633575b505050811b01825562000109565b015160001983871b60f8161c1916905538808062000625565b8385015186558b979095019493840193018e62000613565b909150846000528a6000208480850160051c8201928d8610620006b0575b918991869594930160051c01915b828110620006a0575050620000e0565b6000815585945089910162000690565b9250819262000682565b634e487b7160e01b600052602260045260246000fd5b92607f1692620000c9565b600080fd5b604081019081106001600160401b03821117620005db57604052565b601f909101601f19168101906001600160401b03821190821017620005db57604052565b51906001600160a01b0382168203620006db57565b156200073d57565b60405162461bcd60e51b8152602060048201526005602482015264043453030360dc1b6044820152606490fd5b600680546001600160a01b0319908116909155600580549182166001600160a01b0393841690811790915591167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a356fe608080604052600436101561001357600080fd5b600090813560e01c90816306fdde0314611ae1575080630754617214611ab85780630959950414611a71578063095ea7b314611a4a57806317a3c37014611a2357806318160ddd14611a0557806323b872dd146119155780632f4350c214611805578063313ce567146117e957806331e202cc146117bf57806331f9e35b146117a157806339509351146117515780634f2bfe5b14611728578063505362c4146116ff57806353f7425f146116bc5780635fcbd2851461169357806366be23221461167157806370a0823114611639578063715018a6146115d257806373dd0555146111095780637699b4cd146110d05780637915b1c3146110a657806379ba509714610fdd5780637b4dacef14610fc257806384d2422614610ef55780638b45a67314610ed15780638da5cb5b14610ea85780638fe8a10114610e8257806390827da714610ce1578063958da8de14610ca857806395d89b4114610b9757806396c55175146109915780639c46665c146109655780639e48d35e14610947578063a154f1bb1461087c578063a457c2d7146107d7578063a5870d6b146107ae578063a9059cbb14610743578063b07b709b1461069d578063b1bd608614610664578063bdc83b1f14610646578063c522498314610619578063c826860414610579578063c8562f721461055b578063caa0b9ed14610522578063dd62ed3e146104d3578063e30c3978146104aa578063ef78d4fd1461048c578063f2fde38b1461041e578063f77c4791146103f55763fc566d521461025257600080fd5b346103f257602090816003193601126103f25760043561027b61027433611f34565b1515611e18565b8161028533612464565b338352601884526040832090839160019384820195600291828401965b885481116103e4578187101561034557808352878a52600160408420015442101580610334575b6102dc575b6102d790611e8c565b6102a2565b9561032c6102d7916102f360408620548099611d09565b978986528a8d52866040872001600160ff19825416179055610316818954611e9b565b88556103256017918254611e9b565b9055611e8c565b9690506102ce565b5060ff8460408520015416156102c9565b5050509350509250505b8161035e575b50604051908152f35b6103a49061036c8333611fc3565b60075461038590849033906001600160a01b0316612986565b5061039d610392336120ca565b915460175490611e9b565b9033612265565b6103b081601a54611e9b565b601a556040518181527f222838db2794d11532d940e8dec38ae307ed0b63cd97c233322e221f998767a6833392a238610355565b50505093505092505061034f565b80fd5b50346103f257806003193601126103f257600a546040516001600160a01b039091168152602090f35b50346103f25760203660031901126103f257610438611c01565b610440611cb1565b600680546001600160a01b0319166001600160a01b039283169081179091556005549091167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227008380a380f35b50346103f257806003193601126103f2576020600f54604051908152f35b50346103f257806003193601126103f2576006546040516001600160a01b039091168152602090f35b50346103f25760403660031901126103f2576104ed611c01565b60406104f7611c17565b9260018060a01b03809316815260016020522091166000526020526020604060002054604051908152f35b50346103f25760203660031901126103f2576020906040906001600160a01b0361054a611c01565b168152601483522054604051908152f35b50346103f257806003193601126103f2576020600e54604051908152f35b50346103f257602090816003193601126103f257610595611c01565b6001600160a01b031681526018825260408120600181810154600292830192849291805b6105c8575b8686604051908152f35b80845284875260ff8260408620015416610614578260408520015442106105f9575b6105f390611e7f565b806105b9565b9461060c6105f391604086205490611d09565b9590506105ea565b6105be565b50346103f257806003193601126103f25760165460405160089190911c6001600160a01b03168152602090f35b50346103f257806003193601126103f2576020601754604051908152f35b50346103f25760203660031901126103f2576020906040906001600160a01b0361068c611c01565b168152601283522054604051908152f35b50346103f25760203660031901126103f2576106b7611c01565b6001600160a01b038181163314908115610735575b501561070857806106df6106fd92612464565b6106e8816120ca565b6106f760025460175490611e9b565b91612265565b602060405160018152f35b60405162461bcd60e51b8152602060048201526005602482015264047503030360dc1b6044820152606490fd5b9050600854163314826106cc565b50346103f25760403660031901126103f2576106fd610760611c01565b61079360243561077a81610773336120ca565b1015611e18565b61078333612464565b61078c83612464565b82336120f7565b6106df61079f336120ca565b61039d60025460175490611e9b565b50346103f257806003193601126103f2576009546040516001600160a01b039091168152602090f35b50346103f25760403660031901126103f2576107f1611c01565b60406024359233815260016020522060018060a01b03821660005260205260406000205491808310610829576106fd92039033611d16565b60405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608490fd5b50346103f25760203660031901126103f257610896611c01565b61089e611cb1565b6001600160a01b038181161561091a5760168054610100600160a81b03198116600885811b610100600160a81b031691909117909255604080516001600160a01b039290931c939093168116825290921660208301527f35f7c25f313d8b378045946ab43056cd8fbf3cb403496ebaa0beef117936ec3291a180f35b60405162461bcd60e51b8152602060048201526005602482015264043453030360dc1b6044820152606490fd5b50346103f257806003193601126103f2576020600c54604051908152f35b50346103f25760203660031901126103f2576020610989610984611c01565b6120ca565b604051908152f35b50346103f257602080600319360112610b93576109ac611c01565b9060018060a01b038083169182855260138152604085205491600b5416926040516381fc83bb60e01b81528160048201528281602481885afa8015610b595783908890610b64575b60405163eac6a66760e01b81526001600160a01b0389166004820152602481019190915291508180604481015b0381885afa908115610b59578791610b2c575b50610a3e866120ca565b604051633037408d60e01b81526001600160a01b038816600482015242602482015290958490829060449082905afa908115610b21578891610aec575b5090600d94610a949215918215610ae2575b5050612935565b855252604083205490602881029080820460281490151715610ace57610acb92916064610ac2920410612935565b6106df81612464565b80f35b634e487b7160e01b84526011600452602484fd5b1190503880610a8d565b9190508382813d8311610b1a575b610b048183611c8f565b81010312610b15579051600d610a7b565b600080fd5b503d610afa565b6040513d8a823e3d90fd5b90508281813d8311610b52575b610b438183611c8f565b81010312610b15575138610a34565b503d610b39565b6040513d89823e3d90fd5b5081813d8311610b8c575b610b798183611c8f565b81010312610b155782610a2191516109f4565b503d610b6f565b5080fd5b50346103f257806003193601126103f257604051908060045491600183811c92818516948515610c9e575b6020958686108114610c8a57858852879493929187908215610c68575050600114610c0e575b5050610bf692500383611c8f565b610c0a604051928284938452830190611bc1565b0390f35b90859250600482527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b858310610c50575050610bf693508201013880610be8565b80548389018501528794508693909201918101610c38565b9250935050610bf694915060ff191682840152151560051b8201013880610be8565b634e487b7160e01b83526022600452602483fd5b93607f1693610bc2565b50346103f25760203660031901126103f2576020906040906001600160a01b03610cd0611c01565b168152600d83522054604051908152f35b50346103f257602080600319360112610b935760043590610d03821515611e18565b610d1082610773336120ca565b610d1933612464565b62015180804201804211610e6e57819004818102918183041490151715610ace576224ea00810190818111610e585780855260198352610d5d846040872054611d09565b908552601983526040852055610d7583601a54611d09565b601a553384526018825260408420610d8e848254611d09565b8155600181019182549260018401809411610e445791600291847ff2619dcba9802bb8ec071016f659320c48304701ba220f0420bed16f87139a66969594558260405192610ddb84611c5f565b88845286840192835260408401958a87528a520185526040882091518255516001820155019051151560ff80198354169116179055610e38610e1f84601754611d09565b8060175561039d610e2f336120ca565b91600254611e9b565b6040519283523392a280f35b634e487b7160e01b87526011600452602487fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b85526011600452602485fd5b50346103f257806003193601126103f257602060ff60065460a01c166040519015158152f35b50346103f257806003193601126103f2576005546040516001600160a01b039091168152602090f35b50346103f25760203660031901126103f2576020610989610ef0611c01565b611f34565b50346103f257602090816003193601126103f257610f6a90610f15611c01565b610f1e81612464565b6001600160a01b039081168083526014855260408084205460085491516308b752bb60e41b81526004810193909352306024840152919491928692869290911690829081906044820190565b03915afa918215610fb65791610f85575b6109899250611e9b565b90508282813d8311610faf575b610f9c8183611c8f565b81010312610b1557610989915190610f7b565b503d610f92565b604051903d90823e3d90fd5b50346103f257806003193601126103f2576020610989611ea8565b50346103f257806003193601126103f2576006546001600160a01b03338183160361104f576bffffffffffffffffffffffff60a01b8092166006556005549133908316176005553391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a380f35b60405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608490fd5b50346103f25760203660031901126103f25760406020916004358152601983522054604051908152f35b50346103f25760203660031901126103f2576020906040906001600160a01b036110f8611c01565b168152601383522054604051908152f35b50346103f25760803660031901126103f25767ffffffffffffffff6064358181116115ba57366023820112156115ba5780600401359182116115be5782906040519261115f6020601f19601f8401160185611c8f565b80845236602482840101116115ba5780602460209301838601378301015261118a6004351515611e18565b6007546040516370a0823160e01b81523360048201526001600160a01b039091169190602081602481865afa801561143a578490611582575b6111d291506004351115611e18565b60018060a01b0360165460081c1690604051926111ee84611c2d565b835260043560208401526040519261120584611c5f565b8352602435602084015260443560408401526040519161122483611c2d565b308352600435602084015260018060a01b038451511690604051926370a0823160e01b8452306004850152602084602481865afa938415610b5957879461154a575b506024351580611540575b1561148157505082516020808501516040516323b872dd60e01b81523360048201526001600160a01b039093166024840152604483015291869160649183905af13d15601f3d116001875114161716156114455760206024935b51516040516370a0823160e01b815230600482015294859182906001600160a01b03165afa92831561143a578493611404575b5061130e60209161131894611e9b565b9101511015612969565b61132133612464565b33156113bf57611335600435600254611d09565b600255338152806020526040812060043581540190556040519060043582527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60203393a361138661079f336120ca565b60405160043581527fb831f69f1cebc12b23cd864ce5bfea2669d01956050a0147d71d418074559c2160203392a2602060405160018152f35b60405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606490fd5b92506020833d602011611432575b8161141f60209383611c8f565b81010312610b155791519161130e6112fe565b3d9150611412565b6040513d86823e3d90fd5b60405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b6044820152606490fd5b908092509594953b1561153c5760405163187945bd60e11b8152865180516001600160a01b0316600483015260200151602482015291859183919082908490829061150c9060208d810151604485015260408e015160648501528b516001600160a01b031660848501528b015160a48401523360c484015261010060e4840152610104830190611bc1565b03925af1801561143a57611527575b506020602493946112cb565b602493611535602092611c7b565b935061151b565b8480fd5b5060443515611271565b9093506020813d60201161157a575b8161156660209383611c8f565b8101031261157657519238611266565b8680fd5b3d9150611559565b506020813d6020116115b2575b8161159c60209383611c8f565b810103126115ae576111d290516111c3565b8380fd5b3d915061158f565b8280fd5b634e487b7160e01b83526041600452602483fd5b50346103f257806003193601126103f2576115eb611cb1565b600680546001600160a01b031990811690915560058054918216905581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346103f25760203660031901126103f2576020906040906001600160a01b03611661611c01565b1681528083522054604051908152f35b50346103f257806003193601126103f257602061098960025460175490611e9b565b50346103f257806003193601126103f2576007546040516001600160a01b039091168152602090f35b50346103f25760203660031901126103f25760409081906001600160a01b036116e3611c01565b1681526018602052206001815491015482519182526020820152f35b50346103f257806003193601126103f2576040602091600f548152601083522054604051908152f35b50346103f257806003193601126103f257600b546040516001600160a01b039091168152602090f35b50346103f25760403660031901126103f2576106fd9061179a611772611c01565b9133815260016020526040812060018060a01b03841682526020526040602435912054611d09565b9033611d16565b50346103f257806003193601126103f2576020601554604051908152f35b50346103f25760203660031901126103f25760406020916004358152601083522054604051908152f35b50346103f257806003193601126103f257602060405160128152f35b50346103f257806003193601126103f25761181f33611f34565b61182a811515611e18565b61183333612464565b3382526020916018835260408120600191828201549160029383858301945b6118a9575b87876118678861036c8333611fc3565b61187381601a54611e9b565b601a556040518181527f222838db2794d11532d940e8dec38ae307ed0b63cd97c233322e221f998767a6833392a2604051908152f35b80845284885260ff8660408620015416611910576118d490826040862001544210156118da57611e7f565b80611852565b60408520548760408720018460ff198254161790556118fa818654611e9b565b85556119096017918254611e9b565b9055611e7f565b611857565b50346103f25760603660031901126103f25761192f611c01565b90611938611c17565b9060406044359161194c83610773876120ca565b61195585612464565b61195e84612464565b6001600160a01b038516815260016020818152838320338452905291902054908101611998575b50826106df6106df92846106fd966120f7565b928184106119c0576106df826119b76106df946106fd97033385611d16565b92505092611985565b60405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606490fd5b50346103f257806003193601126103f2576020600254604051908152f35b50346103f257806003193601126103f2576020610989601a54611a44611ea8565b90611e9b565b50346103f25760403660031901126103f2576106fd611a67611c01565b6024359033611d16565b50346103f25760203660031901126103f257600435801515809103610b9357611a98611cb1565b6006805460ff60a01b191660a09290921b60ff60a01b1691909117905580f35b50346103f257806003193601126103f2576008546040516001600160a01b039091168152602090f35b82346103f257806003193601126103f2578060035491600183811c92818516948515611bb7575b6020958686108114610c8a57858852879493929187908215611b95575050600114611b3b575050610bf692500383611c8f565b90859250600382527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b858310611b7d575050610bf693508201018580610be8565b80548389018501528794508693909201918101611b65565b9250935050610bf694915060ff191682840152151560051b8201018580610be8565b93607f1693611b08565b919082519283825260005b848110611bed575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201611bcc565b600435906001600160a01b0382168203610b1557565b602435906001600160a01b0382168203610b1557565b6040810190811067ffffffffffffffff821117611c4957604052565b634e487b7160e01b600052604160045260246000fd5b6060810190811067ffffffffffffffff821117611c4957604052565b67ffffffffffffffff8111611c4957604052565b90601f8019910116810190811067ffffffffffffffff821117611c4957604052565b6005546001600160a01b03163303611cc557565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b91908201809211610e5857565b6001600160a01b03908116918215611dc75716918215611d775760207f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925918360005260018252604060002085600052825280604060002055604051908152a3565b60405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608490fd5b60405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608490fd5b15611e1f57565b60405162461bcd60e51b815260206004820152600560248201526421a298181960d91b6044820152606490fd5b8115611e56570490565b634e487b7160e01b600052601260045260246000fd5b81810292918115918404141715610e5857565b8015610e58576000190190565b6000198114610e585760010190565b91908203918211610e5857565b600062015180804201804211611f20578190049080820291808304821490151715611f20579082915b601c8310611edf5750505090565b9091928382028281048503610e5857611f1991611eff611f139286611e9b565b600052601960205260406000205490611d09565b93611e8c565b9190611ed1565b634e487b7160e01b83526011600452602483fd5b6001600160a01b031660009081526018602090815260408083206001818101549394936002928301939290805b611f70575b5050505050905090565b8060005284875260ff8285600020015416611fbe5782846000200154421015611fa3575b611f9d90611e7f565b80611f61565b94611fb6611f9d91856000205490611d09565b959050611f94565b611f66565b6001600160a01b0316801561207b5760009181835282602052604083205481811061202b57817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef926020928587528684520360408620558060025403600255604051908152a3565b60405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608490fd5b60405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608490fd5b60018060a01b031660005260006020526120f4604060002054601860205260406000205490611e9b565b90565b6001600160a01b0390811691821561221257169182156121c15760008281528060205260408120549180831061216d57604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652828652038282205586815220818154019055604051908152a3565b60405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608490fd5b60405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608490fd5b60405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608490fd5b600b5460408051633037408d60e01b81526001600160a01b0384811660048301524260248301529283169695929493909260209283856044818c5afa94851561242857600095612433575b508360249697989982519788809263d2dcd93360e01b82524260048301525afa958615612428576000966123f9575b506028870287810460281488151715610e5857606490048661238a575b7f47211fe8b1eecabef1c013b28eb9caa892fd6bf2d3f1f5111d08cc115de841659860e0989796959493929180891015612384575087935b169687600052600d855261235d826000205485846000205561235886600e54611d09565b611e9b565b9485600e5582519889528801528601526060850152608084015260a083015260c0820152a1565b93612334565b9695949392919061239b8583611e6c565b98603c8a0299808b04603c1490151715610e58576123e960e09960646123e28a7f47211fe8b1eecabef1c013b28eb9caa892fd6bf2d3f1f5111d08cc115de841659e611e4c565b0490611d09565b91929394959697985098506122fc565b90958482813d8311612421575b6124108183611c8f565b810103126103f257505194386122df565b503d612406565b50513d6000823e3d90fd5b9894848a813d831161245d575b61244a8183611c8f565b810103126103f2575097519397836122b0565b503d612440565b60405160009160c0820167ffffffffffffffff811183821017612921576040528260208301528260408301528260608301528260808301528260a0830152600f548083528352601060205260408320546020830152815183526011602052604083205460408301526015548060608401526080830152600c548060a08401526020830151111561283b575b600a546001600160a01b0316803b156115ae57838091602460405180948193638aca6a2360e01b83523060048401525af1801561143a57612828575b5060ff60065460a01c1661281d575b60208201518042116125ef575b50815160018101809111610ace579081604092845280600f55845260106020524282852055818301518351855260116020528285205560018060a01b031691828452600d602052670de0b6b3a76400006125ba838620546125b48585015160126020528689205490611e9b565b90611e6c565b0483855260146020526125d1838620918254611d09565b90550151908252601260205260408220556013602052604042912055565b600e5462093a808201808311610e585762093a80900462093a8081029080820462093a801490151715610e585742811015612816575b600a546001600160a01b031692869291905b6101f4841061264a575b50505050612547565b6126548183611e9b565b9062093a808104918262093a8081020462093a801483151715610e5857604051630cb8c08d60e31b815230600482015262093a809390930260248401526020836044818a5afa92831561280b579189918694938c946127d0575b5084612701575b50505050504281146126fb578062093a8081018111610e58574262093a80820110156126f15762093a806126ea910193611e8c565b9290612637565b506126ea42611f13565b80612641565b60a0830151868382101591826127c6575b50501561279d57506127758361275f84604061275789612752612752986125b46127476127839d61278d9f9d60600151611e6c565b9160a0880151611e9b565b611e4c565b910151611d09565b60408d015260808c015160608d01819052611e6c565b6125b460a08c015187611e9b565b6040880151611d09565b60408701525b81388781806126b5565b61275291506127b76127839460606127bc97950151611e6c565b611e6c565b6040870152612793565b1090508638612712565b9250925092506020813d602011612803575b816127ef60209383611c8f565b81010312610b1557849289915192386126ae565b3d91506127e2565b6040513d8c823e3d90fd5b5042612625565b82606083015261253a565b61283490939193611c7b565b913861252b565b60095460405163277dbafb60e01b81526001600160a01b039160209082906004908290899087165af19081156129165785916128e3575b50600c55600954604051631627391760e11b81529160209183916004918391165afa90811561143a5784916128b1575b508060808401526015556124ef565b90506020813d6020116128db575b816128cc60209383611c8f565b810103126115ae5751386128a2565b3d91506128bf565b90506020813d60201161290e575b816128fe60209383611c8f565b8101031261153c57516004612872565b3d91506128f1565b6040513d87823e3d90fd5b634e487b7160e01b84526041600452602484fd5b1561293c57565b60405162461bcd60e51b8152602060048201526005602482015264475030303160d81b6044820152606490fd5b1561297057565b634e487b7160e01b600052600160045260246000fd5b604080516370a0823160e01b8082526001600160a01b038086166004840181905292959394169260209291908387602481885afa968715612ade57600097612aae575b5060006044859288519063a9059cbb60e01b825260048201528a602482015282885af13d15601f3d1160016000511416171615612a7857906024839286519586938492835260048301525afa928315612a6e5750600092612a3d575b50506120f491612a3491611e9b565b91821115612969565b81819392933d8311612a67575b612a548183611c8f565b810103126103f257505181612a34612a25565b503d612a4a565b513d6000823e3d90fd5b845162461bcd60e51b815260048101849052600f60248201526e1514905394d1915497d19052531151608a1b6044820152606490fd5b90968482813d8311612ad7575b612ac58183611c8f565b810103126103f25750519560006129c9565b503d612abb565b86513d6000823e3d90fdfea26469706673582212206bed956b7effe049f0ab60543dc33361256b1d1e0807d7f2a3c83c8870d6113064736f6c63430008110033000000000000000000000000c353bf07405304aeab75f4c2fac7e88d6a68f98e00000000000000000000000094afb2c17af24cfacf19f364628f459dfab2688f000000000000000000000000c53c83d26151dbcffa349fae20b6155299e87a35
Deployed Bytecode
0x608080604052600436101561001357600080fd5b600090813560e01c90816306fdde0314611ae1575080630754617214611ab85780630959950414611a71578063095ea7b314611a4a57806317a3c37014611a2357806318160ddd14611a0557806323b872dd146119155780632f4350c214611805578063313ce567146117e957806331e202cc146117bf57806331f9e35b146117a157806339509351146117515780634f2bfe5b14611728578063505362c4146116ff57806353f7425f146116bc5780635fcbd2851461169357806366be23221461167157806370a0823114611639578063715018a6146115d257806373dd0555146111095780637699b4cd146110d05780637915b1c3146110a657806379ba509714610fdd5780637b4dacef14610fc257806384d2422614610ef55780638b45a67314610ed15780638da5cb5b14610ea85780638fe8a10114610e8257806390827da714610ce1578063958da8de14610ca857806395d89b4114610b9757806396c55175146109915780639c46665c146109655780639e48d35e14610947578063a154f1bb1461087c578063a457c2d7146107d7578063a5870d6b146107ae578063a9059cbb14610743578063b07b709b1461069d578063b1bd608614610664578063bdc83b1f14610646578063c522498314610619578063c826860414610579578063c8562f721461055b578063caa0b9ed14610522578063dd62ed3e146104d3578063e30c3978146104aa578063ef78d4fd1461048c578063f2fde38b1461041e578063f77c4791146103f55763fc566d521461025257600080fd5b346103f257602090816003193601126103f25760043561027b61027433611f34565b1515611e18565b8161028533612464565b338352601884526040832090839160019384820195600291828401965b885481116103e4578187101561034557808352878a52600160408420015442101580610334575b6102dc575b6102d790611e8c565b6102a2565b9561032c6102d7916102f360408620548099611d09565b978986528a8d52866040872001600160ff19825416179055610316818954611e9b565b88556103256017918254611e9b565b9055611e8c565b9690506102ce565b5060ff8460408520015416156102c9565b5050509350509250505b8161035e575b50604051908152f35b6103a49061036c8333611fc3565b60075461038590849033906001600160a01b0316612986565b5061039d610392336120ca565b915460175490611e9b565b9033612265565b6103b081601a54611e9b565b601a556040518181527f222838db2794d11532d940e8dec38ae307ed0b63cd97c233322e221f998767a6833392a238610355565b50505093505092505061034f565b80fd5b50346103f257806003193601126103f257600a546040516001600160a01b039091168152602090f35b50346103f25760203660031901126103f257610438611c01565b610440611cb1565b600680546001600160a01b0319166001600160a01b039283169081179091556005549091167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227008380a380f35b50346103f257806003193601126103f2576020600f54604051908152f35b50346103f257806003193601126103f2576006546040516001600160a01b039091168152602090f35b50346103f25760403660031901126103f2576104ed611c01565b60406104f7611c17565b9260018060a01b03809316815260016020522091166000526020526020604060002054604051908152f35b50346103f25760203660031901126103f2576020906040906001600160a01b0361054a611c01565b168152601483522054604051908152f35b50346103f257806003193601126103f2576020600e54604051908152f35b50346103f257602090816003193601126103f257610595611c01565b6001600160a01b031681526018825260408120600181810154600292830192849291805b6105c8575b8686604051908152f35b80845284875260ff8260408620015416610614578260408520015442106105f9575b6105f390611e7f565b806105b9565b9461060c6105f391604086205490611d09565b9590506105ea565b6105be565b50346103f257806003193601126103f25760165460405160089190911c6001600160a01b03168152602090f35b50346103f257806003193601126103f2576020601754604051908152f35b50346103f25760203660031901126103f2576020906040906001600160a01b0361068c611c01565b168152601283522054604051908152f35b50346103f25760203660031901126103f2576106b7611c01565b6001600160a01b038181163314908115610735575b501561070857806106df6106fd92612464565b6106e8816120ca565b6106f760025460175490611e9b565b91612265565b602060405160018152f35b60405162461bcd60e51b8152602060048201526005602482015264047503030360dc1b6044820152606490fd5b9050600854163314826106cc565b50346103f25760403660031901126103f2576106fd610760611c01565b61079360243561077a81610773336120ca565b1015611e18565b61078333612464565b61078c83612464565b82336120f7565b6106df61079f336120ca565b61039d60025460175490611e9b565b50346103f257806003193601126103f2576009546040516001600160a01b039091168152602090f35b50346103f25760403660031901126103f2576107f1611c01565b60406024359233815260016020522060018060a01b03821660005260205260406000205491808310610829576106fd92039033611d16565b60405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608490fd5b50346103f25760203660031901126103f257610896611c01565b61089e611cb1565b6001600160a01b038181161561091a5760168054610100600160a81b03198116600885811b610100600160a81b031691909117909255604080516001600160a01b039290931c939093168116825290921660208301527f35f7c25f313d8b378045946ab43056cd8fbf3cb403496ebaa0beef117936ec3291a180f35b60405162461bcd60e51b8152602060048201526005602482015264043453030360dc1b6044820152606490fd5b50346103f257806003193601126103f2576020600c54604051908152f35b50346103f25760203660031901126103f2576020610989610984611c01565b6120ca565b604051908152f35b50346103f257602080600319360112610b93576109ac611c01565b9060018060a01b038083169182855260138152604085205491600b5416926040516381fc83bb60e01b81528160048201528281602481885afa8015610b595783908890610b64575b60405163eac6a66760e01b81526001600160a01b0389166004820152602481019190915291508180604481015b0381885afa908115610b59578791610b2c575b50610a3e866120ca565b604051633037408d60e01b81526001600160a01b038816600482015242602482015290958490829060449082905afa908115610b21578891610aec575b5090600d94610a949215918215610ae2575b5050612935565b855252604083205490602881029080820460281490151715610ace57610acb92916064610ac2920410612935565b6106df81612464565b80f35b634e487b7160e01b84526011600452602484fd5b1190503880610a8d565b9190508382813d8311610b1a575b610b048183611c8f565b81010312610b15579051600d610a7b565b600080fd5b503d610afa565b6040513d8a823e3d90fd5b90508281813d8311610b52575b610b438183611c8f565b81010312610b15575138610a34565b503d610b39565b6040513d89823e3d90fd5b5081813d8311610b8c575b610b798183611c8f565b81010312610b155782610a2191516109f4565b503d610b6f565b5080fd5b50346103f257806003193601126103f257604051908060045491600183811c92818516948515610c9e575b6020958686108114610c8a57858852879493929187908215610c68575050600114610c0e575b5050610bf692500383611c8f565b610c0a604051928284938452830190611bc1565b0390f35b90859250600482527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b858310610c50575050610bf693508201013880610be8565b80548389018501528794508693909201918101610c38565b9250935050610bf694915060ff191682840152151560051b8201013880610be8565b634e487b7160e01b83526022600452602483fd5b93607f1693610bc2565b50346103f25760203660031901126103f2576020906040906001600160a01b03610cd0611c01565b168152600d83522054604051908152f35b50346103f257602080600319360112610b935760043590610d03821515611e18565b610d1082610773336120ca565b610d1933612464565b62015180804201804211610e6e57819004818102918183041490151715610ace576224ea00810190818111610e585780855260198352610d5d846040872054611d09565b908552601983526040852055610d7583601a54611d09565b601a553384526018825260408420610d8e848254611d09565b8155600181019182549260018401809411610e445791600291847ff2619dcba9802bb8ec071016f659320c48304701ba220f0420bed16f87139a66969594558260405192610ddb84611c5f565b88845286840192835260408401958a87528a520185526040882091518255516001820155019051151560ff80198354169116179055610e38610e1f84601754611d09565b8060175561039d610e2f336120ca565b91600254611e9b565b6040519283523392a280f35b634e487b7160e01b87526011600452602487fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b85526011600452602485fd5b50346103f257806003193601126103f257602060ff60065460a01c166040519015158152f35b50346103f257806003193601126103f2576005546040516001600160a01b039091168152602090f35b50346103f25760203660031901126103f2576020610989610ef0611c01565b611f34565b50346103f257602090816003193601126103f257610f6a90610f15611c01565b610f1e81612464565b6001600160a01b039081168083526014855260408084205460085491516308b752bb60e41b81526004810193909352306024840152919491928692869290911690829081906044820190565b03915afa918215610fb65791610f85575b6109899250611e9b565b90508282813d8311610faf575b610f9c8183611c8f565b81010312610b1557610989915190610f7b565b503d610f92565b604051903d90823e3d90fd5b50346103f257806003193601126103f2576020610989611ea8565b50346103f257806003193601126103f2576006546001600160a01b03338183160361104f576bffffffffffffffffffffffff60a01b8092166006556005549133908316176005553391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a380f35b60405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608490fd5b50346103f25760203660031901126103f25760406020916004358152601983522054604051908152f35b50346103f25760203660031901126103f2576020906040906001600160a01b036110f8611c01565b168152601383522054604051908152f35b50346103f25760803660031901126103f25767ffffffffffffffff6064358181116115ba57366023820112156115ba5780600401359182116115be5782906040519261115f6020601f19601f8401160185611c8f565b80845236602482840101116115ba5780602460209301838601378301015261118a6004351515611e18565b6007546040516370a0823160e01b81523360048201526001600160a01b039091169190602081602481865afa801561143a578490611582575b6111d291506004351115611e18565b60018060a01b0360165460081c1690604051926111ee84611c2d565b835260043560208401526040519261120584611c5f565b8352602435602084015260443560408401526040519161122483611c2d565b308352600435602084015260018060a01b038451511690604051926370a0823160e01b8452306004850152602084602481865afa938415610b5957879461154a575b506024351580611540575b1561148157505082516020808501516040516323b872dd60e01b81523360048201526001600160a01b039093166024840152604483015291869160649183905af13d15601f3d116001875114161716156114455760206024935b51516040516370a0823160e01b815230600482015294859182906001600160a01b03165afa92831561143a578493611404575b5061130e60209161131894611e9b565b9101511015612969565b61132133612464565b33156113bf57611335600435600254611d09565b600255338152806020526040812060043581540190556040519060043582527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60203393a361138661079f336120ca565b60405160043581527fb831f69f1cebc12b23cd864ce5bfea2669d01956050a0147d71d418074559c2160203392a2602060405160018152f35b60405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606490fd5b92506020833d602011611432575b8161141f60209383611c8f565b81010312610b155791519161130e6112fe565b3d9150611412565b6040513d86823e3d90fd5b60405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b6044820152606490fd5b908092509594953b1561153c5760405163187945bd60e11b8152865180516001600160a01b0316600483015260200151602482015291859183919082908490829061150c9060208d810151604485015260408e015160648501528b516001600160a01b031660848501528b015160a48401523360c484015261010060e4840152610104830190611bc1565b03925af1801561143a57611527575b506020602493946112cb565b602493611535602092611c7b565b935061151b565b8480fd5b5060443515611271565b9093506020813d60201161157a575b8161156660209383611c8f565b8101031261157657519238611266565b8680fd5b3d9150611559565b506020813d6020116115b2575b8161159c60209383611c8f565b810103126115ae576111d290516111c3565b8380fd5b3d915061158f565b8280fd5b634e487b7160e01b83526041600452602483fd5b50346103f257806003193601126103f2576115eb611cb1565b600680546001600160a01b031990811690915560058054918216905581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346103f25760203660031901126103f2576020906040906001600160a01b03611661611c01565b1681528083522054604051908152f35b50346103f257806003193601126103f257602061098960025460175490611e9b565b50346103f257806003193601126103f2576007546040516001600160a01b039091168152602090f35b50346103f25760203660031901126103f25760409081906001600160a01b036116e3611c01565b1681526018602052206001815491015482519182526020820152f35b50346103f257806003193601126103f2576040602091600f548152601083522054604051908152f35b50346103f257806003193601126103f257600b546040516001600160a01b039091168152602090f35b50346103f25760403660031901126103f2576106fd9061179a611772611c01565b9133815260016020526040812060018060a01b03841682526020526040602435912054611d09565b9033611d16565b50346103f257806003193601126103f2576020601554604051908152f35b50346103f25760203660031901126103f25760406020916004358152601083522054604051908152f35b50346103f257806003193601126103f257602060405160128152f35b50346103f257806003193601126103f25761181f33611f34565b61182a811515611e18565b61183333612464565b3382526020916018835260408120600191828201549160029383858301945b6118a9575b87876118678861036c8333611fc3565b61187381601a54611e9b565b601a556040518181527f222838db2794d11532d940e8dec38ae307ed0b63cd97c233322e221f998767a6833392a2604051908152f35b80845284885260ff8660408620015416611910576118d490826040862001544210156118da57611e7f565b80611852565b60408520548760408720018460ff198254161790556118fa818654611e9b565b85556119096017918254611e9b565b9055611e7f565b611857565b50346103f25760603660031901126103f25761192f611c01565b90611938611c17565b9060406044359161194c83610773876120ca565b61195585612464565b61195e84612464565b6001600160a01b038516815260016020818152838320338452905291902054908101611998575b50826106df6106df92846106fd966120f7565b928184106119c0576106df826119b76106df946106fd97033385611d16565b92505092611985565b60405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606490fd5b50346103f257806003193601126103f2576020600254604051908152f35b50346103f257806003193601126103f2576020610989601a54611a44611ea8565b90611e9b565b50346103f25760403660031901126103f2576106fd611a67611c01565b6024359033611d16565b50346103f25760203660031901126103f257600435801515809103610b9357611a98611cb1565b6006805460ff60a01b191660a09290921b60ff60a01b1691909117905580f35b50346103f257806003193601126103f2576008546040516001600160a01b039091168152602090f35b82346103f257806003193601126103f2578060035491600183811c92818516948515611bb7575b6020958686108114610c8a57858852879493929187908215611b95575050600114611b3b575050610bf692500383611c8f565b90859250600382527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b858310611b7d575050610bf693508201018580610be8565b80548389018501528794508693909201918101611b65565b9250935050610bf694915060ff191682840152151560051b8201018580610be8565b93607f1693611b08565b919082519283825260005b848110611bed575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201611bcc565b600435906001600160a01b0382168203610b1557565b602435906001600160a01b0382168203610b1557565b6040810190811067ffffffffffffffff821117611c4957604052565b634e487b7160e01b600052604160045260246000fd5b6060810190811067ffffffffffffffff821117611c4957604052565b67ffffffffffffffff8111611c4957604052565b90601f8019910116810190811067ffffffffffffffff821117611c4957604052565b6005546001600160a01b03163303611cc557565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b91908201809211610e5857565b6001600160a01b03908116918215611dc75716918215611d775760207f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925918360005260018252604060002085600052825280604060002055604051908152a3565b60405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608490fd5b60405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608490fd5b15611e1f57565b60405162461bcd60e51b815260206004820152600560248201526421a298181960d91b6044820152606490fd5b8115611e56570490565b634e487b7160e01b600052601260045260246000fd5b81810292918115918404141715610e5857565b8015610e58576000190190565b6000198114610e585760010190565b91908203918211610e5857565b600062015180804201804211611f20578190049080820291808304821490151715611f20579082915b601c8310611edf5750505090565b9091928382028281048503610e5857611f1991611eff611f139286611e9b565b600052601960205260406000205490611d09565b93611e8c565b9190611ed1565b634e487b7160e01b83526011600452602483fd5b6001600160a01b031660009081526018602090815260408083206001818101549394936002928301939290805b611f70575b5050505050905090565b8060005284875260ff8285600020015416611fbe5782846000200154421015611fa3575b611f9d90611e7f565b80611f61565b94611fb6611f9d91856000205490611d09565b959050611f94565b611f66565b6001600160a01b0316801561207b5760009181835282602052604083205481811061202b57817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef926020928587528684520360408620558060025403600255604051908152a3565b60405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608490fd5b60405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608490fd5b60018060a01b031660005260006020526120f4604060002054601860205260406000205490611e9b565b90565b6001600160a01b0390811691821561221257169182156121c15760008281528060205260408120549180831061216d57604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652828652038282205586815220818154019055604051908152a3565b60405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608490fd5b60405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608490fd5b60405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608490fd5b600b5460408051633037408d60e01b81526001600160a01b0384811660048301524260248301529283169695929493909260209283856044818c5afa94851561242857600095612433575b508360249697989982519788809263d2dcd93360e01b82524260048301525afa958615612428576000966123f9575b506028870287810460281488151715610e5857606490048661238a575b7f47211fe8b1eecabef1c013b28eb9caa892fd6bf2d3f1f5111d08cc115de841659860e0989796959493929180891015612384575087935b169687600052600d855261235d826000205485846000205561235886600e54611d09565b611e9b565b9485600e5582519889528801528601526060850152608084015260a083015260c0820152a1565b93612334565b9695949392919061239b8583611e6c565b98603c8a0299808b04603c1490151715610e58576123e960e09960646123e28a7f47211fe8b1eecabef1c013b28eb9caa892fd6bf2d3f1f5111d08cc115de841659e611e4c565b0490611d09565b91929394959697985098506122fc565b90958482813d8311612421575b6124108183611c8f565b810103126103f257505194386122df565b503d612406565b50513d6000823e3d90fd5b9894848a813d831161245d575b61244a8183611c8f565b810103126103f2575097519397836122b0565b503d612440565b60405160009160c0820167ffffffffffffffff811183821017612921576040528260208301528260408301528260608301528260808301528260a0830152600f548083528352601060205260408320546020830152815183526011602052604083205460408301526015548060608401526080830152600c548060a08401526020830151111561283b575b600a546001600160a01b0316803b156115ae57838091602460405180948193638aca6a2360e01b83523060048401525af1801561143a57612828575b5060ff60065460a01c1661281d575b60208201518042116125ef575b50815160018101809111610ace579081604092845280600f55845260106020524282852055818301518351855260116020528285205560018060a01b031691828452600d602052670de0b6b3a76400006125ba838620546125b48585015160126020528689205490611e9b565b90611e6c565b0483855260146020526125d1838620918254611d09565b90550151908252601260205260408220556013602052604042912055565b600e5462093a808201808311610e585762093a80900462093a8081029080820462093a801490151715610e585742811015612816575b600a546001600160a01b031692869291905b6101f4841061264a575b50505050612547565b6126548183611e9b565b9062093a808104918262093a8081020462093a801483151715610e5857604051630cb8c08d60e31b815230600482015262093a809390930260248401526020836044818a5afa92831561280b579189918694938c946127d0575b5084612701575b50505050504281146126fb578062093a8081018111610e58574262093a80820110156126f15762093a806126ea910193611e8c565b9290612637565b506126ea42611f13565b80612641565b60a0830151868382101591826127c6575b50501561279d57506127758361275f84604061275789612752612752986125b46127476127839d61278d9f9d60600151611e6c565b9160a0880151611e9b565b611e4c565b910151611d09565b60408d015260808c015160608d01819052611e6c565b6125b460a08c015187611e9b565b6040880151611d09565b60408701525b81388781806126b5565b61275291506127b76127839460606127bc97950151611e6c565b611e6c565b6040870152612793565b1090508638612712565b9250925092506020813d602011612803575b816127ef60209383611c8f565b81010312610b1557849289915192386126ae565b3d91506127e2565b6040513d8c823e3d90fd5b5042612625565b82606083015261253a565b61283490939193611c7b565b913861252b565b60095460405163277dbafb60e01b81526001600160a01b039160209082906004908290899087165af19081156129165785916128e3575b50600c55600954604051631627391760e11b81529160209183916004918391165afa90811561143a5784916128b1575b508060808401526015556124ef565b90506020813d6020116128db575b816128cc60209383611c8f565b810103126115ae5751386128a2565b3d91506128bf565b90506020813d60201161290e575b816128fe60209383611c8f565b8101031261153c57516004612872565b3d91506128f1565b6040513d87823e3d90fd5b634e487b7160e01b84526041600452602484fd5b1561293c57565b60405162461bcd60e51b8152602060048201526005602482015264475030303160d81b6044820152606490fd5b1561297057565b634e487b7160e01b600052600160045260246000fd5b604080516370a0823160e01b8082526001600160a01b038086166004840181905292959394169260209291908387602481885afa968715612ade57600097612aae575b5060006044859288519063a9059cbb60e01b825260048201528a602482015282885af13d15601f3d1160016000511416171615612a7857906024839286519586938492835260048301525afa928315612a6e5750600092612a3d575b50506120f491612a3491611e9b565b91821115612969565b81819392933d8311612a67575b612a548183611c8f565b810103126103f257505181612a34612a25565b503d612a4a565b513d6000823e3d90fd5b845162461bcd60e51b815260048101849052600f60248201526e1514905394d1915497d19052531151608a1b6044820152606490fd5b90968482813d8311612ad7575b612ac58183611c8f565b810103126103f25750519560006129c9565b503d612abb565b86513d6000823e3d90fdfea26469706673582212206bed956b7effe049f0ab60543dc33361256b1d1e0807d7f2a3c83c8870d6113064736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c353bf07405304aeab75f4c2fac7e88d6a68f98e00000000000000000000000094afb2c17af24cfacf19f364628f459dfab2688f000000000000000000000000c53c83d26151dbcffa349fae20b6155299e87a35
-----Decoded View---------------
Arg [0] : _stakedToken (address): 0xc353Bf07405304AeaB75F4C2Fac7E88D6A68f98e
Arg [1] : _minter (address): 0x94aFb2C17af24cFAcf19f364628F459dfAB2688f
Arg [2] : _permit2Address (address): 0xC53c83d26151dBcfFa349Fae20B6155299E87a35
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000c353bf07405304aeab75f4c2fac7e88d6a68f98e
Arg [1] : 00000000000000000000000094afb2c17af24cfacf19f364628f459dfab2688f
Arg [2] : 000000000000000000000000c53c83d26151dbcffa349fae20b6155299e87a35
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.