Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Approve | 18258416 | 411 days ago | IN | 0 ETH | 0.00053245 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
18258328 | 411 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
SavingsFrax
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
No with 200 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.19; // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // ============================ SavingsFrax =========================== // ==================================================================== // Frax Finance: https://github.com/FraxFinance import { Timelock2Step } from "frax-std/access-control/v2/Timelock2Step.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { SafeCastLib } from "solmate/utils/SafeCastLib.sol"; import { LinearRewardsErc4626, ERC20 } from "./LinearRewardsErc4626.sol"; /// @title Savings Frax /// @notice A ERC4626 Vault implementation with linear rewards, rewards can be capped contract SavingsFrax is LinearRewardsErc4626, Timelock2Step { using SafeCastLib for *; /// @notice The maximum amount of rewards that can be distributed per second per 1e18 asset uint256 public maxDistributionPerSecondPerAsset; /// @param _underlying The erc20 asset deposited /// @param _name The name of the vault /// @param _symbol The symbol of the vault /// @param _rewardsCycleLength The length of the rewards cycle in seconds /// @param _maxDistributionPerSecondPerAsset The maximum amount of rewards that can be distributed per second per 1e18 asset /// @param _timelockAddress The address of the timelock/owner contract constructor( IERC20 _underlying, string memory _name, string memory _symbol, uint32 _rewardsCycleLength, uint256 _maxDistributionPerSecondPerAsset, address _timelockAddress ) LinearRewardsErc4626(ERC20(address(_underlying)), _name, _symbol, _rewardsCycleLength) Timelock2Step(_timelockAddress) { maxDistributionPerSecondPerAsset = _maxDistributionPerSecondPerAsset; } /// @notice The ```SetMaxDistributionPerSecondPerAsset``` event is emitted when the maxDistributionPerSecondPerAsset is set /// @param oldMax The old maxDistributionPerSecondPerAsset value /// @param newMax The new maxDistributionPerSecondPerAsset value event SetMaxDistributionPerSecondPerAsset(uint256 oldMax, uint256 newMax); /// @notice The ```setMaxDistributionPerSecondPerAsset``` function sets the maxDistributionPerSecondPerAsset /// @dev This function can only be called by the timelock, caps the value to type(uint64).max /// @param _maxDistributionPerSecondPerAsset The maximum amount of rewards that can be distributed per second per 1e18 asset function setMaxDistributionPerSecondPerAsset(uint256 _maxDistributionPerSecondPerAsset) external { _requireSenderIsTimelock(); syncRewardsAndDistribution(); // NOTES: prevents bricking the contract via overflow if (_maxDistributionPerSecondPerAsset > type(uint64).max) { _maxDistributionPerSecondPerAsset = type(uint64).max; } emit SetMaxDistributionPerSecondPerAsset({ oldMax: maxDistributionPerSecondPerAsset, newMax: _maxDistributionPerSecondPerAsset }); maxDistributionPerSecondPerAsset = _maxDistributionPerSecondPerAsset; } /// @notice The ```calculateRewardsToDistribute``` function calculates the amount of rewards to distribute based on the rewards cycle data and the time passed /// @param _rewardsCycleData The rewards cycle data /// @param _deltaTime The time passed since the last rewards distribution /// @return _rewardToDistribute The amount of rewards to distribute function calculateRewardsToDistribute( RewardsCycleData memory _rewardsCycleData, uint256 _deltaTime ) public view override returns (uint256 _rewardToDistribute) { _rewardToDistribute = super.calculateRewardsToDistribute(_rewardsCycleData, _deltaTime); // Cap rewards uint256 _maxDistribution = (maxDistributionPerSecondPerAsset * _deltaTime * storedTotalAssets) / PRECISION; if (_rewardToDistribute > _maxDistribution) { _rewardToDistribute = _maxDistribution; } } }
// SPDX-License-Identifier: ISC pragma solidity >=0.8.0; // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // ========================== Timelock2Step =========================== // ==================================================================== // Frax Finance: https://github.com/FraxFinance // Primary Author // Drake Evans: https://github.com/DrakeEvans // Reviewers // Dennis: https://github.com/denett // ==================================================================== /// @title Timelock2Step /// @author Drake Evans (Frax Finance) https://github.com/drakeevans /// @dev Inspired by OpenZeppelin's Ownable2Step contract /// @notice An abstract contract which contains 2-step transfer and renounce logic for a timelock address abstract contract Timelock2Step { /// @notice The pending timelock address address public pendingTimelockAddress; /// @notice The current timelock address address public timelockAddress; constructor(address _timelockAddress) { timelockAddress = _timelockAddress; } // ============================================================================================ // Functions: External Functions // ============================================================================================ /// @notice The ```transferTimelock``` function initiates the timelock transfer /// @dev Must be called by the current timelock /// @param _newTimelock The address of the nominated (pending) timelock function transferTimelock(address _newTimelock) external virtual { _requireSenderIsTimelock(); _transferTimelock(_newTimelock); } /// @notice The ```acceptTransferTimelock``` function completes the timelock transfer /// @dev Must be called by the pending timelock function acceptTransferTimelock() external virtual { _requireSenderIsPendingTimelock(); _acceptTransferTimelock(); } /// @notice The ```renounceTimelock``` function renounces the timelock after setting pending timelock to current timelock /// @dev Pending timelock must be set to current timelock before renouncing, creating a 2-step renounce process function renounceTimelock() external virtual { _requireSenderIsTimelock(); _requireSenderIsPendingTimelock(); _transferTimelock(address(0)); _setTimelock(address(0)); } // ============================================================================================ // Functions: Internal Actions // ============================================================================================ /// @notice The ```_transferTimelock``` function initiates the timelock transfer /// @dev This function is to be implemented by a public function /// @param _newTimelock The address of the nominated (pending) timelock function _transferTimelock(address _newTimelock) internal { pendingTimelockAddress = _newTimelock; emit TimelockTransferStarted(timelockAddress, _newTimelock); } /// @notice The ```_acceptTransferTimelock``` function completes the timelock transfer /// @dev This function is to be implemented by a public function function _acceptTransferTimelock() internal { pendingTimelockAddress = address(0); _setTimelock(msg.sender); } /// @notice The ```_setTimelock``` function sets the timelock address /// @dev This function is to be implemented by a public function /// @param _newTimelock The address of the new timelock function _setTimelock(address _newTimelock) internal { emit TimelockTransferred(timelockAddress, _newTimelock); timelockAddress = _newTimelock; } // ============================================================================================ // Functions: Internal Checks // ============================================================================================ /// @notice The ```_isTimelock``` function checks if _address is current timelock address /// @param _address The address to check against the timelock /// @return Whether or not msg.sender is current timelock address function _isTimelock(address _address) internal view returns (bool) { return _address == timelockAddress; } /// @notice The ```_requireIsTimelock``` function reverts if _address is not current timelock address /// @param _address The address to check against the timelock function _requireIsTimelock(address _address) internal view { if (!_isTimelock(_address)) revert AddressIsNotTimelock(timelockAddress, _address); } /// @notice The ```_requireSenderIsTimelock``` function reverts if msg.sender is not current timelock address /// @dev This function is to be implemented by a public function function _requireSenderIsTimelock() internal view { _requireIsTimelock(msg.sender); } /// @notice The ```_isPendingTimelock``` function checks if the _address is pending timelock address /// @dev This function is to be implemented by a public function /// @param _address The address to check against the pending timelock /// @return Whether or not _address is pending timelock address function _isPendingTimelock(address _address) internal view returns (bool) { return _address == pendingTimelockAddress; } /// @notice The ```_requireIsPendingTimelock``` function reverts if the _address is not pending timelock address /// @dev This function is to be implemented by a public function /// @param _address The address to check against the pending timelock function _requireIsPendingTimelock(address _address) internal view { if (!_isPendingTimelock(_address)) revert AddressIsNotPendingTimelock(pendingTimelockAddress, _address); } /// @notice The ```_requirePendingTimelock``` function reverts if msg.sender is not pending timelock address /// @dev This function is to be implemented by a public function function _requireSenderIsPendingTimelock() internal view { _requireIsPendingTimelock(msg.sender); } // ============================================================================================ // Functions: Events // ============================================================================================ /// @notice The ```TimelockTransferStarted``` event is emitted when the timelock transfer is initiated /// @param previousTimelock The address of the previous timelock /// @param newTimelock The address of the new timelock event TimelockTransferStarted(address indexed previousTimelock, address indexed newTimelock); /// @notice The ```TimelockTransferred``` event is emitted when the timelock transfer is completed /// @param previousTimelock The address of the previous timelock /// @param newTimelock The address of the new timelock event TimelockTransferred(address indexed previousTimelock, address indexed newTimelock); // ============================================================================================ // Functions: Errors // ============================================================================================ /// @notice Emitted when timelock is transferred error AddressIsNotTimelock(address timelockAddress, address actualAddress); /// @notice Emitted when pending timelock is transferred error AddressIsNotPendingTimelock(address pendingTimelockAddress, address actualAddress); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of 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}. * * 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 default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual 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: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Safe unsigned integer casting library that reverts on overflow. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeCastLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeCast.sol) library SafeCastLib { function safeCastTo248(uint256 x) internal pure returns (uint248 y) { require(x < 1 << 248); y = uint248(x); } function safeCastTo240(uint256 x) internal pure returns (uint240 y) { require(x < 1 << 240); y = uint240(x); } function safeCastTo232(uint256 x) internal pure returns (uint232 y) { require(x < 1 << 232); y = uint232(x); } function safeCastTo224(uint256 x) internal pure returns (uint224 y) { require(x < 1 << 224); y = uint224(x); } function safeCastTo216(uint256 x) internal pure returns (uint216 y) { require(x < 1 << 216); y = uint216(x); } function safeCastTo208(uint256 x) internal pure returns (uint208 y) { require(x < 1 << 208); y = uint208(x); } function safeCastTo200(uint256 x) internal pure returns (uint200 y) { require(x < 1 << 200); y = uint200(x); } function safeCastTo192(uint256 x) internal pure returns (uint192 y) { require(x < 1 << 192); y = uint192(x); } function safeCastTo184(uint256 x) internal pure returns (uint184 y) { require(x < 1 << 184); y = uint184(x); } function safeCastTo176(uint256 x) internal pure returns (uint176 y) { require(x < 1 << 176); y = uint176(x); } function safeCastTo168(uint256 x) internal pure returns (uint168 y) { require(x < 1 << 168); y = uint168(x); } function safeCastTo160(uint256 x) internal pure returns (uint160 y) { require(x < 1 << 160); y = uint160(x); } function safeCastTo152(uint256 x) internal pure returns (uint152 y) { require(x < 1 << 152); y = uint152(x); } function safeCastTo144(uint256 x) internal pure returns (uint144 y) { require(x < 1 << 144); y = uint144(x); } function safeCastTo136(uint256 x) internal pure returns (uint136 y) { require(x < 1 << 136); y = uint136(x); } function safeCastTo128(uint256 x) internal pure returns (uint128 y) { require(x < 1 << 128); y = uint128(x); } function safeCastTo120(uint256 x) internal pure returns (uint120 y) { require(x < 1 << 120); y = uint120(x); } function safeCastTo112(uint256 x) internal pure returns (uint112 y) { require(x < 1 << 112); y = uint112(x); } function safeCastTo104(uint256 x) internal pure returns (uint104 y) { require(x < 1 << 104); y = uint104(x); } function safeCastTo96(uint256 x) internal pure returns (uint96 y) { require(x < 1 << 96); y = uint96(x); } function safeCastTo88(uint256 x) internal pure returns (uint88 y) { require(x < 1 << 88); y = uint88(x); } function safeCastTo80(uint256 x) internal pure returns (uint80 y) { require(x < 1 << 80); y = uint80(x); } function safeCastTo72(uint256 x) internal pure returns (uint72 y) { require(x < 1 << 72); y = uint72(x); } function safeCastTo64(uint256 x) internal pure returns (uint64 y) { require(x < 1 << 64); y = uint64(x); } function safeCastTo56(uint256 x) internal pure returns (uint56 y) { require(x < 1 << 56); y = uint56(x); } function safeCastTo48(uint256 x) internal pure returns (uint48 y) { require(x < 1 << 48); y = uint48(x); } function safeCastTo40(uint256 x) internal pure returns (uint40 y) { require(x < 1 << 40); y = uint40(x); } function safeCastTo32(uint256 x) internal pure returns (uint32 y) { require(x < 1 << 32); y = uint32(x); } function safeCastTo24(uint256 x) internal pure returns (uint24 y) { require(x < 1 << 24); y = uint24(x); } function safeCastTo16(uint256 x) internal pure returns (uint16 y) { require(x < 1 << 16); y = uint16(x); } function safeCastTo8(uint256 x) internal pure returns (uint8 y) { require(x < 1 << 8); y = uint8(x); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.19; // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // ======================== LinearRewardsErc4626 ====================== // ==================================================================== // Frax Finance: https://github.com/FraxFinance import { ERC20, ERC4626 } from "solmate/mixins/ERC4626.sol"; import { SafeCastLib } from "solmate/utils/SafeCastLib.sol"; /// @title LinearRewardsErc4626 /// @notice An ERC4626 Vault implementation with linear rewards contract LinearRewardsErc4626 is ERC4626 { using SafeCastLib for *; /// @notice The precision of all integer calculations uint256 public constant PRECISION = 1e18; /// @notice The cycle length in seconds uint256 public immutable REWARDS_CYCLE_LENGTH; /// @notice Information about the current rewards cycle struct RewardsCycleData { uint40 cycleEnd; // Timestamp of the end of the current rewards cycle uint40 lastSync; // Timestamp of the last time the rewards cycle was synced uint216 rewardCycleAmount; // Amount of rewards to be distributed in the current cycle } /// @notice The rewards cycle data, stored in a single word to save gas RewardsCycleData public rewardsCycleData; /// @notice The timestamp of the last time rewards were distributed uint256 public lastRewardsDistribution; /// @notice The total amount of assets that have been distributed and deposited uint256 public storedTotalAssets; /// @param _underlying The erc20 asset deposited /// @param _name The name of the vault /// @param _symbol The symbol of the vault /// @param _rewardsCycleLength The length of the rewards cycle in seconds constructor( ERC20 _underlying, string memory _name, string memory _symbol, uint256 _rewardsCycleLength ) ERC4626(_underlying, _name, _symbol) { REWARDS_CYCLE_LENGTH = _rewardsCycleLength; // seed initial rewardsCycleEnd // NOTE: normally distribution of rewards should be done prior to _syncRewards but in this case we know there are no users or rewards yet. _syncRewards(); distributeRewards(); } /// @notice The ```calculateRewardsToDistribute``` function calculates the amount of rewards to distribute based on the rewards cycle data and the time passed /// @param _rewardsCycleData The rewards cycle data /// @param _deltaTime The time passed since the last rewards distribution /// @return _rewardToDistribute The amount of rewards to distribute function calculateRewardsToDistribute( RewardsCycleData memory _rewardsCycleData, uint256 _deltaTime ) public view virtual returns (uint256 _rewardToDistribute) { _rewardToDistribute = (_rewardsCycleData.rewardCycleAmount * _deltaTime) / (_rewardsCycleData.cycleEnd - _rewardsCycleData.lastSync); } /// @notice The ```previewDistributeRewards``` function is used to preview the rewards distributed at the top of the block /// @return _rewardToDistribute The amount of underlying to distribute function previewDistributeRewards() public view virtual returns (uint256 _rewardToDistribute) { // Cache state for gas savings RewardsCycleData memory _rewardsCycleData = rewardsCycleData; uint256 _lastRewardsDistribution = lastRewardsDistribution; uint40 _timestamp = block.timestamp.safeCastTo40(); // Calculate the delta time, but only include up to the cycle end uint256 _deltaTime = _timestamp > _rewardsCycleData.cycleEnd ? _rewardsCycleData.cycleEnd - _lastRewardsDistribution : _timestamp - _lastRewardsDistribution; // Calculate the rewards to distribute _rewardToDistribute = calculateRewardsToDistribute(_rewardsCycleData, _deltaTime); } /// @notice The ```distributeRewards``` function distributes the rewards once per block /// @return _rewardToDistribute The amount of underlying to distribute function distributeRewards() public virtual returns (uint256 _rewardToDistribute) { _rewardToDistribute = previewDistributeRewards(); // Only write to state if we need to update if (_rewardToDistribute != 0) { storedTotalAssets += _rewardToDistribute; } lastRewardsDistribution = block.timestamp; emit DistributeRewards(_rewardToDistribute); } /// @notice The ```previewSyncRewards``` function returns the updated rewards cycle data without updating the state /// @return _newRewardsCycleData The updated rewards cycle data function previewSyncRewards() public view virtual returns (RewardsCycleData memory _newRewardsCycleData) { RewardsCycleData memory _rewardsCycleData = rewardsCycleData; uint256 _timestamp = block.timestamp; // Only sync if the previous cycle has ended if (_timestamp <= _rewardsCycleData.cycleEnd) return _rewardsCycleData; // Calculate rewards for next cycle uint256 _newRewards = asset.balanceOf(address(this)) - storedTotalAssets; // Calculate the next cycle end, this keeps cycles at the same time regardless of when sync is called uint40 _cycleEnd = (((_timestamp + REWARDS_CYCLE_LENGTH) / REWARDS_CYCLE_LENGTH) * REWARDS_CYCLE_LENGTH) .safeCastTo40(); // This block prevents big jumps in rewards rate in case the sync happens near the end of the cycle if (_cycleEnd - _timestamp < REWARDS_CYCLE_LENGTH / 20) { _cycleEnd += REWARDS_CYCLE_LENGTH.safeCastTo40(); } // Write return values _rewardsCycleData.rewardCycleAmount = _newRewards.safeCastTo216(); _rewardsCycleData.lastSync = _timestamp.safeCastTo40(); _rewardsCycleData.cycleEnd = _cycleEnd; return _rewardsCycleData; } /// @notice The ```_syncRewards``` function is used to update the rewards cycle data function _syncRewards() internal virtual { RewardsCycleData memory _rewardsCycleData = previewSyncRewards(); if ( block.timestamp.safeCastTo40() == _rewardsCycleData.lastSync && rewardsCycleData.lastSync != _rewardsCycleData.lastSync ) { rewardsCycleData = _rewardsCycleData; emit SyncRewards({ cycleEnd: _rewardsCycleData.cycleEnd, lastSync: _rewardsCycleData.lastSync, rewardCycleAmount: _rewardsCycleData.rewardCycleAmount }); } } /// @notice The ```syncRewardsAndDistribution``` function is used to update the rewards cycle data and distribute rewards /// @dev rewards must be distributed before the cycle is synced function syncRewardsAndDistribution() public virtual { distributeRewards(); _syncRewards(); } /// @notice The ```totalAssets``` function returns the total assets available in the vault /// @dev This function simulates the rewards that will be distributed at the top of the block /// @return _totalAssets The total assets available in the vault function totalAssets() public view virtual override returns (uint256 _totalAssets) { uint256 _rewardToDistribute = previewDistributeRewards(); _totalAssets = storedTotalAssets + _rewardToDistribute; } function afterDeposit(uint256 amount, uint256 shares) internal virtual override { storedTotalAssets += amount; } /// @notice The ```deposit``` function allows a user to mint shares by depositing underlying /// @param _assets The amount of underlying to deposit /// @param _receiver The address to send the shares to /// @return _shares The amount of shares minted function deposit(uint256 _assets, address _receiver) public override returns (uint256 _shares) { distributeRewards(); _syncRewards(); _shares = super.deposit(_assets, _receiver); } /// @notice The ```mint``` function allows a user to mint a given number of shares /// @param _shares The amount of shares to mint /// @param _receiver The address to send the shares to /// @return _assets The amount of underlying deposited function mint(uint256 _shares, address _receiver) public override returns (uint256 _assets) { distributeRewards(); _syncRewards(); _assets = super.mint(_shares, _receiver); } function beforeWithdraw(uint256 amount, uint256 shares) internal virtual override { storedTotalAssets -= amount; } /// @notice The ```withdraw``` function allows a user to withdraw a given amount of underlying /// @param _assets The amount of underlying to withdraw /// @param _receiver The address to send the underlying to /// @param _owner The address of the owner of the shares /// @return _shares The amount of shares burned function withdraw(uint256 _assets, address _receiver, address _owner) public override returns (uint256 _shares) { distributeRewards(); _syncRewards(); _shares = super.withdraw(_assets, _receiver, _owner); } /// @notice The ```redeem``` function allows a user to redeem their shares for underlying /// @param _shares The amount of shares to redeem /// @param _receiver The address to send the underlying to /// @param _owner The address of the owner of the shares /// @return _assets The amount of underlying redeemed function redeem(uint256 _shares, address _receiver, address _owner) public override returns (uint256 _assets) { distributeRewards(); _syncRewards(); _assets = super.redeem(_shares, _receiver, _owner); } /// @notice The ```depositWithSignature``` function allows a user to use signed approvals to deposit /// @param _assets The amount of underlying to deposit /// @param _receiver The address to send the shares to /// @param _deadline The deadline for the signature /// @param _approveMax Whether or not to approve the maximum amount /// @param _v The v value of the signature /// @param _r The r value of the signature /// @param _s The s value of the signature /// @return _shares The amount of shares minted function depositWithSignature( uint256 _assets, address _receiver, uint256 _deadline, bool _approveMax, uint8 _v, bytes32 _r, bytes32 _s ) external returns (uint256 _shares) { uint256 amount = _approveMax ? type(uint256).max : _assets; asset.permit(msg.sender, address(this), amount, _deadline, _v, _r, _s); _shares = (deposit(_assets, _receiver)); } //============================================================================== // Events //============================================================================== /// @notice The ```SyncRewards``` event is emitted when the rewards cycle is synced /// @param cycleEnd The timestamp of the end of the current rewards cycle /// @param lastSync The timestamp of the last time the rewards cycle was synced /// @param rewardCycleAmount The amount of rewards to be distributed in the current cycle event SyncRewards(uint40 cycleEnd, uint40 lastSync, uint216 rewardCycleAmount); /// @notice The ```DistributeRewards``` event is emitted when rewards are distributed to storedTotalAssets /// @param rewardsToDistribute The amount of rewards that were distributed event DistributeRewards(uint256 rewardsToDistribute); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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 (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 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: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.sol"; import {SafeTransferLib} from "../utils/SafeTransferLib.sol"; import {FixedPointMathLib} from "../utils/FixedPointMathLib.sol"; /// @notice Minimal ERC4626 tokenized Vault implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/mixins/ERC4626.sol) abstract contract ERC4626 is ERC20 { using SafeTransferLib for ERC20; using FixedPointMathLib for uint256; /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares); event Withdraw( address indexed caller, address indexed receiver, address indexed owner, uint256 assets, uint256 shares ); /*////////////////////////////////////////////////////////////// IMMUTABLES //////////////////////////////////////////////////////////////*/ ERC20 public immutable asset; constructor( ERC20 _asset, string memory _name, string memory _symbol ) ERC20(_name, _symbol, _asset.decimals()) { asset = _asset; } /*////////////////////////////////////////////////////////////// DEPOSIT/WITHDRAWAL LOGIC //////////////////////////////////////////////////////////////*/ function deposit(uint256 assets, address receiver) public virtual returns (uint256 shares) { // Check for rounding error since we round down in previewDeposit. require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES"); // Need to transfer before minting or ERC777s could reenter. asset.safeTransferFrom(msg.sender, address(this), assets); _mint(receiver, shares); emit Deposit(msg.sender, receiver, assets, shares); afterDeposit(assets, shares); } function mint(uint256 shares, address receiver) public virtual returns (uint256 assets) { assets = previewMint(shares); // No need to check for rounding error, previewMint rounds up. // Need to transfer before minting or ERC777s could reenter. asset.safeTransferFrom(msg.sender, address(this), assets); _mint(receiver, shares); emit Deposit(msg.sender, receiver, assets, shares); afterDeposit(assets, shares); } function withdraw( uint256 assets, address receiver, address owner ) public virtual returns (uint256 shares) { shares = previewWithdraw(assets); // No need to check for rounding error, previewWithdraw rounds up. if (msg.sender != owner) { uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares; } beforeWithdraw(assets, shares); _burn(owner, shares); emit Withdraw(msg.sender, receiver, owner, assets, shares); asset.safeTransfer(receiver, assets); } function redeem( uint256 shares, address receiver, address owner ) public virtual returns (uint256 assets) { if (msg.sender != owner) { uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares; } // Check for rounding error since we round down in previewRedeem. require((assets = previewRedeem(shares)) != 0, "ZERO_ASSETS"); beforeWithdraw(assets, shares); _burn(owner, shares); emit Withdraw(msg.sender, receiver, owner, assets, shares); asset.safeTransfer(receiver, assets); } /*////////////////////////////////////////////////////////////// ACCOUNTING LOGIC //////////////////////////////////////////////////////////////*/ function totalAssets() public view virtual returns (uint256); function convertToShares(uint256 assets) public view virtual returns (uint256) { uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero. return supply == 0 ? assets : assets.mulDivDown(supply, totalAssets()); } function convertToAssets(uint256 shares) public view virtual returns (uint256) { uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero. return supply == 0 ? shares : shares.mulDivDown(totalAssets(), supply); } function previewDeposit(uint256 assets) public view virtual returns (uint256) { return convertToShares(assets); } function previewMint(uint256 shares) public view virtual returns (uint256) { uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero. return supply == 0 ? shares : shares.mulDivUp(totalAssets(), supply); } function previewWithdraw(uint256 assets) public view virtual returns (uint256) { uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero. return supply == 0 ? assets : assets.mulDivUp(supply, totalAssets()); } function previewRedeem(uint256 shares) public view virtual returns (uint256) { return convertToAssets(shares); } /*////////////////////////////////////////////////////////////// DEPOSIT/WITHDRAWAL LIMIT LOGIC //////////////////////////////////////////////////////////////*/ function maxDeposit(address) public view virtual returns (uint256) { return type(uint256).max; } function maxMint(address) public view virtual returns (uint256) { return type(uint256).max; } function maxWithdraw(address owner) public view virtual returns (uint256) { return convertToAssets(balanceOf[owner]); } function maxRedeem(address owner) public view virtual returns (uint256) { return balanceOf[owner]; } /*////////////////////////////////////////////////////////////// INTERNAL HOOKS LOGIC //////////////////////////////////////////////////////////////*/ function beforeWithdraw(uint256 assets, uint256 shares) internal virtual {} function afterDeposit(uint256 assets, uint256 shares) internal virtual {} }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.sol"; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. /// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller. library SafeTransferLib { /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; /// @solidity memory-safe-assembly assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } require(success, "ETH_TRANSFER_FAILED"); } /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( ERC20 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), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument. mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. 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( ERC20 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), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. 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( ERC20 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), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. 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"); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol) /// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) library FixedPointMathLib { /*////////////////////////////////////////////////////////////// SIMPLIFIED FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ uint256 internal constant MAX_UINT256 = 2**256 - 1; uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s. function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down. } function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up. } function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down. } function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up. } /*////////////////////////////////////////////////////////////// LOW LEVEL FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ function mulDivDown( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y)) if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) { revert(0, 0) } // Divide x * y by the denominator. z := div(mul(x, y), denominator) } } function mulDivUp( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y)) if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) { revert(0, 0) } // If x * y modulo the denominator is strictly greater than 0, // 1 is added to round up the division of x * y by the denominator. z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator)) } } function rpow( uint256 x, uint256 n, uint256 scalar ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { switch x case 0 { switch n case 0 { // 0 ** 0 = 1 z := scalar } default { // 0 ** n = 0 z := 0 } } default { switch mod(n, 2) case 0 { // If n is even, store scalar in z for now. z := scalar } default { // If n is odd, store x in z for now. z := x } // Shifting right by 1 is like dividing by 2. let half := shr(1, scalar) for { // Shift n right by 1 before looping to halve it. n := shr(1, n) } n { // Shift n right by 1 each iteration to halve it. n := shr(1, n) } { // Revert immediately if x ** 2 would overflow. // Equivalent to iszero(eq(div(xx, x), x)) here. if shr(128, x) { revert(0, 0) } // Store x squared. let xx := mul(x, x) // Round to the nearest number. let xxRound := add(xx, half) // Revert if xx + half overflowed. if lt(xxRound, xx) { revert(0, 0) } // Set x to scaled xxRound. x := div(xxRound, scalar) // If n is even: if mod(n, 2) { // Compute z * x. let zx := mul(z, x) // If z * x overflowed: if iszero(eq(div(zx, x), z)) { // Revert if x is non-zero. if iszero(iszero(x)) { revert(0, 0) } } // Round to the nearest number. let zxRound := add(zx, half) // Revert if zx + half overflowed. if lt(zxRound, zx) { revert(0, 0) } // Return properly scaled zxRound. z := div(zxRound, scalar) } } } } } /*////////////////////////////////////////////////////////////// GENERAL NUMBER UTILITIES //////////////////////////////////////////////////////////////*/ function sqrt(uint256 x) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { let y := x // We start y at x, which will help us make our initial estimate. z := 181 // The "correct" value is 1, but this saves a multiplication later. // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically. // We check y >= 2^(k + 8) but shift right by k bits // each branch to ensure that if x >= 256, then y >= 256. if iszero(lt(y, 0x10000000000000000000000000000000000)) { y := shr(128, y) z := shl(64, z) } if iszero(lt(y, 0x1000000000000000000)) { y := shr(64, y) z := shl(32, z) } if iszero(lt(y, 0x10000000000)) { y := shr(32, y) z := shl(16, z) } if iszero(lt(y, 0x1000000)) { y := shr(16, y) z := shl(8, z) } // Goal was to get z*z*y within a small factor of x. More iterations could // get y in a tighter range. Currently, we will have y in [256, 256*2^16). // We ensured y >= 256 so that the relative difference between y and y+1 is small. // That's not possible if x < 256 but we can just verify those cases exhaustively. // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256. // Correctness can be checked exhaustively for x < 256, so we assume y >= 256. // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps. // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256. // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18. // There is no overflow risk here since y < 2^136 after the first branch above. z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181. // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) // If x+1 is a perfect square, the Babylonian method cycles between // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor. // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case. // If you don't care whether the floor or ceil square root is returned, you can remove this statement. z := sub(z, lt(div(x, z), z)) } } function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Mod x by y. Note this will return // 0 instead of reverting if y is zero. z := mod(x, y) } } function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { // Divide x by y. Note this will return // 0 instead of reverting if y is zero. r := div(x, y) } } function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Add 1 to x * y if x % y > 0. Note this will // return 0 instead of reverting if y is zero. z := add(gt(mod(x, y), 0), div(x, y)) } } }
{ "remappings": [ "frax-std/=lib/frax-standard-solidity/src/", "solmate/=lib/solmate/src/", "@openzeppelin/=node_modules/@openzeppelin/", "ds-test/=lib/solmate/lib/ds-test/src/", "forge-std/=lib/frax-standard-solidity/lib/forge-std/src/", "frax-standard-solidity/=lib/frax-standard-solidity/src/", "solidity-bytes-utils/=lib/frax-standard-solidity/lib/solidity-bytes-utils/" ], "optimizer": { "enabled": false, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none", "appendCBOR": false }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IERC20","name":"_underlying","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint32","name":"_rewardsCycleLength","type":"uint32"},{"internalType":"uint256","name":"_maxDistributionPerSecondPerAsset","type":"uint256"},{"internalType":"address","name":"_timelockAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"pendingTimelockAddress","type":"address"},{"internalType":"address","name":"actualAddress","type":"address"}],"name":"AddressIsNotPendingTimelock","type":"error"},{"inputs":[{"internalType":"address","name":"timelockAddress","type":"address"},{"internalType":"address","name":"actualAddress","type":"address"}],"name":"AddressIsNotTimelock","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"rewardsToDistribute","type":"uint256"}],"name":"DistributeRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMax","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMax","type":"uint256"}],"name":"SetMaxDistributionPerSecondPerAsset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint40","name":"cycleEnd","type":"uint40"},{"indexed":false,"internalType":"uint40","name":"lastSync","type":"uint40"},{"indexed":false,"internalType":"uint216","name":"rewardCycleAmount","type":"uint216"}],"name":"SyncRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousTimelock","type":"address"},{"indexed":true,"internalType":"address","name":"newTimelock","type":"address"}],"name":"TimelockTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousTimelock","type":"address"},{"indexed":true,"internalType":"address","name":"newTimelock","type":"address"}],"name":"TimelockTransferred","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":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARDS_CYCLE_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptTransferTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","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":[],"name":"asset","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint40","name":"cycleEnd","type":"uint40"},{"internalType":"uint40","name":"lastSync","type":"uint40"},{"internalType":"uint216","name":"rewardCycleAmount","type":"uint216"}],"internalType":"struct LinearRewardsErc4626.RewardsCycleData","name":"_rewardsCycleData","type":"tuple"},{"internalType":"uint256","name":"_deltaTime","type":"uint256"}],"name":"calculateRewardsToDistribute","outputs":[{"internalType":"uint256","name":"_rewardToDistribute","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assets","type":"uint256"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assets","type":"uint256"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"bool","name":"_approveMax","type":"bool"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"depositWithSignature","outputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"distributeRewards","outputs":[{"internalType":"uint256","name":"_rewardToDistribute","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastRewardsDistribution","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxDistributionPerSecondPerAsset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"_assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingTimelockAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"previewDistributeRewards","outputs":[{"internalType":"uint256","name":"_rewardToDistribute","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"previewSyncRewards","outputs":[{"components":[{"internalType":"uint40","name":"cycleEnd","type":"uint40"},{"internalType":"uint40","name":"lastSync","type":"uint40"},{"internalType":"uint216","name":"rewardCycleAmount","type":"uint216"}],"internalType":"struct LinearRewardsErc4626.RewardsCycleData","name":"_newRewardsCycleData","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"_assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardsCycleData","outputs":[{"internalType":"uint40","name":"cycleEnd","type":"uint40"},{"internalType":"uint40","name":"lastSync","type":"uint40"},{"internalType":"uint216","name":"rewardCycleAmount","type":"uint216"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxDistributionPerSecondPerAsset","type":"uint256"}],"name":"setMaxDistributionPerSecondPerAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"storedTotalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"syncRewardsAndDistribution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"timelockAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"_totalAssets","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":"_newTimelock","type":"address"}],"name":"transferTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assets","type":"uint256"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101206040523480156200001257600080fd5b50604051620054f5380380620054f5833981810160405281019062000038919062000c7f565b808686868663ffffffff1683838381818473ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000094573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ba919062000d97565b8260009081620000cb91906200100a565b508160019081620000dd91906200100a565b508060ff1660808160ff16815250504660a0818152505062000104620001c860201b60201c565b60c081815250505050508273ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff16815250505050508061010081815250506200015e6200025860201b60201c565b6200016e620003c660201b60201c565b505050505080600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505081600c819055505050505050506200152d565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051620001fc9190620011a0565b60405180910390207fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc646306040516020016200023d959493929190620011f6565b60405160208183030381529060405280519060200120905090565b60006200026a6200044260201b60201c565b9050806020015164ffffffffff1662000289426200070d60201b60201c565b64ffffffffff16148015620002c65750806020015164ffffffffff16600660000160059054906101000a900464ffffffffff1664ffffffffff1614155b15620003c35780600660008201518160000160006101000a81548164ffffffffff021916908364ffffffffff16021790555060208201518160000160056101000a81548164ffffffffff021916908364ffffffffff16021790555060408201518160010160006101000a8154817affffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837affffffffffffffffffffffffffffffffffffffffffffffffffffff1602179055509050507fc32a546ed958490e37f30335e501e0a39438cb650a4851bfd4b775490af29dad816000015182602001518360400151604051620003ba93929190620012ad565b60405180910390a15b50565b6000620003d86200072a60201b60201c565b905060008114620003ff578060096000828254620003f7919062001319565b925050819055505b426008819055507fb9d196a585c1a894f648393ec7d52cc59ff6d94191579d073ba32b0a74d7f7a68160405162000437919062001354565b60405180910390a190565b6200044c6200097a565b600060066040518060600160405290816000820160009054906101000a900464ffffffffff1664ffffffffff1664ffffffffff1681526020016000820160059054906101000a900464ffffffffff1664ffffffffff1664ffffffffff1681526020016001820160009054906101000a90047affffffffffffffffffffffffffffffffffffffffffffffffffffff167affffffffffffffffffffffffffffffffffffffffffffffffffffff167affffffffffffffffffffffffffffffffffffffffffffffffffffff168152505090506000429050816000015164ffffffffff1681116200053d5781925050506200070a565b600060095460e05173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016200057f919062001371565b602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c391906200138e565b620005cf9190620013c0565b905060006200061461010051610100516101005186620005f0919062001319565b620005fc91906200142a565b62000608919062001462565b6200070d60201b60201c565b90506014610100516200062891906200142a565b838264ffffffffff166200063d9190620013c0565b1015620006685762000658610100516200070d60201b60201c565b81620006659190620014ad565b90505b62000679826200088360201b60201c565b84604001907affffffffffffffffffffffffffffffffffffffffffffffffffffff1690817affffffffffffffffffffffffffffffffffffffffffffffffffffff1681525050620006cf836200070d60201b60201c565b846020019064ffffffffff16908164ffffffffff168152505080846000019064ffffffffff16908164ffffffffff1681525050839450505050505b90565b60006501000000000082106200072257600080fd5b819050919050565b60008060066040518060600160405290816000820160009054906101000a900464ffffffffff1664ffffffffff1664ffffffffff1681526020016000820160059054906101000a900464ffffffffff1664ffffffffff1664ffffffffff1681526020016001820160009054906101000a90047affffffffffffffffffffffffffffffffffffffffffffffffffffff167affffffffffffffffffffffffffffffffffffffffffffffffffffff167affffffffffffffffffffffffffffffffffffffffffffffffffffff1681525050905060006008549050600062000813426200070d60201b60201c565b90506000836000015164ffffffffff168264ffffffffff16116200084c57828264ffffffffff16620008469190620013c0565b62000866565b82846000015164ffffffffff16620008659190620013c0565b5b90506200087a8482620008b660201b60201c565b94505050505090565b60007b010000000000000000000000000000000000000000000000000000008210620008ae57600080fd5b819050919050565b6000620008ca83836200091860201b60201c565b90506000670de0b6b3a764000060095484600c54620008ea919062001462565b620008f6919062001462565b6200090291906200142a565b90508082111562000911578091505b5092915050565b600082602001518360000151620009309190620014ed565b64ffffffffff168284604001517affffffffffffffffffffffffffffffffffffffffffffffffffffff1662000966919062001462565b6200097291906200142a565b905092915050565b6040518060600160405280600064ffffffffff168152602001600064ffffffffff16815260200160007affffffffffffffffffffffffffffffffffffffffffffffffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062000a0782620009da565b9050919050565b600062000a1b82620009fa565b9050919050565b62000a2d8162000a0e565b811462000a3957600080fd5b50565b60008151905062000a4d8162000a22565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b62000aa88262000a5d565b810181811067ffffffffffffffff8211171562000aca5762000ac962000a6e565b5b80604052505050565b600062000adf620009c6565b905062000aed828262000a9d565b919050565b600067ffffffffffffffff82111562000b105762000b0f62000a6e565b5b62000b1b8262000a5d565b9050602081019050919050565b60005b8381101562000b4857808201518184015260208101905062000b2b565b60008484015250505050565b600062000b6b62000b658462000af2565b62000ad3565b90508281526020810184848401111562000b8a5762000b8962000a58565b5b62000b9784828562000b28565b509392505050565b600082601f83011262000bb75762000bb662000a53565b5b815162000bc984826020860162000b54565b91505092915050565b600063ffffffff82169050919050565b62000bed8162000bd2565b811462000bf957600080fd5b50565b60008151905062000c0d8162000be2565b92915050565b6000819050919050565b62000c288162000c13565b811462000c3457600080fd5b50565b60008151905062000c488162000c1d565b92915050565b62000c5981620009fa565b811462000c6557600080fd5b50565b60008151905062000c798162000c4e565b92915050565b60008060008060008060c0878903121562000c9f5762000c9e620009d0565b5b600062000caf89828a0162000a3c565b965050602087015167ffffffffffffffff81111562000cd35762000cd2620009d5565b5b62000ce189828a0162000b9f565b955050604087015167ffffffffffffffff81111562000d055762000d04620009d5565b5b62000d1389828a0162000b9f565b945050606062000d2689828a0162000bfc565b935050608062000d3989828a0162000c37565b92505060a062000d4c89828a0162000c68565b9150509295509295509295565b600060ff82169050919050565b62000d718162000d59565b811462000d7d57600080fd5b50565b60008151905062000d918162000d66565b92915050565b60006020828403121562000db05762000daf620009d0565b5b600062000dc08482850162000d80565b91505092915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168062000e1c57607f821691505b60208210810362000e325762000e3162000dd4565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b60006008830262000e9c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000e5d565b62000ea8868362000e5d565b95508019841693508086168417925050509392505050565b6000819050919050565b600062000eeb62000ee562000edf8462000c13565b62000ec0565b62000c13565b9050919050565b6000819050919050565b62000f078362000eca565b62000f1f62000f168262000ef2565b84845462000e6a565b825550505050565b600090565b62000f3662000f27565b62000f4381848462000efc565b505050565b5b8181101562000f6b5762000f5f60008262000f2c565b60018101905062000f49565b5050565b601f82111562000fba5762000f848162000e38565b62000f8f8462000e4d565b8101602085101562000f9f578190505b62000fb762000fae8562000e4d565b83018262000f48565b50505b505050565b600082821c905092915050565b600062000fdf6000198460080262000fbf565b1980831691505092915050565b600062000ffa838362000fcc565b9150826002028217905092915050565b620010158262000dc9565b67ffffffffffffffff81111562001031576200103062000a6e565b5b6200103d825462000e03565b6200104a82828562000f6f565b600060209050601f8311600181146200108257600084156200106d578287015190505b62001079858262000fec565b865550620010e9565b601f198416620010928662000e38565b60005b82811015620010bc5784890151825560018201915060208501945060208101905062001095565b86831015620010dc5784890151620010d8601f89168262000fcc565b8355505b6001600288020188555050505b505050505050565b600081905092915050565b60008190508160005260206000209050919050565b60008154620011208162000e03565b6200112c8186620010f1565b945060018216600081146200114a5760018114620011605762001197565b60ff198316865281151582028601935062001197565b6200116b85620010fc565b60005b838110156200118f578154818901526001820191506020810190506200116e565b838801955050505b50505092915050565b6000620011ae828462001111565b915081905092915050565b6000819050919050565b620011ce81620011b9565b82525050565b620011df8162000c13565b82525050565b620011f081620009fa565b82525050565b600060a0820190506200120d6000830188620011c3565b6200121c6020830187620011c3565b6200122b6040830186620011c3565b6200123a6060830185620011d4565b620012496080830184620011e5565b9695505050505050565b600064ffffffffff82169050919050565b6200126f8162001253565b82525050565b60007affffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b620012a78162001275565b82525050565b6000606082019050620012c4600083018662001264565b620012d3602083018562001264565b620012e260408301846200129c565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000620013268262000c13565b9150620013338362000c13565b92508282019050808211156200134e576200134d620012ea565b5b92915050565b60006020820190506200136b6000830184620011d4565b92915050565b6000602082019050620013886000830184620011e5565b92915050565b600060208284031215620013a757620013a6620009d0565b5b6000620013b78482850162000c37565b91505092915050565b6000620013cd8262000c13565b9150620013da8362000c13565b9250828203905081811115620013f557620013f4620012ea565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000620014378262000c13565b9150620014448362000c13565b925082620014575762001456620013fb565b5b828204905092915050565b60006200146f8262000c13565b91506200147c8362000c13565b92508282026200148c8162000c13565b91508282048414831517620014a657620014a5620012ea565b5b5092915050565b6000620014ba8262001253565b9150620014c78362001253565b9250828201905064ffffffffff811115620014e757620014e6620012ea565b5b92915050565b6000620014fa8262001253565b9150620015078362001253565b9250828203905064ffffffffff811115620015275762001526620012ea565b5b92915050565b60805160a05160c05160e05161010051613f36620015bf60003960008181611120015281816114f701528181611518015281816115390152818161158201526115c9015260008181610feb015281816112890152818161144c015281816122200152818161232d0152818161260301526128a101526000610f7101526000610f3d01526000610dd40152613f366000f3fe608060405234801561001057600080fd5b506004361061028a5760003560e01c80636e553f651161015c578063b460af94116100ce578063d505accf11610087578063d505accf1461087f578063d71356e61461089b578063d905777e146108a5578063dd62ed3e146108d5578063ef8b30f714610905578063f6ccaad4146109355761028a565b8063b460af9414610771578063ba087652146107a1578063bd6f3603146107d1578063c63d75b6146107ef578063c6e6f5921461081f578063ce96cb771461084f5761028a565b80638f765d59116101205780638f765d591461068757806394bf804d146106a557806395d89b41146106d5578063a9059cbb146106f3578063aaf5eb6814610723578063b3d7f6b9146107415761028a565b80636e553f65146105a95780636f4a2cd0146105d957806370a08231146105f757806375e077c3146106275780637ecebe00146106575761028a565b80633644e515116102005780634bc66f32116101b95780634bc66f32146104f55780634cdad506146105135780634f8b4ae71461054357806356caf6051461054d5780635ebae5661461056b57806361c1c5e91461058b5761028a565b80633644e51514610421578063374010a41461043f57806338d52e0f1461046f578063402d267d1461048d57806345014095146104bd57806348f76e0f146104d95761028a565b80630a28a477116102525780630a28a4771461034957806318160ddd1461037957806323b872dd146103975780632af98d6d146103c7578063313ce567146103e5578063358245fc146104035761028a565b806301e1d1141461028f57806306fdde03146102ad57806307a2d13a146102cb578063090f3f50146102fb578063095ea7b314610319575b600080fd5b61029761093f565b6040516102a49190612e87565b60405180910390f35b6102b5610960565b6040516102c29190612f32565b60405180910390f35b6102e560048036038101906102e09190612f8f565b6109ee565b6040516102f29190612e87565b60405180910390f35b610303610a29565b6040516103109190612ffd565b60405180910390f35b610333600480360381019061032e9190613044565b610a4f565b604051610340919061309f565b60405180910390f35b610363600480360381019061035e9190612f8f565b610b41565b6040516103709190612e87565b60405180910390f35b610381610b7c565b60405161038e9190612e87565b60405180910390f35b6103b160048036038101906103ac91906130ba565b610b82565b6040516103be919061309f565b60405180910390f35b6103cf610dcc565b6040516103dc9190612e87565b60405180910390f35b6103ed610dd2565b6040516103fa9190613129565b60405180910390f35b61040b610df6565b6040516104189190612e87565b60405180910390f35b610429610f39565b604051610436919061315d565b60405180910390f35b610459600480360381019061045491906132ec565b610f96565b6040516104669190612e87565b60405180910390f35b610477610fe9565b604051610484919061338b565b60405180910390f35b6104a760048036038101906104a291906133a6565b61100d565b6040516104b49190612e87565b60405180910390f35b6104d760048036038101906104d291906133a6565b611037565b005b6104f360048036038101906104ee9190612f8f565b61104b565b005b6104fd6110c0565b60405161050a9190612ffd565b60405180910390f35b61052d60048036038101906105289190612f8f565b6110e6565b60405161053a9190612e87565b60405180910390f35b61054b6110f8565b005b61055561111e565b6040516105629190612e87565b60405180910390f35b610573611142565b604051610582939291906133f1565b60405180910390f35b6105936111a3565b6040516105a09190612e87565b60405180910390f35b6105c360048036038101906105be9190613428565b6111a9565b6040516105d09190612e87565b60405180910390f35b6105e16111ce565b6040516105ee9190612e87565b60405180910390f35b610611600480360381019061060c91906133a6565b61123d565b60405161061e9190612e87565b60405180910390f35b610641600480360381019061063c91906134ec565b611255565b60405161064e9190612e87565b60405180910390f35b610671600480360381019061066c91906133a6565b611336565b60405161067e9190612e87565b60405180910390f35b61068f61134e565b60405161069c91906135ee565b60405180910390f35b6106bf60048036038101906106ba9190613428565b611690565b6040516106cc9190612e87565b60405180910390f35b6106dd6116b5565b6040516106ea9190612f32565b60405180910390f35b61070d60048036038101906107089190613044565b611743565b60405161071a919061309f565b60405180910390f35b61072b611857565b6040516107389190612e87565b60405180910390f35b61075b60048036038101906107569190612f8f565b611863565b6040516107689190612e87565b60405180910390f35b61078b60048036038101906107869190613609565b61189e565b6040516107989190612e87565b60405180910390f35b6107bb60048036038101906107b69190613609565b6118c5565b6040516107c89190612e87565b60405180910390f35b6107d96118ec565b6040516107e69190612e87565b60405180910390f35b610809600480360381019061080491906133a6565b6118f2565b6040516108169190612e87565b60405180910390f35b61083960048036038101906108349190612f8f565b61191c565b6040516108469190612e87565b60405180910390f35b610869600480360381019061086491906133a6565b611957565b6040516108769190612e87565b60405180910390f35b6108996004803603810190610894919061365c565b6119a8565b005b6108a3611ca1565b005b6108bf60048036038101906108ba91906133a6565b611cb4565b6040516108cc9190612e87565b60405180910390f35b6108ef60048036038101906108ea91906136fe565b611cfd565b6040516108fc9190612e87565b60405180910390f35b61091f600480360381019061091a9190612f8f565b611d22565b60405161092c9190612e87565b60405180910390f35b61093d611d34565b005b60008061094a610df6565b90508060095461095a919061376d565b91505090565b6000805461096d906137d0565b80601f0160208091040260200160405190810160405280929190818152602001828054610999906137d0565b80156109e65780601f106109bb576101008083540402835291602001916109e6565b820191906000526020600020905b8154815290600101906020018083116109c957829003601f168201915b505050505081565b600080600254905060008114610a1f57610a1a610a0961093f565b8285611d469092919063ffffffff16565b610a21565b825b915050919050565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051610b2f9190612e87565b60405180910390a36001905092915050565b600080600254905060008114610b7257610b6d81610b5d61093f565b85611d899092919063ffffffff16565b610b74565b825b915050919050565b60025481565b600080600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610cb8578281610c379190613801565b600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b82600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610d079190613801565b9250508190555082600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef85604051610db89190612e87565b60405180910390a360019150509392505050565b600c5481565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060066040518060600160405290816000820160009054906101000a900464ffffffffff1664ffffffffff1664ffffffffff1681526020016000820160059054906101000a900464ffffffffff1664ffffffffff1664ffffffffff1681526020016001820160009054906101000a90047affffffffffffffffffffffffffffffffffffffffffffffffffffff167affffffffffffffffffffffffffffffffffffffffffffffffffffff167affffffffffffffffffffffffffffffffffffffffffffffffffffff16815250509050600060085490506000610ed742611dd5565b90506000836000015164ffffffffff168264ffffffffff1611610f0c57828264ffffffffff16610f079190613801565b610f24565b82846000015164ffffffffff16610f239190613801565b5b9050610f308482610f96565b94505050505090565b60007f00000000000000000000000000000000000000000000000000000000000000004614610f6f57610f6a611df1565b610f91565b7f00000000000000000000000000000000000000000000000000000000000000005b905090565b6000610fa28383611e7d565b90506000670de0b6b3a764000060095484600c54610fc09190613835565b610fca9190613835565b610fd491906138a6565b905080821115610fe2578091505b5092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9050919050565b61103f611ed9565b61104881611ee4565b50565b611053611ed9565b61105b611ca1565b67ffffffffffffffff801681111561107b5767ffffffffffffffff801690505b7f05d530f0fd6974b7d995fd3b71870f5301bb9fe086180bdd0bd36526728f5c6b600c54826040516110ae9291906138d7565b60405180910390a180600c8190555050565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006110f1826109ee565b9050919050565b611100611ed9565b611108611fa4565b6111126000611ee4565b61111c6000611faf565b565b7f000000000000000000000000000000000000000000000000000000000000000081565b60068060000160009054906101000a900464ffffffffff16908060000160059054906101000a900464ffffffffff16908060010160009054906101000a90047affffffffffffffffffffffffffffffffffffffffffffffffffffff16905083565b60095481565b60006111b36111ce565b506111bc61206f565b6111c683836121c9565b905092915050565b60006111d8610df6565b9050600081146111fc5780600960008282546111f4919061376d565b925050819055505b426008819055507fb9d196a585c1a894f648393ec7d52cc59ff6d94191579d073ba32b0a74d7f7a6816040516112329190612e87565b60405180910390a190565b60036020528060005260406000206000915090505481565b600080856112635788611285565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d505accf3330848b8a8a8a6040518863ffffffff1660e01b81526004016112ec9796959493929190613900565b600060405180830381600087803b15801561130657600080fd5b505af115801561131a573d6000803e3d6000fd5b5050505061132889896111a9565b915050979650505050505050565b60056020528060005260406000206000915090505481565b611356612e22565b600060066040518060600160405290816000820160009054906101000a900464ffffffffff1664ffffffffff1664ffffffffff1681526020016000820160059054906101000a900464ffffffffff1664ffffffffff1664ffffffffff1681526020016001820160009054906101000a90047affffffffffffffffffffffffffffffffffffffffffffffffffffff167affffffffffffffffffffffffffffffffffffffffffffffffffffff167affffffffffffffffffffffffffffffffffffffffffffffffffffff168152505090506000429050816000015164ffffffffff16811161144557819250505061168d565b60006009547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016114a39190612ffd565b602060405180830381865afa1580156114c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114e49190613984565b6114ee9190613801565b9050600061157c7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000086611563919061376d565b61156d91906138a6565b6115779190613835565b611dd5565b905060147f00000000000000000000000000000000000000000000000000000000000000006115ab91906138a6565b838264ffffffffff166115be9190613801565b10156115fb576115ed7f0000000000000000000000000000000000000000000000000000000000000000611dd5565b816115f891906139b1565b90505b611604826122e6565b84604001907affffffffffffffffffffffffffffffffffffffffffffffffffffff1690817affffffffffffffffffffffffffffffffffffffffffffffffffffff168152505061165283611dd5565b846020019064ffffffffff16908164ffffffffff168152505080846000019064ffffffffff16908164ffffffffff1681525050839450505050505b90565b600061169a6111ce565b506116a361206f565b6116ad8383612318565b905092915050565b600180546116c2906137d0565b80601f01602080910402602001604051908101604052809291908181526020018280546116ee906137d0565b801561173b5780601f106117105761010080835404028352916020019161173b565b820191906000526020600020905b81548152906001019060200180831161171e57829003601f168201915b505050505081565b600081600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546117949190613801565b9250508190555081600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516118459190612e87565b60405180910390a36001905092915050565b670de0b6b3a764000081565b6000806002549050600081146118945761188f61187e61093f565b8285611d899092919063ffffffff16565b611896565b825b915050919050565b60006118a86111ce565b506118b161206f565b6118bc8484846123f3565b90509392505050565b60006118cf6111ce565b506118d861206f565b6118e384848461264e565b90509392505050565b60085481565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9050919050565b60008060025490506000811461194d576119488161193861093f565b85611d469092919063ffffffff16565b61194f565b825b915050919050565b60006119a1600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546109ee565b9050919050565b428410156119eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119e290613a36565b60405180910390fd5b600060016119f7610f39565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98a8a8a600560008f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815480929190600101919050558b604051602001611a7f96959493929190613a56565b60405160208183030381529060405280519060200120604051602001611aa6929190613b2f565b6040516020818303038152906040528051906020012085858560405160008152602001604052604051611adc9493929190613b66565b6020604051602081039080840390855afa158015611afe573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015611b7257508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b611bb1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ba890613bf7565b60405180910390fd5b85600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92587604051611c909190612e87565b60405180910390a350505050505050565b611ca96111ce565b50611cb261206f565b565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6004602052816000526040600020602052806000526040600020600091509150505481565b6000611d2d8261191c565b9050919050565b611d3c611fa4565b611d446128ec565b565b6000827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0484118302158202611d7b57600080fd5b818385020490509392505050565b6000827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0484118302158202611dbe57600080fd5b818385020460008385870206110190509392505050565b6000650100000000008210611de957600080fd5b819050919050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611e239190613cba565b60405180910390207fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc64630604051602001611e62959493929190613cd1565b60405160208183030381529060405280519060200120905090565b600082602001518360000151611e939190613d24565b64ffffffffff168284604001517affffffffffffffffffffffffffffffffffffffffffffffffffffff16611ec79190613835565b611ed191906138a6565b905092915050565b611ee233612939565b565b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f162998b90abc2507f3953aa797827b03a14c42dbd9a35f09feaf02e0d592773a60405160405180910390a350565b611fad336129aa565b565b8073ffffffffffffffffffffffffffffffffffffffff16600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f31b6c5a04b069b6ec1b3cef44c4e7c1eadd721349cda9823d0b1877b3551cdc660405160405180910390a380600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061207961134e565b9050806020015164ffffffffff1661209042611dd5565b64ffffffffff161480156120cc5750806020015164ffffffffff16600660000160059054906101000a900464ffffffffff1664ffffffffff1614155b156121c65780600660008201518160000160006101000a81548164ffffffffff021916908364ffffffffff16021790555060208201518160000160056101000a81548164ffffffffff021916908364ffffffffff16021790555060408201518160010160006101000a8154817affffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837affffffffffffffffffffffffffffffffffffffffffffffffffffff1602179055509050507fc32a546ed958490e37f30335e501e0a39438cb650a4851bfd4b775490af29dad8160000151826020015183604001516040516121bd939291906133f1565b60405180910390a15b50565b6000806121d584611d22565b91508103612218576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161220f90613da9565b60405180910390fd5b6122653330857f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16612a1b909392919063ffffffff16565b61226f8282612ae6565b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d785846040516122ce9291906138d7565b60405180910390a36122e08382612bb6565b92915050565b60007b01000000000000000000000000000000000000000000000000000000821061231057600080fd5b819050919050565b600061232383611863565b90506123723330837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16612a1b909392919063ffffffff16565b61237c8284612ae6565b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d783866040516123db9291906138d7565b60405180910390a36123ed8184612bb6565b92915050565b60006123fe84610b41565b90508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461256a576000600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146125685781816124e79190613801565b600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b505b6125748482612bd3565b61257e8282612bf0565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db87856040516125f49291906138d7565b60405180910390a461264783857f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16612cc09092919063ffffffff16565b9392505050565b60008173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146127ba576000600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146127b85784816127379190613801565b600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b505b60006127c5856110e6565b91508103612808576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127ff90613e15565b60405180910390fd5b6128128185612bd3565b61281c8285612bf0565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db84886040516128929291906138d7565b60405180910390a46128e583827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16612cc09092919063ffffffff16565b9392505050565b6000600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061293733611faf565b565b61294281612d6e565b6129a757600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816040517f443dc2b400000000000000000000000000000000000000000000000000000000815260040161299e929190613e35565b60405180910390fd5b50565b6129b381612dc8565b612a1857600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816040517fbe5a9537000000000000000000000000000000000000000000000000000000008152600401612a0f929190613e35565b60405180910390fd5b50565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff841660248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080612adf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ad690613eaa565b60405180910390fd5b5050505050565b8060026000828254612af8919061376d565b9250508190555080600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612baa9190612e87565b60405180910390a35050565b8160096000828254612bc8919061376d565b925050819055505050565b8160096000828254612be59190613801565b925050819055505050565b80600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612c3f9190613801565b9250508190555080600260008282540392505081905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612cb49190612e87565b60405180910390a35050565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080612d68576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d5f90613f16565b60405180910390fd5b50505050565b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b6040518060600160405280600064ffffffffff168152602001600064ffffffffff16815260200160007affffffffffffffffffffffffffffffffffffffffffffffffffffff1681525090565b6000819050919050565b612e8181612e6e565b82525050565b6000602082019050612e9c6000830184612e78565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612edc578082015181840152602081019050612ec1565b60008484015250505050565b6000601f19601f8301169050919050565b6000612f0482612ea2565b612f0e8185612ead565b9350612f1e818560208601612ebe565b612f2781612ee8565b840191505092915050565b60006020820190508181036000830152612f4c8184612ef9565b905092915050565b6000604051905090565b600080fd5b612f6c81612e6e565b8114612f7757600080fd5b50565b600081359050612f8981612f63565b92915050565b600060208284031215612fa557612fa4612f5e565b5b6000612fb384828501612f7a565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612fe782612fbc565b9050919050565b612ff781612fdc565b82525050565b60006020820190506130126000830184612fee565b92915050565b61302181612fdc565b811461302c57600080fd5b50565b60008135905061303e81613018565b92915050565b6000806040838503121561305b5761305a612f5e565b5b60006130698582860161302f565b925050602061307a85828601612f7a565b9150509250929050565b60008115159050919050565b61309981613084565b82525050565b60006020820190506130b46000830184613090565b92915050565b6000806000606084860312156130d3576130d2612f5e565b5b60006130e18682870161302f565b93505060206130f28682870161302f565b925050604061310386828701612f7a565b9150509250925092565b600060ff82169050919050565b6131238161310d565b82525050565b600060208201905061313e600083018461311a565b92915050565b6000819050919050565b61315781613144565b82525050565b6000602082019050613172600083018461314e565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6131b582612ee8565b810181811067ffffffffffffffff821117156131d4576131d361317d565b5b80604052505050565b60006131e7612f54565b90506131f382826131ac565b919050565b600064ffffffffff82169050919050565b613212816131f8565b811461321d57600080fd5b50565b60008135905061322f81613209565b92915050565b60007affffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b61326581613235565b811461327057600080fd5b50565b6000813590506132828161325c565b92915050565b60006060828403121561329e5761329d613178565b5b6132a860606131dd565b905060006132b884828501613220565b60008301525060206132cc84828501613220565b60208301525060406132e084828501613273565b60408301525092915050565b6000806080838503121561330357613302612f5e565b5b600061331185828601613288565b925050606061332285828601612f7a565b9150509250929050565b6000819050919050565b600061335161334c61334784612fbc565b61332c565b612fbc565b9050919050565b600061336382613336565b9050919050565b600061337582613358565b9050919050565b6133858161336a565b82525050565b60006020820190506133a0600083018461337c565b92915050565b6000602082840312156133bc576133bb612f5e565b5b60006133ca8482850161302f565b91505092915050565b6133dc816131f8565b82525050565b6133eb81613235565b82525050565b600060608201905061340660008301866133d3565b61341360208301856133d3565b61342060408301846133e2565b949350505050565b6000806040838503121561343f5761343e612f5e565b5b600061344d85828601612f7a565b925050602061345e8582860161302f565b9150509250929050565b61347181613084565b811461347c57600080fd5b50565b60008135905061348e81613468565b92915050565b61349d8161310d565b81146134a857600080fd5b50565b6000813590506134ba81613494565b92915050565b6134c981613144565b81146134d457600080fd5b50565b6000813590506134e6816134c0565b92915050565b600080600080600080600060e0888a03121561350b5761350a612f5e565b5b60006135198a828b01612f7a565b975050602061352a8a828b0161302f565b965050604061353b8a828b01612f7a565b955050606061354c8a828b0161347f565b945050608061355d8a828b016134ab565b93505060a061356e8a828b016134d7565b92505060c061357f8a828b016134d7565b91505092959891949750929550565b613597816131f8565b82525050565b6135a681613235565b82525050565b6060820160008201516135c2600085018261358e565b5060208201516135d5602085018261358e565b5060408201516135e8604085018261359d565b50505050565b600060608201905061360360008301846135ac565b92915050565b60008060006060848603121561362257613621612f5e565b5b600061363086828701612f7a565b93505060206136418682870161302f565b92505060406136528682870161302f565b9150509250925092565b600080600080600080600060e0888a03121561367b5761367a612f5e565b5b60006136898a828b0161302f565b975050602061369a8a828b0161302f565b96505060406136ab8a828b01612f7a565b95505060606136bc8a828b01612f7a565b94505060806136cd8a828b016134ab565b93505060a06136de8a828b016134d7565b92505060c06136ef8a828b016134d7565b91505092959891949750929550565b6000806040838503121561371557613714612f5e565b5b60006137238582860161302f565b92505060206137348582860161302f565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061377882612e6e565b915061378383612e6e565b925082820190508082111561379b5761379a61373e565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806137e857607f821691505b6020821081036137fb576137fa6137a1565b5b50919050565b600061380c82612e6e565b915061381783612e6e565b925082820390508181111561382f5761382e61373e565b5b92915050565b600061384082612e6e565b915061384b83612e6e565b925082820261385981612e6e565b915082820484148315176138705761386f61373e565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006138b182612e6e565b91506138bc83612e6e565b9250826138cc576138cb613877565b5b828204905092915050565b60006040820190506138ec6000830185612e78565b6138f96020830184612e78565b9392505050565b600060e082019050613915600083018a612fee565b6139226020830189612fee565b61392f6040830188612e78565b61393c6060830187612e78565b613949608083018661311a565b61395660a083018561314e565b61396360c083018461314e565b98975050505050505050565b60008151905061397e81612f63565b92915050565b60006020828403121561399a57613999612f5e565b5b60006139a88482850161396f565b91505092915050565b60006139bc826131f8565b91506139c7836131f8565b9250828201905064ffffffffff8111156139e4576139e361373e565b5b92915050565b7f5045524d49545f444541444c494e455f45585049524544000000000000000000600082015250565b6000613a20601783612ead565b9150613a2b826139ea565b602082019050919050565b60006020820190508181036000830152613a4f81613a13565b9050919050565b600060c082019050613a6b600083018961314e565b613a786020830188612fee565b613a856040830187612fee565b613a926060830186612e78565b613a9f6080830185612e78565b613aac60a0830184612e78565b979650505050505050565b600081905092915050565b7f1901000000000000000000000000000000000000000000000000000000000000600082015250565b6000613af8600283613ab7565b9150613b0382613ac2565b600282019050919050565b6000819050919050565b613b29613b2482613144565b613b0e565b82525050565b6000613b3a82613aeb565b9150613b468285613b18565b602082019150613b568284613b18565b6020820191508190509392505050565b6000608082019050613b7b600083018761314e565b613b88602083018661311a565b613b95604083018561314e565b613ba2606083018461314e565b95945050505050565b7f494e56414c49445f5349474e4552000000000000000000000000000000000000600082015250565b6000613be1600e83612ead565b9150613bec82613bab565b602082019050919050565b60006020820190508181036000830152613c1081613bd4565b9050919050565b600081905092915050565b60008190508160005260206000209050919050565b60008154613c44816137d0565b613c4e8186613c17565b94506001821660008114613c695760018114613c7e57613cb1565b60ff1983168652811515820286019350613cb1565b613c8785613c22565b60005b83811015613ca957815481890152600182019150602081019050613c8a565b838801955050505b50505092915050565b6000613cc68284613c37565b915081905092915050565b600060a082019050613ce6600083018861314e565b613cf3602083018761314e565b613d00604083018661314e565b613d0d6060830185612e78565b613d1a6080830184612fee565b9695505050505050565b6000613d2f826131f8565b9150613d3a836131f8565b9250828203905064ffffffffff811115613d5757613d5661373e565b5b92915050565b7f5a45524f5f534841524553000000000000000000000000000000000000000000600082015250565b6000613d93600b83612ead565b9150613d9e82613d5d565b602082019050919050565b60006020820190508181036000830152613dc281613d86565b9050919050565b7f5a45524f5f415353455453000000000000000000000000000000000000000000600082015250565b6000613dff600b83612ead565b9150613e0a82613dc9565b602082019050919050565b60006020820190508181036000830152613e2e81613df2565b9050919050565b6000604082019050613e4a6000830185612fee565b613e576020830184612fee565b9392505050565b7f5452414e534645525f46524f4d5f4641494c4544000000000000000000000000600082015250565b6000613e94601483612ead565b9150613e9f82613e5e565b602082019050919050565b60006020820190508181036000830152613ec381613e87565b9050919050565b7f5452414e534645525f4641494c45440000000000000000000000000000000000600082015250565b6000613f00600f83612ead565b9150613f0b82613eca565b602082019050919050565b60006020820190508181036000830152613f2f81613ef3565b905091905056000000000000000000000000853d955acef822db058eb8505911ed77f175b99e00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000093a8000000000000000000000000000000000000000000000000000000001699a6ed80000000000000000000000008412ebf45bac1b340bbe8f318b928c466c4e39ca000000000000000000000000000000000000000000000000000000000000000c536176696e67732046726178000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057346524158000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061028a5760003560e01c80636e553f651161015c578063b460af94116100ce578063d505accf11610087578063d505accf1461087f578063d71356e61461089b578063d905777e146108a5578063dd62ed3e146108d5578063ef8b30f714610905578063f6ccaad4146109355761028a565b8063b460af9414610771578063ba087652146107a1578063bd6f3603146107d1578063c63d75b6146107ef578063c6e6f5921461081f578063ce96cb771461084f5761028a565b80638f765d59116101205780638f765d591461068757806394bf804d146106a557806395d89b41146106d5578063a9059cbb146106f3578063aaf5eb6814610723578063b3d7f6b9146107415761028a565b80636e553f65146105a95780636f4a2cd0146105d957806370a08231146105f757806375e077c3146106275780637ecebe00146106575761028a565b80633644e515116102005780634bc66f32116101b95780634bc66f32146104f55780634cdad506146105135780634f8b4ae71461054357806356caf6051461054d5780635ebae5661461056b57806361c1c5e91461058b5761028a565b80633644e51514610421578063374010a41461043f57806338d52e0f1461046f578063402d267d1461048d57806345014095146104bd57806348f76e0f146104d95761028a565b80630a28a477116102525780630a28a4771461034957806318160ddd1461037957806323b872dd146103975780632af98d6d146103c7578063313ce567146103e5578063358245fc146104035761028a565b806301e1d1141461028f57806306fdde03146102ad57806307a2d13a146102cb578063090f3f50146102fb578063095ea7b314610319575b600080fd5b61029761093f565b6040516102a49190612e87565b60405180910390f35b6102b5610960565b6040516102c29190612f32565b60405180910390f35b6102e560048036038101906102e09190612f8f565b6109ee565b6040516102f29190612e87565b60405180910390f35b610303610a29565b6040516103109190612ffd565b60405180910390f35b610333600480360381019061032e9190613044565b610a4f565b604051610340919061309f565b60405180910390f35b610363600480360381019061035e9190612f8f565b610b41565b6040516103709190612e87565b60405180910390f35b610381610b7c565b60405161038e9190612e87565b60405180910390f35b6103b160048036038101906103ac91906130ba565b610b82565b6040516103be919061309f565b60405180910390f35b6103cf610dcc565b6040516103dc9190612e87565b60405180910390f35b6103ed610dd2565b6040516103fa9190613129565b60405180910390f35b61040b610df6565b6040516104189190612e87565b60405180910390f35b610429610f39565b604051610436919061315d565b60405180910390f35b610459600480360381019061045491906132ec565b610f96565b6040516104669190612e87565b60405180910390f35b610477610fe9565b604051610484919061338b565b60405180910390f35b6104a760048036038101906104a291906133a6565b61100d565b6040516104b49190612e87565b60405180910390f35b6104d760048036038101906104d291906133a6565b611037565b005b6104f360048036038101906104ee9190612f8f565b61104b565b005b6104fd6110c0565b60405161050a9190612ffd565b60405180910390f35b61052d60048036038101906105289190612f8f565b6110e6565b60405161053a9190612e87565b60405180910390f35b61054b6110f8565b005b61055561111e565b6040516105629190612e87565b60405180910390f35b610573611142565b604051610582939291906133f1565b60405180910390f35b6105936111a3565b6040516105a09190612e87565b60405180910390f35b6105c360048036038101906105be9190613428565b6111a9565b6040516105d09190612e87565b60405180910390f35b6105e16111ce565b6040516105ee9190612e87565b60405180910390f35b610611600480360381019061060c91906133a6565b61123d565b60405161061e9190612e87565b60405180910390f35b610641600480360381019061063c91906134ec565b611255565b60405161064e9190612e87565b60405180910390f35b610671600480360381019061066c91906133a6565b611336565b60405161067e9190612e87565b60405180910390f35b61068f61134e565b60405161069c91906135ee565b60405180910390f35b6106bf60048036038101906106ba9190613428565b611690565b6040516106cc9190612e87565b60405180910390f35b6106dd6116b5565b6040516106ea9190612f32565b60405180910390f35b61070d60048036038101906107089190613044565b611743565b60405161071a919061309f565b60405180910390f35b61072b611857565b6040516107389190612e87565b60405180910390f35b61075b60048036038101906107569190612f8f565b611863565b6040516107689190612e87565b60405180910390f35b61078b60048036038101906107869190613609565b61189e565b6040516107989190612e87565b60405180910390f35b6107bb60048036038101906107b69190613609565b6118c5565b6040516107c89190612e87565b60405180910390f35b6107d96118ec565b6040516107e69190612e87565b60405180910390f35b610809600480360381019061080491906133a6565b6118f2565b6040516108169190612e87565b60405180910390f35b61083960048036038101906108349190612f8f565b61191c565b6040516108469190612e87565b60405180910390f35b610869600480360381019061086491906133a6565b611957565b6040516108769190612e87565b60405180910390f35b6108996004803603810190610894919061365c565b6119a8565b005b6108a3611ca1565b005b6108bf60048036038101906108ba91906133a6565b611cb4565b6040516108cc9190612e87565b60405180910390f35b6108ef60048036038101906108ea91906136fe565b611cfd565b6040516108fc9190612e87565b60405180910390f35b61091f600480360381019061091a9190612f8f565b611d22565b60405161092c9190612e87565b60405180910390f35b61093d611d34565b005b60008061094a610df6565b90508060095461095a919061376d565b91505090565b6000805461096d906137d0565b80601f0160208091040260200160405190810160405280929190818152602001828054610999906137d0565b80156109e65780601f106109bb576101008083540402835291602001916109e6565b820191906000526020600020905b8154815290600101906020018083116109c957829003601f168201915b505050505081565b600080600254905060008114610a1f57610a1a610a0961093f565b8285611d469092919063ffffffff16565b610a21565b825b915050919050565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051610b2f9190612e87565b60405180910390a36001905092915050565b600080600254905060008114610b7257610b6d81610b5d61093f565b85611d899092919063ffffffff16565b610b74565b825b915050919050565b60025481565b600080600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610cb8578281610c379190613801565b600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b82600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610d079190613801565b9250508190555082600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef85604051610db89190612e87565b60405180910390a360019150509392505050565b600c5481565b7f000000000000000000000000000000000000000000000000000000000000001281565b60008060066040518060600160405290816000820160009054906101000a900464ffffffffff1664ffffffffff1664ffffffffff1681526020016000820160059054906101000a900464ffffffffff1664ffffffffff1664ffffffffff1681526020016001820160009054906101000a90047affffffffffffffffffffffffffffffffffffffffffffffffffffff167affffffffffffffffffffffffffffffffffffffffffffffffffffff167affffffffffffffffffffffffffffffffffffffffffffffffffffff16815250509050600060085490506000610ed742611dd5565b90506000836000015164ffffffffff168264ffffffffff1611610f0c57828264ffffffffff16610f079190613801565b610f24565b82846000015164ffffffffff16610f239190613801565b5b9050610f308482610f96565b94505050505090565b60007f00000000000000000000000000000000000000000000000000000000000000014614610f6f57610f6a611df1565b610f91565b7f9e304003948e420cd07c68c550f02fd9638e5cf11b531b879c8a918e711b9c9e5b905090565b6000610fa28383611e7d565b90506000670de0b6b3a764000060095484600c54610fc09190613835565b610fca9190613835565b610fd491906138a6565b905080821115610fe2578091505b5092915050565b7f000000000000000000000000853d955acef822db058eb8505911ed77f175b99e81565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9050919050565b61103f611ed9565b61104881611ee4565b50565b611053611ed9565b61105b611ca1565b67ffffffffffffffff801681111561107b5767ffffffffffffffff801690505b7f05d530f0fd6974b7d995fd3b71870f5301bb9fe086180bdd0bd36526728f5c6b600c54826040516110ae9291906138d7565b60405180910390a180600c8190555050565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006110f1826109ee565b9050919050565b611100611ed9565b611108611fa4565b6111126000611ee4565b61111c6000611faf565b565b7f0000000000000000000000000000000000000000000000000000000000093a8081565b60068060000160009054906101000a900464ffffffffff16908060000160059054906101000a900464ffffffffff16908060010160009054906101000a90047affffffffffffffffffffffffffffffffffffffffffffffffffffff16905083565b60095481565b60006111b36111ce565b506111bc61206f565b6111c683836121c9565b905092915050565b60006111d8610df6565b9050600081146111fc5780600960008282546111f4919061376d565b925050819055505b426008819055507fb9d196a585c1a894f648393ec7d52cc59ff6d94191579d073ba32b0a74d7f7a6816040516112329190612e87565b60405180910390a190565b60036020528060005260406000206000915090505481565b600080856112635788611285565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b90507f000000000000000000000000853d955acef822db058eb8505911ed77f175b99e73ffffffffffffffffffffffffffffffffffffffff1663d505accf3330848b8a8a8a6040518863ffffffff1660e01b81526004016112ec9796959493929190613900565b600060405180830381600087803b15801561130657600080fd5b505af115801561131a573d6000803e3d6000fd5b5050505061132889896111a9565b915050979650505050505050565b60056020528060005260406000206000915090505481565b611356612e22565b600060066040518060600160405290816000820160009054906101000a900464ffffffffff1664ffffffffff1664ffffffffff1681526020016000820160059054906101000a900464ffffffffff1664ffffffffff1664ffffffffff1681526020016001820160009054906101000a90047affffffffffffffffffffffffffffffffffffffffffffffffffffff167affffffffffffffffffffffffffffffffffffffffffffffffffffff167affffffffffffffffffffffffffffffffffffffffffffffffffffff168152505090506000429050816000015164ffffffffff16811161144557819250505061168d565b60006009547f000000000000000000000000853d955acef822db058eb8505911ed77f175b99e73ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016114a39190612ffd565b602060405180830381865afa1580156114c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114e49190613984565b6114ee9190613801565b9050600061157c7f0000000000000000000000000000000000000000000000000000000000093a807f0000000000000000000000000000000000000000000000000000000000093a807f0000000000000000000000000000000000000000000000000000000000093a8086611563919061376d565b61156d91906138a6565b6115779190613835565b611dd5565b905060147f0000000000000000000000000000000000000000000000000000000000093a806115ab91906138a6565b838264ffffffffff166115be9190613801565b10156115fb576115ed7f0000000000000000000000000000000000000000000000000000000000093a80611dd5565b816115f891906139b1565b90505b611604826122e6565b84604001907affffffffffffffffffffffffffffffffffffffffffffffffffffff1690817affffffffffffffffffffffffffffffffffffffffffffffffffffff168152505061165283611dd5565b846020019064ffffffffff16908164ffffffffff168152505080846000019064ffffffffff16908164ffffffffff1681525050839450505050505b90565b600061169a6111ce565b506116a361206f565b6116ad8383612318565b905092915050565b600180546116c2906137d0565b80601f01602080910402602001604051908101604052809291908181526020018280546116ee906137d0565b801561173b5780601f106117105761010080835404028352916020019161173b565b820191906000526020600020905b81548152906001019060200180831161171e57829003601f168201915b505050505081565b600081600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546117949190613801565b9250508190555081600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516118459190612e87565b60405180910390a36001905092915050565b670de0b6b3a764000081565b6000806002549050600081146118945761188f61187e61093f565b8285611d899092919063ffffffff16565b611896565b825b915050919050565b60006118a86111ce565b506118b161206f565b6118bc8484846123f3565b90509392505050565b60006118cf6111ce565b506118d861206f565b6118e384848461264e565b90509392505050565b60085481565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9050919050565b60008060025490506000811461194d576119488161193861093f565b85611d469092919063ffffffff16565b61194f565b825b915050919050565b60006119a1600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546109ee565b9050919050565b428410156119eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119e290613a36565b60405180910390fd5b600060016119f7610f39565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98a8a8a600560008f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815480929190600101919050558b604051602001611a7f96959493929190613a56565b60405160208183030381529060405280519060200120604051602001611aa6929190613b2f565b6040516020818303038152906040528051906020012085858560405160008152602001604052604051611adc9493929190613b66565b6020604051602081039080840390855afa158015611afe573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015611b7257508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b611bb1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ba890613bf7565b60405180910390fd5b85600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92587604051611c909190612e87565b60405180910390a350505050505050565b611ca96111ce565b50611cb261206f565b565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6004602052816000526040600020602052806000526040600020600091509150505481565b6000611d2d8261191c565b9050919050565b611d3c611fa4565b611d446128ec565b565b6000827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0484118302158202611d7b57600080fd5b818385020490509392505050565b6000827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0484118302158202611dbe57600080fd5b818385020460008385870206110190509392505050565b6000650100000000008210611de957600080fd5b819050919050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611e239190613cba565b60405180910390207fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc64630604051602001611e62959493929190613cd1565b60405160208183030381529060405280519060200120905090565b600082602001518360000151611e939190613d24565b64ffffffffff168284604001517affffffffffffffffffffffffffffffffffffffffffffffffffffff16611ec79190613835565b611ed191906138a6565b905092915050565b611ee233612939565b565b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f162998b90abc2507f3953aa797827b03a14c42dbd9a35f09feaf02e0d592773a60405160405180910390a350565b611fad336129aa565b565b8073ffffffffffffffffffffffffffffffffffffffff16600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f31b6c5a04b069b6ec1b3cef44c4e7c1eadd721349cda9823d0b1877b3551cdc660405160405180910390a380600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061207961134e565b9050806020015164ffffffffff1661209042611dd5565b64ffffffffff161480156120cc5750806020015164ffffffffff16600660000160059054906101000a900464ffffffffff1664ffffffffff1614155b156121c65780600660008201518160000160006101000a81548164ffffffffff021916908364ffffffffff16021790555060208201518160000160056101000a81548164ffffffffff021916908364ffffffffff16021790555060408201518160010160006101000a8154817affffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837affffffffffffffffffffffffffffffffffffffffffffffffffffff1602179055509050507fc32a546ed958490e37f30335e501e0a39438cb650a4851bfd4b775490af29dad8160000151826020015183604001516040516121bd939291906133f1565b60405180910390a15b50565b6000806121d584611d22565b91508103612218576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161220f90613da9565b60405180910390fd5b6122653330857f000000000000000000000000853d955acef822db058eb8505911ed77f175b99e73ffffffffffffffffffffffffffffffffffffffff16612a1b909392919063ffffffff16565b61226f8282612ae6565b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d785846040516122ce9291906138d7565b60405180910390a36122e08382612bb6565b92915050565b60007b01000000000000000000000000000000000000000000000000000000821061231057600080fd5b819050919050565b600061232383611863565b90506123723330837f000000000000000000000000853d955acef822db058eb8505911ed77f175b99e73ffffffffffffffffffffffffffffffffffffffff16612a1b909392919063ffffffff16565b61237c8284612ae6565b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d783866040516123db9291906138d7565b60405180910390a36123ed8184612bb6565b92915050565b60006123fe84610b41565b90508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461256a576000600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146125685781816124e79190613801565b600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b505b6125748482612bd3565b61257e8282612bf0565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db87856040516125f49291906138d7565b60405180910390a461264783857f000000000000000000000000853d955acef822db058eb8505911ed77f175b99e73ffffffffffffffffffffffffffffffffffffffff16612cc09092919063ffffffff16565b9392505050565b60008173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146127ba576000600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146127b85784816127379190613801565b600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b505b60006127c5856110e6565b91508103612808576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127ff90613e15565b60405180910390fd5b6128128185612bd3565b61281c8285612bf0565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db84886040516128929291906138d7565b60405180910390a46128e583827f000000000000000000000000853d955acef822db058eb8505911ed77f175b99e73ffffffffffffffffffffffffffffffffffffffff16612cc09092919063ffffffff16565b9392505050565b6000600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061293733611faf565b565b61294281612d6e565b6129a757600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816040517f443dc2b400000000000000000000000000000000000000000000000000000000815260040161299e929190613e35565b60405180910390fd5b50565b6129b381612dc8565b612a1857600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816040517fbe5a9537000000000000000000000000000000000000000000000000000000008152600401612a0f929190613e35565b60405180910390fd5b50565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff841660248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080612adf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ad690613eaa565b60405180910390fd5b5050505050565b8060026000828254612af8919061376d565b9250508190555080600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612baa9190612e87565b60405180910390a35050565b8160096000828254612bc8919061376d565b925050819055505050565b8160096000828254612be59190613801565b925050819055505050565b80600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612c3f9190613801565b9250508190555080600260008282540392505081905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612cb49190612e87565b60405180910390a35050565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080612d68576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d5f90613f16565b60405180910390fd5b50505050565b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b6040518060600160405280600064ffffffffff168152602001600064ffffffffff16815260200160007affffffffffffffffffffffffffffffffffffffffffffffffffffff1681525090565b6000819050919050565b612e8181612e6e565b82525050565b6000602082019050612e9c6000830184612e78565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612edc578082015181840152602081019050612ec1565b60008484015250505050565b6000601f19601f8301169050919050565b6000612f0482612ea2565b612f0e8185612ead565b9350612f1e818560208601612ebe565b612f2781612ee8565b840191505092915050565b60006020820190508181036000830152612f4c8184612ef9565b905092915050565b6000604051905090565b600080fd5b612f6c81612e6e565b8114612f7757600080fd5b50565b600081359050612f8981612f63565b92915050565b600060208284031215612fa557612fa4612f5e565b5b6000612fb384828501612f7a565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612fe782612fbc565b9050919050565b612ff781612fdc565b82525050565b60006020820190506130126000830184612fee565b92915050565b61302181612fdc565b811461302c57600080fd5b50565b60008135905061303e81613018565b92915050565b6000806040838503121561305b5761305a612f5e565b5b60006130698582860161302f565b925050602061307a85828601612f7a565b9150509250929050565b60008115159050919050565b61309981613084565b82525050565b60006020820190506130b46000830184613090565b92915050565b6000806000606084860312156130d3576130d2612f5e565b5b60006130e18682870161302f565b93505060206130f28682870161302f565b925050604061310386828701612f7a565b9150509250925092565b600060ff82169050919050565b6131238161310d565b82525050565b600060208201905061313e600083018461311a565b92915050565b6000819050919050565b61315781613144565b82525050565b6000602082019050613172600083018461314e565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6131b582612ee8565b810181811067ffffffffffffffff821117156131d4576131d361317d565b5b80604052505050565b60006131e7612f54565b90506131f382826131ac565b919050565b600064ffffffffff82169050919050565b613212816131f8565b811461321d57600080fd5b50565b60008135905061322f81613209565b92915050565b60007affffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b61326581613235565b811461327057600080fd5b50565b6000813590506132828161325c565b92915050565b60006060828403121561329e5761329d613178565b5b6132a860606131dd565b905060006132b884828501613220565b60008301525060206132cc84828501613220565b60208301525060406132e084828501613273565b60408301525092915050565b6000806080838503121561330357613302612f5e565b5b600061331185828601613288565b925050606061332285828601612f7a565b9150509250929050565b6000819050919050565b600061335161334c61334784612fbc565b61332c565b612fbc565b9050919050565b600061336382613336565b9050919050565b600061337582613358565b9050919050565b6133858161336a565b82525050565b60006020820190506133a0600083018461337c565b92915050565b6000602082840312156133bc576133bb612f5e565b5b60006133ca8482850161302f565b91505092915050565b6133dc816131f8565b82525050565b6133eb81613235565b82525050565b600060608201905061340660008301866133d3565b61341360208301856133d3565b61342060408301846133e2565b949350505050565b6000806040838503121561343f5761343e612f5e565b5b600061344d85828601612f7a565b925050602061345e8582860161302f565b9150509250929050565b61347181613084565b811461347c57600080fd5b50565b60008135905061348e81613468565b92915050565b61349d8161310d565b81146134a857600080fd5b50565b6000813590506134ba81613494565b92915050565b6134c981613144565b81146134d457600080fd5b50565b6000813590506134e6816134c0565b92915050565b600080600080600080600060e0888a03121561350b5761350a612f5e565b5b60006135198a828b01612f7a565b975050602061352a8a828b0161302f565b965050604061353b8a828b01612f7a565b955050606061354c8a828b0161347f565b945050608061355d8a828b016134ab565b93505060a061356e8a828b016134d7565b92505060c061357f8a828b016134d7565b91505092959891949750929550565b613597816131f8565b82525050565b6135a681613235565b82525050565b6060820160008201516135c2600085018261358e565b5060208201516135d5602085018261358e565b5060408201516135e8604085018261359d565b50505050565b600060608201905061360360008301846135ac565b92915050565b60008060006060848603121561362257613621612f5e565b5b600061363086828701612f7a565b93505060206136418682870161302f565b92505060406136528682870161302f565b9150509250925092565b600080600080600080600060e0888a03121561367b5761367a612f5e565b5b60006136898a828b0161302f565b975050602061369a8a828b0161302f565b96505060406136ab8a828b01612f7a565b95505060606136bc8a828b01612f7a565b94505060806136cd8a828b016134ab565b93505060a06136de8a828b016134d7565b92505060c06136ef8a828b016134d7565b91505092959891949750929550565b6000806040838503121561371557613714612f5e565b5b60006137238582860161302f565b92505060206137348582860161302f565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061377882612e6e565b915061378383612e6e565b925082820190508082111561379b5761379a61373e565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806137e857607f821691505b6020821081036137fb576137fa6137a1565b5b50919050565b600061380c82612e6e565b915061381783612e6e565b925082820390508181111561382f5761382e61373e565b5b92915050565b600061384082612e6e565b915061384b83612e6e565b925082820261385981612e6e565b915082820484148315176138705761386f61373e565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006138b182612e6e565b91506138bc83612e6e565b9250826138cc576138cb613877565b5b828204905092915050565b60006040820190506138ec6000830185612e78565b6138f96020830184612e78565b9392505050565b600060e082019050613915600083018a612fee565b6139226020830189612fee565b61392f6040830188612e78565b61393c6060830187612e78565b613949608083018661311a565b61395660a083018561314e565b61396360c083018461314e565b98975050505050505050565b60008151905061397e81612f63565b92915050565b60006020828403121561399a57613999612f5e565b5b60006139a88482850161396f565b91505092915050565b60006139bc826131f8565b91506139c7836131f8565b9250828201905064ffffffffff8111156139e4576139e361373e565b5b92915050565b7f5045524d49545f444541444c494e455f45585049524544000000000000000000600082015250565b6000613a20601783612ead565b9150613a2b826139ea565b602082019050919050565b60006020820190508181036000830152613a4f81613a13565b9050919050565b600060c082019050613a6b600083018961314e565b613a786020830188612fee565b613a856040830187612fee565b613a926060830186612e78565b613a9f6080830185612e78565b613aac60a0830184612e78565b979650505050505050565b600081905092915050565b7f1901000000000000000000000000000000000000000000000000000000000000600082015250565b6000613af8600283613ab7565b9150613b0382613ac2565b600282019050919050565b6000819050919050565b613b29613b2482613144565b613b0e565b82525050565b6000613b3a82613aeb565b9150613b468285613b18565b602082019150613b568284613b18565b6020820191508190509392505050565b6000608082019050613b7b600083018761314e565b613b88602083018661311a565b613b95604083018561314e565b613ba2606083018461314e565b95945050505050565b7f494e56414c49445f5349474e4552000000000000000000000000000000000000600082015250565b6000613be1600e83612ead565b9150613bec82613bab565b602082019050919050565b60006020820190508181036000830152613c1081613bd4565b9050919050565b600081905092915050565b60008190508160005260206000209050919050565b60008154613c44816137d0565b613c4e8186613c17565b94506001821660008114613c695760018114613c7e57613cb1565b60ff1983168652811515820286019350613cb1565b613c8785613c22565b60005b83811015613ca957815481890152600182019150602081019050613c8a565b838801955050505b50505092915050565b6000613cc68284613c37565b915081905092915050565b600060a082019050613ce6600083018861314e565b613cf3602083018761314e565b613d00604083018661314e565b613d0d6060830185612e78565b613d1a6080830184612fee565b9695505050505050565b6000613d2f826131f8565b9150613d3a836131f8565b9250828203905064ffffffffff811115613d5757613d5661373e565b5b92915050565b7f5a45524f5f534841524553000000000000000000000000000000000000000000600082015250565b6000613d93600b83612ead565b9150613d9e82613d5d565b602082019050919050565b60006020820190508181036000830152613dc281613d86565b9050919050565b7f5a45524f5f415353455453000000000000000000000000000000000000000000600082015250565b6000613dff600b83612ead565b9150613e0a82613dc9565b602082019050919050565b60006020820190508181036000830152613e2e81613df2565b9050919050565b6000604082019050613e4a6000830185612fee565b613e576020830184612fee565b9392505050565b7f5452414e534645525f46524f4d5f4641494c4544000000000000000000000000600082015250565b6000613e94601483612ead565b9150613e9f82613e5e565b602082019050919050565b60006020820190508181036000830152613ec381613e87565b9050919050565b7f5452414e534645525f4641494c45440000000000000000000000000000000000600082015250565b6000613f00600f83612ead565b9150613f0b82613eca565b602082019050919050565b60006020820190508181036000830152613f2f81613ef3565b905091905056
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000853d955acef822db058eb8505911ed77f175b99e00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000093a8000000000000000000000000000000000000000000000000000000001699a6ed80000000000000000000000008412ebf45bac1b340bbe8f318b928c466c4e39ca000000000000000000000000000000000000000000000000000000000000000c536176696e67732046726178000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057346524158000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _underlying (address): 0x853d955aCEf822Db058eb8505911ED77F175b99e
Arg [1] : _name (string): Savings Frax
Arg [2] : _symbol (string): sFRAX
Arg [3] : _rewardsCycleLength (uint32): 604800
Arg [4] : _maxDistributionPerSecondPerAsset (uint256): 6066695896
Arg [5] : _timelockAddress (address): 0x8412ebf45bAC1B340BbE8F318b928C466c4E39CA
-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 000000000000000000000000853d955acef822db058eb8505911ed77f175b99e
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [3] : 0000000000000000000000000000000000000000000000000000000000093a80
Arg [4] : 00000000000000000000000000000000000000000000000000000001699a6ed8
Arg [5] : 0000000000000000000000008412ebf45bac1b340bbe8f318b928c466c4e39ca
Arg [6] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [7] : 536176696e677320467261780000000000000000000000000000000000000000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [9] : 7346524158000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $0.996562 | 1,072.2131 | $1,068.53 |
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.