Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 25 from a total of 140 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Upgrade Proxy | 2863581 | 50 days ago | IN | 0 ETH | 0.00000226 | ||||
Upgrade Proxy | 2856571 | 51 days ago | IN | 0 ETH | 0.00000227 | ||||
Upgrade Proxy | 2856024 | 51 days ago | IN | 0 ETH | 0.00000228 | ||||
Upgrade Proxy | 2855242 | 51 days ago | IN | 0 ETH | 0.00000282 | ||||
Claim Exited Ass... | 2837917 | 54 days ago | IN | 0 ETH | 0.0000171 | ||||
Deposit | 2837263 | 54 days ago | IN | 0 ETH | 0.00002672 | ||||
Deposit | 2837224 | 54 days ago | IN | 0 ETH | 0.0000284 | ||||
Deposit | 2837212 | 54 days ago | IN | 0 ETH | 0.0000284 | ||||
Deposit | 2837165 | 54 days ago | IN | 0 ETH | 0.0000284 | ||||
Multicall | 2837118 | 54 days ago | IN | 0 ETH | 0.00003441 | ||||
Claim Exited Ass... | 2823406 | 56 days ago | IN | 0 ETH | 0.00006527 | ||||
Multicall | 2818250 | 57 days ago | IN | 0 ETH | 0.00006283 | ||||
Deposit | 2811230 | 58 days ago | IN | 0 ETH | 0.00005962 | ||||
Claim Exited Ass... | 2810818 | 58 days ago | IN | 0 ETH | 0.00006392 | ||||
Enter Exit Queue | 2791818 | 61 days ago | IN | 0 ETH | 0.00014223 | ||||
Enter Exit Queue | 2791605 | 61 days ago | IN | 0 ETH | 0.00015116 | ||||
Multicall | 2791577 | 61 days ago | IN | 0 ETH | 0.00051715 | ||||
Deposit | 2789892 | 61 days ago | IN | 0 ETH | 0.00006779 | ||||
Multicall | 2789851 | 61 days ago | IN | 0 ETH | 0.0000697 | ||||
Multicall | 2787353 | 61 days ago | IN | 0 ETH | 0.00009146 | ||||
Multicall | 2787341 | 61 days ago | IN | 0 ETH | 0.00011058 | ||||
Multicall | 2785001 | 62 days ago | IN | 0 ETH | 0.0001951 | ||||
Multicall | 2784771 | 62 days ago | IN | 0 ETH | 0.00016501 | ||||
Deposit | 2784231 | 62 days ago | IN | 0 ETH | 0.00019491 | ||||
Deposit | 2784215 | 62 days ago | IN | 0 ETH | 0.00016254 |
Latest 25 internal transactions (View All)
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
EthAaveLeverageStrategy
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.26; import {WETH9} from '@aave-core/dependencies/weth/WETH9.sol'; import {IEthVault} from '@stakewise-core/interfaces/IEthVault.sol'; import {IStrategy} from '../interfaces/IStrategy.sol'; import {IStrategyProxy} from '../interfaces/IStrategyProxy.sol'; import {LeverageStrategy} from './LeverageStrategy.sol'; import {AaveLeverageStrategy} from './AaveLeverageStrategy.sol'; /** * @title EthAaveLeverageStrategy * @author StakeWise * @notice Defines the Aave leverage strategy functionality on Ethereum */ contract EthAaveLeverageStrategy is AaveLeverageStrategy { /** * @dev Constructor * @param osToken The address of the OsToken contract * @param assetToken The address of the asset token contract (e.g. WETH) * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param osTokenFlashLoans The address of the OsTokenFlashLoans contract * @param osTokenVaultEscrow The address of the OsTokenVaultEscrow contract * @param strategiesRegistry The address of the StrategiesRegistry contract * @param strategyProxyImplementation The address of the StrategyProxy implementation * @param balancerVault The address of the BalancerVault contract * @param aavePool The address of the Aave pool contract * @param aaveOsToken The address of the Aave OsToken contract * @param aaveVarDebtAssetToken The address of the Aave variable debt asset token contract */ constructor( address osToken, address assetToken, address osTokenVaultController, address osTokenConfig, address osTokenFlashLoans, address osTokenVaultEscrow, address strategiesRegistry, address strategyProxyImplementation, address balancerVault, address aavePool, address aaveOsToken, address aaveVarDebtAssetToken ) AaveLeverageStrategy( osToken, assetToken, osTokenVaultController, osTokenConfig, osTokenFlashLoans, osTokenVaultEscrow, strategiesRegistry, strategyProxyImplementation, balancerVault, aavePool, aaveOsToken, aaveVarDebtAssetToken ) {} /// @inheritdoc IStrategy function strategyId() public pure override returns (bytes32) { return keccak256('EthAaveLeverageStrategy'); } /// @inheritdoc LeverageStrategy function _claimOsTokenVaultEscrowAssets( address vault, address proxy, uint256 positionTicket, uint256 osTokenShares ) internal override returns (uint256 claimedAssets) { claimedAssets = super._claimOsTokenVaultEscrowAssets(vault, proxy, positionTicket, osTokenShares); if (claimedAssets == 0) return 0; // convert ETH to WETH IStrategyProxy(proxy).executeWithValue( address(_assetToken), abi.encodeWithSelector(WETH9(payable(address(_assetToken))).deposit.selector), claimedAssets ); } /// @inheritdoc LeverageStrategy function _mintOsTokenShares( address vault, address proxy, uint256 depositAssets, uint256 mintOsTokenShares ) internal override returns (uint256) { IStrategyProxy(proxy).execute( address(_assetToken), abi.encodeWithSelector(WETH9(payable(address(_assetToken))).withdraw.selector, depositAssets) ); uint256 balanceBefore = _osToken.balanceOf(proxy); IStrategyProxy(proxy).executeWithValue( vault, abi.encodeWithSelector( IEthVault(vault).depositAndMintOsToken.selector, proxy, mintOsTokenShares, address(0) ), depositAssets ); return _osToken.balanceOf(proxy) - balanceBefore; } /// @inheritdoc LeverageStrategy function _transferAssets(address proxy, address receiver, uint256 amount) internal override { IStrategyProxy(proxy).execute( address(_assetToken), abi.encodeWithSelector(WETH9(payable(address(_assetToken))).withdraw.selector, amount) ); IStrategyProxy(proxy).sendValue(payable(receiver), amount); } }
// Copyright (C) 2015, 2016, 2017 Dapphub // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity ^0.8.10; contract WETH9 { string public name = 'Wrapped Ether'; string public symbol = 'WETH'; uint8 public decimals = 18; event Approval(address indexed src, address indexed guy, uint256 wad); event Transfer(address indexed src, address indexed dst, uint256 wad); event Deposit(address indexed dst, uint256 wad); event Withdrawal(address indexed src, uint256 wad); mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; receive() external payable { deposit(); } function deposit() public payable { balanceOf[msg.sender] += msg.value; emit Deposit(msg.sender, msg.value); } function withdraw(uint256 wad) public { require(balanceOf[msg.sender] >= wad); balanceOf[msg.sender] -= wad; payable(msg.sender).transfer(wad); emit Withdrawal(msg.sender, wad); } function totalSupply() public view returns (uint256) { return address(this).balance; } function approve(address guy, uint256 wad) public returns (bool) { allowance[msg.sender][guy] = wad; emit Approval(msg.sender, guy, wad); return true; } function transfer(address dst, uint256 wad) public returns (bool) { return transferFrom(msg.sender, dst, wad); } function transferFrom(address src, address dst, uint256 wad) public returns (bool) { require(balanceOf[src] >= wad); if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) { require(allowance[src][msg.sender] >= wad); allowance[src][msg.sender] -= wad; } balanceOf[src] -= wad; balanceOf[dst] += wad; emit Transfer(src, dst, wad); return true; } } /* GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the program's name and a brief idea of what it does.> Copyright (C) <year> <name of author> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: <program> Copyright (C) <year> <name of author> This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <http://www.gnu.org/licenses/>. The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <http://www.gnu.org/philosophy/why-not-lgpl.html>. */
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IKeeperRewards} from './IKeeperRewards.sol'; import {IVaultAdmin} from './IVaultAdmin.sol'; import {IVaultVersion} from './IVaultVersion.sol'; import {IVaultFee} from './IVaultFee.sol'; import {IVaultState} from './IVaultState.sol'; import {IVaultValidators} from './IVaultValidators.sol'; import {IVaultEnterExit} from './IVaultEnterExit.sol'; import {IVaultOsToken} from './IVaultOsToken.sol'; import {IVaultMev} from './IVaultMev.sol'; import {IVaultEthStaking} from './IVaultEthStaking.sol'; import {IMulticall} from './IMulticall.sol'; /** * @title IEthVault * @author StakeWise * @notice Defines the interface for the EthVault contract */ interface IEthVault is IVaultAdmin, IVaultVersion, IVaultFee, IVaultState, IVaultValidators, IVaultEnterExit, IVaultOsToken, IVaultMev, IVaultEthStaking, IMulticall { /** * @dev Struct for initializing the EthVault contract * @param capacity The Vault stops accepting deposits after exceeding the capacity * @param feePercent The fee percent that is charged by the Vault * @param metadataIpfsHash The IPFS hash of the Vault's metadata file */ struct EthVaultInitParams { uint256 capacity; uint16 feePercent; string metadataIpfsHash; } /** * @notice Initializes or upgrades the EthVault contract. Must transfer security deposit during the deployment. * @param params The encoded parameters for initializing the EthVault contract */ function initialize(bytes calldata params) external payable; /** * @notice Deposits assets to the vault and mints OsToken shares to the receiver * @param receiver The address to receive the OsToken * @param osTokenShares The amount of OsToken shares to mint. * If set to type(uint256).max, max OsToken shares will be minted. * @param referrer The address of the referrer * @return The amount of OsToken assets minted */ function depositAndMintOsToken( address receiver, uint256 osTokenShares, address referrer ) external payable returns (uint256); /** * @notice Updates the state, deposits assets to the vault and mints OsToken shares to the receiver * @param receiver The address to receive the OsToken * @param osTokenShares The amount of OsToken shares to mint. * If set to type(uint256).max, max OsToken shares will be minted. * @param referrer The address of the referrer * @param harvestParams The parameters for the harvest * @return The amount of OsToken assets minted */ function updateStateAndDepositAndMintOsToken( address receiver, uint256 osTokenShares, address referrer, IKeeperRewards.HarvestParams calldata harvestParams ) external payable returns (uint256); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.26; /** * @title IStrategy * @author StakeWise * @notice Defines the interface for the Strategy contract */ interface IStrategy { /** * @notice Strategy Unique Identifier * @return The unique identifier of the strategy */ function strategyId() external pure returns (bytes32); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.26; /** * @title IStrategyProxy * @author StakeWise * @notice Defines the interface for the StrategyProxy contract */ interface IStrategyProxy { /** * @notice Initializes the proxy. * @param initialOwner The address of the owner */ function initialize( address initialOwner ) external; /** * @notice Executes a call on the target contract. Can only be called by the owner. * @param target The address of the target contract * @param data The call data * @return The call result */ function execute(address target, bytes memory data) external payable returns (bytes memory); /** * @notice Executes a call on the target contract with a native assets transfer. Can only be called by the owner. * @param target The address of the target contract * @param data The call data * @param value The amount of native assets to send * @return The call result */ function executeWithValue(address target, bytes memory data, uint256 value) external returns (bytes memory); /** * @notice Function for sending native assets to the recipient. Can only be called by the owner. * @param recipient The address of the recipient * @param amount The amount of native assets to send */ function sendValue(address payable recipient, uint256 amount) external; }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.26; import {IERC20Permit} from '@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol'; import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; import {Math} from '@openzeppelin/contracts/utils/math/Math.sol'; import {Clones} from '@openzeppelin/contracts/proxy/Clones.sol'; import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol'; import {Multicall} from '@stakewise-core/base/Multicall.sol'; import {Errors} from '@stakewise-core/libraries/Errors.sol'; import {IKeeperRewards} from '@stakewise-core/interfaces/IKeeperRewards.sol'; import {IVaultOsToken} from '@stakewise-core/interfaces/IVaultOsToken.sol'; import {IVaultState} from '@stakewise-core/interfaces/IVaultState.sol'; import {IOsTokenVaultEscrow} from '@stakewise-core/interfaces/IOsTokenVaultEscrow.sol'; import {IOsTokenVaultController} from '@stakewise-core/interfaces/IOsTokenVaultController.sol'; import {IOsTokenConfig} from '@stakewise-core/interfaces/IOsTokenConfig.sol'; import {IOsTokenFlashLoans} from '@stakewise-core/interfaces/IOsTokenFlashLoans.sol'; import {IOsTokenFlashLoanRecipient} from '@stakewise-core/interfaces/IOsTokenFlashLoanRecipient.sol'; import {IVaultVersion} from '@stakewise-core/interfaces/IVaultVersion.sol'; import {IBalancerVault} from './interfaces/IBalancerVault.sol'; import {ILeverageStrategy} from './interfaces/ILeverageStrategy.sol'; import {IStrategiesRegistry} from '../interfaces/IStrategiesRegistry.sol'; import {IStrategyProxy} from '../interfaces/IStrategyProxy.sol'; import {IStrategy} from '../interfaces/IStrategy.sol'; /** * @title LeverageStrategy * @author StakeWise * @notice Defines the functionality for the leverage strategy */ abstract contract LeverageStrategy is Multicall, ILeverageStrategy { uint256 private constant _wad = 1e18; uint256 private constant _vaultDisabledLiqThreshold = type(uint64).max; string internal constant _maxVaultLtvPercentConfigName = 'maxVaultLtvPercent'; string internal constant _maxBorrowLtvPercentConfigName = 'maxBorrowLtvPercent'; string internal constant _vaultForceExitLtvPercentConfigName = 'vaultForceExitLtvPercent'; string internal constant _borrowForceExitLtvPercentConfigName = 'borrowForceExitLtvPercent'; string internal constant _rescueVaultConfigName = 'rescueVault'; string internal constant _balancerPoolIdConfigName = 'balancerPoolId'; string internal constant _vaultUpgradeConfigName = 'upgradeV1'; // Strategy IStrategiesRegistry internal immutable _strategiesRegistry; address private immutable _strategyProxyImplementation; // OsToken IOsTokenVaultController internal immutable _osTokenVaultController; IOsTokenConfig internal immutable _osTokenConfig; IOsTokenFlashLoans private immutable _osTokenFlashLoans; IOsTokenVaultEscrow internal immutable _osTokenVaultEscrow; // Balancer IBalancerVault private immutable _balancerVault; // Tokens IERC20 internal immutable _osToken; IERC20 internal immutable _assetToken; mapping(address proxy => bool isExiting) public isStrategyProxyExiting; /** * @dev Constructor * @param osToken The address of the OsToken contract * @param assetToken The address of the asset token contract (e.g. WETH) * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param osTokenFlashLoans The address of the OsTokenFlashLoans contract * @param osTokenVaultEscrow The address of the OsTokenVaultEscrow contract * @param strategiesRegistry The address of the StrategiesRegistry contract * @param strategyProxyImplementation The address of the StrategyProxy implementation * @param balancerVault The address of the BalancerVault contract */ constructor( address osToken, address assetToken, address osTokenVaultController, address osTokenConfig, address osTokenFlashLoans, address osTokenVaultEscrow, address strategiesRegistry, address strategyProxyImplementation, address balancerVault ) { _osToken = IERC20(osToken); _assetToken = IERC20(assetToken); _osTokenVaultController = IOsTokenVaultController(osTokenVaultController); _osTokenConfig = IOsTokenConfig(osTokenConfig); _osTokenFlashLoans = IOsTokenFlashLoans(osTokenFlashLoans); _osTokenVaultEscrow = IOsTokenVaultEscrow(osTokenVaultEscrow); _strategiesRegistry = IStrategiesRegistry(strategiesRegistry); _strategyProxyImplementation = strategyProxyImplementation; _balancerVault = IBalancerVault(balancerVault); } /// @inheritdoc ILeverageStrategy function getStrategyProxy(address vault, address user) public view returns (address proxy) { // check whether strategy proxy exists bytes32 strategyProxyId = keccak256(abi.encode(strategyId(), vault, user)); proxy = _strategiesRegistry.strategyProxyIdToProxy(strategyProxyId); if (proxy == address(0)) { // calculate the proxy address return Clones.predictDeterministicAddress(_strategyProxyImplementation, strategyProxyId); } } /// @inheritdoc ILeverageStrategy function updateVaultState(address vault, IKeeperRewards.HarvestParams calldata harvestParams) external { IVaultState(vault).updateState(harvestParams); } /// @inheritdoc ILeverageStrategy function permit(address vault, uint256 osTokenShares, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external { (address proxy,) = _getOrCreateStrategyProxy(vault, msg.sender); try IStrategyProxy(proxy).execute( address(_osToken), abi.encodeWithSelector( IERC20Permit(address(_osToken)).permit.selector, msg.sender, proxy, osTokenShares, deadline, v, r, s ) ) {} catch {} } /// @inheritdoc ILeverageStrategy function deposit(address vault, uint256 osTokenShares) external { if (osTokenShares == 0) revert Errors.InvalidShares(); // fetch strategy proxy (address proxy,) = _getOrCreateStrategyProxy(vault, msg.sender); if (isStrategyProxyExiting[proxy]) revert Errors.ExitRequestNotProcessed(); // transfer osToken shares from user to the proxy IStrategyProxy(proxy).execute( address(_osToken), abi.encodeWithSelector(_osToken.transferFrom.selector, msg.sender, proxy, osTokenShares) ); // fetch vault state and lending protocol state (uint256 stakedAssets, uint256 mintedOsTokenShares) = _getVaultState(vault, proxy); (uint256 borrowedAssets, uint256 suppliedOsTokenShares) = _getBorrowState(proxy); // check whether any of the positions exist uint256 leverageOsTokenShares = osTokenShares; if (stakedAssets != 0 || mintedOsTokenShares != 0 || borrowedAssets != 0 || suppliedOsTokenShares != 0) { // supply osToken shares to the lending protocol _supplyOsTokenShares(proxy, osTokenShares); suppliedOsTokenShares += osTokenShares; // borrow max amount of assets from the lending protocol uint256 maxBorrowAssets = Math.mulDiv(_osTokenVaultController.convertToAssets(suppliedOsTokenShares), _getBorrowLtv(), _wad); if (borrowedAssets >= maxBorrowAssets) { // nothing to borrow emit Deposited(vault, msg.sender, osTokenShares, 0); return; } uint256 assetsToBorrow; unchecked { // cannot underflow because maxBorrowAssets > borrowedAssets assetsToBorrow = maxBorrowAssets - borrowedAssets; } _borrowAssets(proxy, assetsToBorrow); // mint max possible osToken shares leverageOsTokenShares = _mintOsTokenShares(vault, proxy, assetsToBorrow, type(uint256).max); } // calculate flash loaned osToken shares uint256 flashloanOsTokenShares = _getFlashloanOsTokenShares(vault, leverageOsTokenShares); if (flashloanOsTokenShares == 0) { // no osToken shares to leverage emit Deposited(vault, msg.sender, osTokenShares, 0); return; } // execute flashloan _osTokenFlashLoans.flashLoan(flashloanOsTokenShares, abi.encode(FlashloanAction.Deposit, vault, proxy)); // emit event emit Deposited(vault, msg.sender, osTokenShares, flashloanOsTokenShares); } /// @inheritdoc ILeverageStrategy function enterExitQueue(address vault, uint256 positionPercent) external returns (uint256 positionTicket) { return _enterExitQueue(vault, msg.sender, positionPercent); } /// @inheritdoc ILeverageStrategy function forceEnterExitQueue(address vault, address user) external returns (uint256 positionTicket) { if (!_canForceEnterExitQueue(vault, user)) revert Errors.AccessDenied(); return _enterExitQueue(vault, user, _wad); } function claimExitedAssets(address vault, address user, ExitPosition calldata exitPosition) external { // fetch strategy proxy address proxy = getStrategyProxy(vault, user); if (!isStrategyProxyExiting[proxy]) revert ExitQueueNotEntered(); // fetch exit position (address owner, uint256 exitedAssets, uint256 exitedOsTokenShares) = _osTokenVaultEscrow.getPosition(vault, exitPosition.positionTicket); if (owner != proxy) revert InvalidExitQueueTicket(); if (exitedOsTokenShares <= 1) { // osToken vault escrow position was redeemed or liquidated delete isStrategyProxyExiting[proxy]; emit ExitedAssetsClaimed(vault, user, 0, 0); return; } if (exitedAssets == 0) { // the exit assets are not processed _osTokenVaultEscrow.processExitedAssets( vault, exitPosition.positionTicket, exitPosition.timestamp, exitPosition.exitQueueIndex ); } // flashloan the exited osToken shares _osTokenFlashLoans.flashLoan( exitedOsTokenShares, abi.encode(FlashloanAction.ClaimExitedAssets, vault, proxy, exitPosition.positionTicket) ); // withdraw left assets to the user (uint256 claimedOsTokenShares, uint256 claimedAssets) = _claimProxyAssets(proxy, user); // update state delete isStrategyProxyExiting[proxy]; // emit event emit ExitedAssetsClaimed(vault, user, claimedOsTokenShares, claimedAssets); } /// @inheritdoc ILeverageStrategy function rescueVaultAssets(address vault, ExitPosition calldata exitPosition) external { address proxy = getStrategyProxy(vault, msg.sender); if (!isStrategyProxyExiting[proxy]) revert ExitQueueNotEntered(); // fetch exit position (address owner, uint256 exitedAssets, uint256 exitedOsTokenShares) = _osTokenVaultEscrow.getPosition(vault, exitPosition.positionTicket); if (owner != proxy) revert InvalidExitQueueTicket(); if (exitedOsTokenShares <= 1) { // osToken vault escrow position was redeemed or liquidated delete isStrategyProxyExiting[proxy]; emit VaultAssetsRescued(vault, msg.sender, 0, 0); return; } if (exitedAssets == 0) { // the exit assets are not processed _osTokenVaultEscrow.processExitedAssets( vault, exitPosition.positionTicket, exitPosition.timestamp, exitPosition.exitQueueIndex ); } // flashloan the exited osToken shares _osTokenFlashLoans.flashLoan( exitedOsTokenShares, abi.encode(FlashloanAction.RescueVaultAssets, vault, proxy, exitPosition.positionTicket) ); // update state delete isStrategyProxyExiting[proxy]; // withdraw left assets to the user (uint256 claimedOsTokenShares, uint256 claimedAssets) = _claimProxyAssets(proxy, msg.sender); // emit event emit VaultAssetsRescued(vault, msg.sender, claimedOsTokenShares, claimedAssets); } /// @inheritdoc ILeverageStrategy function rescueLendingAssets(address vault, uint256 assets, uint256 maxSlippagePercent) external { if (maxSlippagePercent >= _wad) revert InvalidMaxSlippagePercent(); // fetch borrowed assets address proxy = getStrategyProxy(vault, msg.sender); (uint256 borrowedAssets,) = _getBorrowState(proxy); if (assets == 0 || assets > borrowedAssets) revert Errors.InvalidAssets(); // calculate osToken shares to flashloan uint256 osTokenShares = _osTokenVaultController.convertToShares(assets); // apply max slippage percent osTokenShares += Math.mulDiv(osTokenShares, maxSlippagePercent, _wad); // flashloan the osToken shares _osTokenFlashLoans.flashLoan(osTokenShares, abi.encode(FlashloanAction.RescueLendingAssets, proxy, assets)); // withdraw left assets to the user (uint256 claimedOsTokenShares, uint256 claimedAssets) = _claimProxyAssets(proxy, msg.sender); // emit event emit LendingAssetsRescued(vault, msg.sender, claimedOsTokenShares, claimedAssets); } /// @inheritdoc IOsTokenFlashLoanRecipient function receiveFlashLoan(uint256 osTokenShares, bytes memory userData) external { // validate sender if (msg.sender != address(_osTokenFlashLoans)) { revert Errors.AccessDenied(); } // decode userData action (FlashloanAction flashloanType) = abi.decode(userData, (FlashloanAction)); if (flashloanType == FlashloanAction.Deposit) { // process deposit flashloan (, address vault, address proxy) = abi.decode(userData, (FlashloanAction, address, address)); _processDepositFlashloan(vault, proxy, osTokenShares); } else if (flashloanType == FlashloanAction.ClaimExitedAssets) { // process claim exited assets flashloan (, address vault, address proxy, uint256 exitPositionTicket) = abi.decode(userData, (FlashloanAction, address, address, uint256)); _processClaimFlashloan(vault, proxy, exitPositionTicket, osTokenShares); } else if (flashloanType == FlashloanAction.RescueVaultAssets) { // process vault assets rescue flashloan (, address vault, address proxy, uint256 exitPositionTicket) = abi.decode(userData, (FlashloanAction, address, address, uint256)); _processVaultAssetsRescueFlashloan(vault, proxy, exitPositionTicket, osTokenShares); } else if (flashloanType == FlashloanAction.RescueLendingAssets) { // process lending assets rescue flashloan (, address proxy, uint256 assets) = abi.decode(userData, (FlashloanAction, address, uint256)); _processLendingAssetsRescueFlashloan(proxy, assets, osTokenShares); } else { revert InvalidFlashloanAction(); } } /// @inheritdoc ILeverageStrategy function upgradeProxy( address vault ) external { // fetch strategy proxy address proxy = getStrategyProxy(vault, msg.sender); if (isStrategyProxyExiting[proxy]) revert Errors.ExitRequestNotProcessed(); if (!_strategiesRegistry.strategyProxies(proxy)) revert Errors.AccessDenied(); // check whether there is a new version for the current strategy bytes memory vaultUpgradeConfig = _strategiesRegistry.getStrategyConfig(strategyId(), _vaultUpgradeConfigName); if (vaultUpgradeConfig.length == 0) { revert Errors.UpgradeFailed(); } // decode and check new strategy address address newStrategy = abi.decode(vaultUpgradeConfig, (address)); if (newStrategy == address(0) || newStrategy == address(this)) { revert Errors.ValueNotChanged(); } // migrate strategy Ownable(proxy).transferOwnership(newStrategy); emit StrategyProxyUpgraded(vault, msg.sender, newStrategy); } /** * @dev Enters the exit queue for the strategy proxy * @param vault The address of the vault * @param user The address of the user * @param positionPercent The percentage of the position to exit * @return positionTicket The exit position ticket */ function _enterExitQueue( address vault, address user, uint256 positionPercent ) private returns (uint256 positionTicket) { if (positionPercent == 0 || positionPercent > _wad) { revert InvalidExitQueuePercent(); } // fetch strategy proxy address proxy = getStrategyProxy(vault, user); if (isStrategyProxyExiting[proxy]) revert Errors.ExitRequestNotProcessed(); // calculate the minted OsToken shares to transfer to the escrow (, uint256 mintedOsTokenShares) = _getVaultState(vault, proxy); uint256 osTokenShares = Math.mulDiv(mintedOsTokenShares, positionPercent, _wad); if (osTokenShares == 0) revert Errors.InvalidPosition(); // initiate exit for assets bytes memory response = IStrategyProxy(proxy).execute( vault, abi.encodeWithSelector(IVaultOsToken(vault).transferOsTokenPositionToEscrow.selector, osTokenShares) ); positionTicket = abi.decode(response, (uint256)); // update state isStrategyProxyExiting[proxy] = true; // emit event emit ExitQueueEntered(vault, user, positionTicket, block.timestamp, osTokenShares, positionPercent); } /** * @dev Calculates the amount of osToken shares to flashloan * @param vault The address of the vault * @param osTokenShares The amount of osToken shares at hand * @return The amount of osToken shares to flashloan */ function _getFlashloanOsTokenShares(address vault, uint256 osTokenShares) private view returns (uint256) { // fetch deposit and borrow LTVs uint256 vaultLtv = _getVaultLtv(vault); uint256 borrowLtv = _getBorrowLtv(); // calculate the amount of osToken shares that can be leveraged uint256 totalLtv = Math.mulDiv(vaultLtv, borrowLtv, _wad); return Math.mulDiv(osTokenShares, _wad, _wad - totalLtv) - osTokenShares; } /** * @dev Processes the deposit flashloan * @param vault The address of the vault * @param proxy The address of the strategy proxy * @param flashloanOsTokenShares The amount of flashloan osToken shares */ function _processDepositFlashloan(address vault, address proxy, uint256 flashloanOsTokenShares) private { // transfer flashloan to proxy SafeERC20.safeTransfer(_osToken, proxy, flashloanOsTokenShares); // supply all osToken shares to the lending protocol _supplyOsTokenShares(proxy, _osToken.balanceOf(proxy)); // calculate assets to borrow uint256 borrowAssets = Math.mulDiv(_osTokenVaultController.convertToAssets(flashloanOsTokenShares), _wad, _getVaultLtv(vault)); borrowAssets += 2; // add 2 wei to avoid rounding errors // borrow assets from the lending protocol _borrowAssets(proxy, borrowAssets); // mint osToken shares _mintOsTokenShares(vault, proxy, borrowAssets, flashloanOsTokenShares); // transfer flashloan osToken shares to the osTokenFlashLoans contract IStrategyProxy(proxy).execute( address(_osToken), abi.encodeWithSelector(_osToken.transfer.selector, address(_osTokenFlashLoans), flashloanOsTokenShares) ); } /** * @dev Processes the exited assets claim flashloan * @param vault The address of the vault * @param proxy The address of the strategy proxy * @param exitPositionTicket The exit position ticket * @param flashloanOsTokenShares The amount of flashloan osToken shares */ function _processClaimFlashloan( address vault, address proxy, uint256 exitPositionTicket, uint256 flashloanOsTokenShares ) private { // transfer flashloan to proxy SafeERC20.safeTransfer(_osToken, proxy, flashloanOsTokenShares); // claim exited assets uint256 claimedAssets = _claimOsTokenVaultEscrowAssets(vault, proxy, exitPositionTicket, flashloanOsTokenShares); // repay borrowed assets (uint256 borrowedAssets, uint256 suppliedOsTokenShares) = _getBorrowState(proxy); uint256 repayAssets = Math.min(borrowedAssets, claimedAssets); _repayAssets(proxy, repayAssets); unchecked { // cannot underflow because repayAssets <= borrowedAssets borrowedAssets -= repayAssets; } // deduct reserved osToken shares from the supplied osToken shares if (borrowedAssets != 0) { suppliedOsTokenShares -= _osTokenVaultController.convertToShares(Math.mulDiv(borrowedAssets, _wad, _getBorrowLtv())); } // withdraw osToken shares _withdrawOsTokenShares(proxy, suppliedOsTokenShares); // transfer flashloan osToken shares to the osTokenFlashLoans contract IStrategyProxy(proxy).execute( address(_osToken), abi.encodeWithSelector(_osToken.transfer.selector, address(_osTokenFlashLoans), flashloanOsTokenShares) ); } /** * @dev Processes the vault assets rescue flashloan * @param vault The address of the vault * @param proxy The address of the strategy proxy * @param exitPositionTicket The exit position ticket * @param flashloanOsTokenShares The amount of flashloan osToken shares */ function _processVaultAssetsRescueFlashloan( address vault, address proxy, uint256 exitPositionTicket, uint256 flashloanOsTokenShares ) private { // transfer flashloan to proxy SafeERC20.safeTransfer(_osToken, proxy, flashloanOsTokenShares); // claim exited assets uint256 claimedAssets = _claimOsTokenVaultEscrowAssets(vault, proxy, exitPositionTicket, flashloanOsTokenShares); // fetch vault with higher LTV than user's vault and proxy addresses bytes memory rescueVaultConfig = _strategiesRegistry.getStrategyConfig(strategyId(), _rescueVaultConfigName); if (rescueVaultConfig.length == 0) revert Errors.InvalidVault(); address rescueVault = abi.decode(rescueVaultConfig, (address)); (address rescueProxy,) = _getOrCreateStrategyProxy(rescueVault, address(1)); // mint osToken shares to rescue proxy IStrategyProxy(proxy).execute( address(_assetToken), abi.encodeWithSelector(_assetToken.transfer.selector, rescueProxy, claimedAssets) ); uint256 totalOsTokenShares = _mintOsTokenShares(rescueVault, rescueProxy, claimedAssets, type(uint256).max); // transfer flashloan osToken shares to the osTokenFlashLoans contract IStrategyProxy(rescueProxy).execute( address(_osToken), abi.encodeWithSelector(_osToken.transfer.selector, address(_osTokenFlashLoans), flashloanOsTokenShares) ); // transfer left osToken shares to user's proxy IStrategyProxy(rescueProxy).execute( address(_osToken), abi.encodeWithSelector(_osToken.transfer.selector, proxy, totalOsTokenShares - flashloanOsTokenShares) ); } /** * @dev Processes the lending assets rescue flashloan * @param proxy The address of the strategy proxy * @param repayAssets The amount of borrowed assets to repay * @param flashloanOsTokenShares The amount of flashloan osToken shares */ function _processLendingAssetsRescueFlashloan( address proxy, uint256 repayAssets, uint256 flashloanOsTokenShares ) private { // transfer flashloan to proxy SafeERC20.safeTransfer(_osToken, proxy, flashloanOsTokenShares); // fetch Balancer pool ID to execute swap bytes memory balancerPoolIdConfig = _strategiesRegistry.getStrategyConfig(strategyId(), _balancerPoolIdConfigName); if (balancerPoolIdConfig.length == 0) revert InvalidBalancerPoolId(); bytes32 balancerPoolId = abi.decode(balancerPoolIdConfig, (bytes32)); // define balancer swap IBalancerVault.SingleSwap memory singleSwap = IBalancerVault.SingleSwap({ poolId: balancerPoolId, kind: IBalancerVault.SwapKind.GIVEN_OUT, assetIn: address(_osToken), assetOut: address(_assetToken), amount: repayAssets, userData: '' }); // define balancer funds IBalancerVault.FundManagement memory funds = IBalancerVault.FundManagement({ sender: proxy, fromInternalBalance: false, recipient: payable(proxy), toInternalBalance: false }); // swap osToken shares to assets IStrategyProxy(proxy).execute( address(_osToken), abi.encodeWithSelector(_osToken.approve.selector, address(_balancerVault), flashloanOsTokenShares) ); IStrategyProxy(proxy).execute( address(_balancerVault), abi.encodeWithSelector( _balancerVault.swap.selector, singleSwap, funds, flashloanOsTokenShares, block.timestamp ) ); // repay borrowed assets _repayAssets(proxy, repayAssets); // calculate osToken shares to withdraw (uint256 borrowedAssets, uint256 suppliedOsTokenShares) = _getBorrowState(proxy); if (borrowedAssets != 0) { suppliedOsTokenShares -= _osTokenVaultController.convertToShares(Math.mulDiv(borrowedAssets, _wad, _getBorrowLtv())); } // withdraw osToken shares _withdrawOsTokenShares(proxy, suppliedOsTokenShares); // transfer flashloan osToken shares to the osTokenFlashLoans contract IStrategyProxy(proxy).execute( address(_osToken), abi.encodeWithSelector(_osToken.transfer.selector, address(_osTokenFlashLoans), flashloanOsTokenShares) ); } /** * @dev Returns the vault LTV. * @param vault The address of the vault * @return The vault LTV */ function _getVaultLtv( address vault ) internal view returns (uint256) { uint256 vaultLtvPercent = _osTokenConfig.getConfig(vault).ltvPercent; // check whether there is max vault LTV percent set in the strategy config bytes memory vaultMaxLtvPercentConfig = _strategiesRegistry.getStrategyConfig(strategyId(), _maxVaultLtvPercentConfigName); if (vaultMaxLtvPercentConfig.length == 0) { return vaultLtvPercent; } return Math.min(vaultLtvPercent, abi.decode(vaultMaxLtvPercentConfig, (uint256))); } /** * @dev Returns the vault state * @param vault The address of the vault * @param proxy The address of the strategy proxy * @return stakedAssets The amount of staked assets * @return mintedOsTokenShares The amount of minted osToken shares */ function _getVaultState( address vault, address proxy ) internal view returns (uint256 stakedAssets, uint256 mintedOsTokenShares) { // check harvested if (IVaultState(vault).isStateUpdateRequired()) { revert Errors.NotHarvested(); } // fetch staked assets uint256 stakedShares = IVaultState(vault).getShares(proxy); if (stakedShares != 0) { stakedAssets = IVaultState(vault).convertToAssets(stakedShares); } // fetch minted osToken shares mintedOsTokenShares = IVaultOsToken(vault).osTokenPositions(proxy); } /** * @dev Returns the strategy proxy or creates a new one * @param vault The address of the vault * @param user The address of the user * @return proxy The address of the strategy proxy * @return isCreated Whether the proxy was created */ function _getOrCreateStrategyProxy( address vault, address user ) internal virtual returns (address proxy, bool isCreated) { proxy = getStrategyProxy(vault, user); if (_strategiesRegistry.strategyProxies(proxy)) { // already registered return (proxy, false); } // check vault and user addresses if (user == address(0)) revert Errors.ZeroAddress(); if (vault == address(0) || IVaultVersion(vault).version() < 3) { revert Errors.InvalidVault(); } // create proxy bytes32 strategyProxyId = keccak256(abi.encode(strategyId(), vault, user)); proxy = Clones.cloneDeterministic(_strategyProxyImplementation, strategyProxyId); isCreated = true; IStrategyProxy(proxy).initialize(address(this)); _strategiesRegistry.addStrategyProxy(strategyProxyId, proxy); emit StrategyProxyCreated(strategyProxyId, vault, user, proxy); } /** * @dev Claims the exited assets from the OsToken vault escrow * @param vault The address of the vault * @param proxy The address of the strategy proxy * @param positionTicket The exit position ticket * @param osTokenShares The amount of osToken shares to claim * @return claimedAssets The amount of claimed assets */ function _claimOsTokenVaultEscrowAssets( address vault, address proxy, uint256 positionTicket, uint256 osTokenShares ) internal virtual returns (uint256 claimedAssets) { bytes memory response = IStrategyProxy(proxy).execute( address(_osTokenVaultEscrow), abi.encodeWithSelector(IOsTokenVaultEscrow.claimExitedAssets.selector, vault, positionTicket, osTokenShares) ); return abi.decode(response, (uint256)); } /** * @dev Claims assets and osToken shares from the proxy to the user * @param proxy The address of the strategy proxy * @param user The address of the user that receives the assets * @return claimedOsTokenShares The amount of claimed osToken shares * @return claimedAssets The amount of claimed assets */ function _claimProxyAssets( address proxy, address user ) private returns (uint256 claimedOsTokenShares, uint256 claimedAssets) { // withdraw left osToken shares to the user claimedOsTokenShares = _osToken.balanceOf(proxy); if (claimedOsTokenShares > 0) { IStrategyProxy(proxy).execute( address(_osToken), abi.encodeWithSelector(_osToken.transfer.selector, user, claimedOsTokenShares) ); } // withdraw left assets to the user claimedAssets = _assetToken.balanceOf(proxy); if (claimedAssets > 0) { _transferAssets(proxy, user, claimedAssets); } } /** * @dev Checks whether the user can be forced to the exit queue * @param vault The address of the vault * @param user The address of the user * @return True if the user can be forced to the exit queue, otherwise false */ function _canForceEnterExitQueue(address vault, address user) private view returns (bool) { address proxy = getStrategyProxy(vault, user); bytes32 _strategyId = strategyId(); // check whether force exit vault LTV is set in the strategy config bytes memory vaultForceExitLtvPercentConfig = _strategiesRegistry.getStrategyConfig(_strategyId, _vaultForceExitLtvPercentConfigName); if ( vaultForceExitLtvPercentConfig.length != 0 && _osTokenConfig.getConfig(vault).liqThresholdPercent != _vaultDisabledLiqThreshold ) { (uint256 stakedAssets, uint256 mintedOsTokenShares) = _getVaultState(vault, proxy); uint256 mintedOsTokenAssets = _osTokenVaultController.convertToAssets(mintedOsTokenShares); uint256 vaultForceExitLtvPercent = abi.decode(vaultForceExitLtvPercentConfig, (uint256)); // check whether approaching vault liquidation if (Math.mulDiv(stakedAssets, vaultForceExitLtvPercent, _wad) <= mintedOsTokenAssets) { return true; } } // check whether force exit borrow LTV is set in the strategy config bytes memory borrowForceExitLtvPercentConfig = _strategiesRegistry.getStrategyConfig(_strategyId, _borrowForceExitLtvPercentConfigName); if (borrowForceExitLtvPercentConfig.length != 0) { (uint256 borrowedAssets, uint256 suppliedOsTokenShares) = _getBorrowState(proxy); uint256 suppliedOsTokenAssets = _osTokenVaultController.convertToAssets(suppliedOsTokenShares); uint256 borrowForceExitLtvPercent = abi.decode(borrowForceExitLtvPercentConfig, (uint256)); // check whether approaching borrow liquidation if (Math.mulDiv(suppliedOsTokenAssets, borrowForceExitLtvPercent, _wad) <= borrowedAssets) { return true; } } return false; } /// @inheritdoc IStrategy function strategyId() public pure virtual returns (bytes32); /** * @dev Deposits assets to the vault and mints osToken shares * @param vault The address of the vault * @param proxy The address of the strategy proxy * @param depositAssets The amount of assets to deposit * @param mintOsTokenShares The amount of osToken shares to mint * @return The amount of osToken shares minted */ function _mintOsTokenShares( address vault, address proxy, uint256 depositAssets, uint256 mintOsTokenShares ) internal virtual returns (uint256); /** * @dev Returns the borrow LTV. * @return The borrow LTV */ function _getBorrowLtv() internal view virtual returns (uint256); /** * @dev Returns the borrow position state * @param proxy The address of the strategy proxy * @return borrowedAssets The amount of borrowed assets * @return suppliedOsTokenShares The amount of supplied osToken shares */ function _getBorrowState( address proxy ) internal view virtual returns (uint256 borrowedAssets, uint256 suppliedOsTokenShares); /** * @dev Locks OsToken shares to the lending protocol * @param proxy The address of the strategy proxy * @param osTokenShares The amount of OsToken shares to lock */ function _supplyOsTokenShares(address proxy, uint256 osTokenShares) internal virtual; /** * @dev Withdraws OsToken shares from the lending protocol * @param proxy The address of the strategy proxy * @param osTokenShares The amount of OsToken shares to withdraw */ function _withdrawOsTokenShares(address proxy, uint256 osTokenShares) internal virtual; /** * @dev Borrows the assets from the lending protocol * @param proxy The address of the strategy proxy * @param amount The amount of assets borrowed */ function _borrowAssets(address proxy, uint256 amount) internal virtual; /** * @dev Repays the assets from the lending protocol * @param proxy The address of the strategy proxy * @param amount The amount of assets to repay */ function _repayAssets(address proxy, uint256 amount) internal virtual; /** * @dev Transfers assets from the proxy to the receiver * @param proxy The address of the strategy proxy * @param receiver The address of the receiver * @param amount The amount of assets to transfer */ function _transferAssets(address proxy, address receiver, uint256 amount) internal virtual; }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.26; import {Math} from '@openzeppelin/contracts/utils/math/Math.sol'; import {SafeCast} from '@openzeppelin/contracts/utils/math/SafeCast.sol'; import {IPool} from '@aave-core/interfaces/IPool.sol'; import {IScaledBalanceToken} from '@aave-core/interfaces/IScaledBalanceToken.sol'; import {WadRayMath} from '@aave-core/protocol/libraries/math/WadRayMath.sol'; import {IStrategyProxy} from '../interfaces/IStrategyProxy.sol'; import {LeverageStrategy} from './LeverageStrategy.sol'; /** * @title AaveLeverageStrategy * @author StakeWise * @notice Defines the Aave leverage strategy functionality */ abstract contract AaveLeverageStrategy is LeverageStrategy { uint8 private constant _emodeCategory = 1; IPool private immutable _aavePool; IScaledBalanceToken private immutable _aaveOsToken; IScaledBalanceToken private immutable _aaveVarDebtAssetToken; /** * @dev Constructor * @param osToken The address of the OsToken contract * @param assetToken The address of the asset token contract (e.g. WETH) * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param osTokenFlashLoans The address of the OsTokenFlashLoans contract * @param osTokenVaultEscrow The address of the OsTokenVaultEscrow contract * @param strategiesRegistry The address of the StrategiesRegistry contract * @param strategyProxyImplementation The address of the StrategyProxy implementation * @param balancerVault The address of the BalancerVault contract * @param aavePool The address of the Aave pool contract * @param aaveOsToken The address of the Aave OsToken contract * @param aaveVarDebtAssetToken The address of the Aave variable debt asset token contract */ constructor( address osToken, address assetToken, address osTokenVaultController, address osTokenConfig, address osTokenFlashLoans, address osTokenVaultEscrow, address strategiesRegistry, address strategyProxyImplementation, address balancerVault, address aavePool, address aaveOsToken, address aaveVarDebtAssetToken ) LeverageStrategy( osToken, assetToken, osTokenVaultController, osTokenConfig, osTokenFlashLoans, osTokenVaultEscrow, strategiesRegistry, strategyProxyImplementation, balancerVault ) { _aavePool = IPool(aavePool); _aaveOsToken = IScaledBalanceToken(aaveOsToken); _aaveVarDebtAssetToken = IScaledBalanceToken(aaveVarDebtAssetToken); } /// @inheritdoc LeverageStrategy function _getBorrowLtv() internal view override returns (uint256) { // convert to 1e18 precision uint256 aaveLtv = uint256(_aavePool.getEModeCategoryCollateralConfig(_emodeCategory).ltv) * 1e14; // check whether there is max borrow LTV percent set in the strategy config bytes memory maxBorrowLtvPercentConfig = _strategiesRegistry.getStrategyConfig(strategyId(), _maxBorrowLtvPercentConfigName); if (maxBorrowLtvPercentConfig.length == 0) { return aaveLtv; } return Math.min(aaveLtv, abi.decode(maxBorrowLtvPercentConfig, (uint256))); } /// @inheritdoc LeverageStrategy function _getBorrowState( address proxy ) internal view override returns (uint256 borrowedAssets, uint256 suppliedOsTokenShares) { suppliedOsTokenShares = _aaveOsToken.scaledBalanceOf(proxy); if (suppliedOsTokenShares != 0) { uint256 normalizedIncome = _aavePool.getReserveNormalizedIncome(address(_osToken)); suppliedOsTokenShares = WadRayMath.rayMul(suppliedOsTokenShares, normalizedIncome); } borrowedAssets = _aaveVarDebtAssetToken.scaledBalanceOf(proxy); if (borrowedAssets != 0) { uint256 normalizedDebt = _aavePool.getReserveNormalizedVariableDebt(address(_assetToken)); borrowedAssets = WadRayMath.rayMul(borrowedAssets, normalizedDebt); } } /// @inheritdoc LeverageStrategy function _supplyOsTokenShares(address proxy, uint256 osTokenShares) internal override { IStrategyProxy(proxy).execute( address(_aavePool), abi.encodeWithSelector(_aavePool.supply.selector, address(_osToken), osTokenShares, proxy, 0) ); } /// @inheritdoc LeverageStrategy function _withdrawOsTokenShares(address proxy, uint256 osTokenShares) internal override { IStrategyProxy(proxy).execute( address(_aavePool), abi.encodeWithSelector(_aavePool.withdraw.selector, address(_osToken), osTokenShares, proxy) ); } /// @inheritdoc LeverageStrategy function _borrowAssets(address proxy, uint256 amount) internal override { IStrategyProxy(proxy).execute( address(_aavePool), abi.encodeWithSelector(_aavePool.borrow.selector, address(_assetToken), amount, 2, 0, proxy) ); } /// @inheritdoc LeverageStrategy function _repayAssets(address proxy, uint256 amount) internal override { IStrategyProxy(proxy).execute( address(_aavePool), abi.encodeWithSelector(_aavePool.repay.selector, address(_assetToken), amount, 2, proxy) ); } /// @inheritdoc LeverageStrategy function _getOrCreateStrategyProxy( address vault, address user ) internal virtual override returns (address proxy, bool isCreated) { (proxy, isCreated) = super._getOrCreateStrategyProxy(vault, user); if (!isCreated) { return (proxy, isCreated); } // setup emode category IStrategyProxy(proxy).execute( address(_aavePool), abi.encodeWithSelector(_aavePool.setUserEMode.selector, _emodeCategory) ); // approve Aave pool to spend OsToken and AssetToken IStrategyProxy(proxy).execute( address(_osToken), abi.encodeWithSelector(_osToken.approve.selector, address(_aavePool), type(uint256).max) ); IStrategyProxy(proxy).execute( address(_assetToken), abi.encodeWithSelector(_assetToken.approve.selector, address(_aavePool), type(uint256).max) ); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IKeeperOracles} from './IKeeperOracles.sol'; /** * @title IKeeperRewards * @author StakeWise * @notice Defines the interface for the Keeper contract rewards */ interface IKeeperRewards is IKeeperOracles { /** * @notice Event emitted on rewards update * @param caller The address of the function caller * @param rewardsRoot The new rewards merkle tree root * @param avgRewardPerSecond The new average reward per second * @param updateTimestamp The update timestamp used for rewards calculation * @param nonce The nonce used for verifying signatures * @param rewardsIpfsHash The new rewards IPFS hash */ event RewardsUpdated( address indexed caller, bytes32 indexed rewardsRoot, uint256 avgRewardPerSecond, uint64 updateTimestamp, uint64 nonce, string rewardsIpfsHash ); /** * @notice Event emitted on Vault harvest * @param vault The address of the Vault * @param rewardsRoot The rewards merkle tree root * @param totalAssetsDelta The Vault total assets delta since last sync. Can be negative in case of penalty/slashing. * @param unlockedMevDelta The Vault execution reward that can be withdrawn from shared MEV escrow. Only used by shared MEV Vaults. */ event Harvested( address indexed vault, bytes32 indexed rewardsRoot, int256 totalAssetsDelta, uint256 unlockedMevDelta ); /** * @notice Event emitted on rewards min oracles number update * @param oracles The new minimum number of oracles required to update rewards */ event RewardsMinOraclesUpdated(uint256 oracles); /** * @notice A struct containing the last synced Vault's cumulative reward * @param assets The Vault cumulative reward earned since the start. Can be negative in case of penalty/slashing. * @param nonce The nonce of the last sync */ struct Reward { int192 assets; uint64 nonce; } /** * @notice A struct containing the last unlocked Vault's cumulative execution reward that can be withdrawn from shared MEV escrow. Only used by shared MEV Vaults. * @param assets The shared MEV Vault's cumulative execution reward that can be withdrawn * @param nonce The nonce of the last sync */ struct UnlockedMevReward { uint192 assets; uint64 nonce; } /** * @notice A struct containing parameters for rewards update * @param rewardsRoot The new rewards merkle root * @param avgRewardPerSecond The new average reward per second * @param updateTimestamp The update timestamp used for rewards calculation * @param rewardsIpfsHash The new IPFS hash with all the Vaults' rewards for the new root * @param signatures The concatenation of the Oracles' signatures */ struct RewardsUpdateParams { bytes32 rewardsRoot; uint256 avgRewardPerSecond; uint64 updateTimestamp; string rewardsIpfsHash; bytes signatures; } /** * @notice A struct containing parameters for harvesting rewards. Can only be called by Vault. * @param rewardsRoot The rewards merkle root * @param reward The Vault cumulative reward earned since the start. Can be negative in case of penalty/slashing. * @param unlockedMevReward The Vault cumulative execution reward that can be withdrawn from shared MEV escrow. Only used by shared MEV Vaults. * @param proof The proof to verify that Vault's reward is correct */ struct HarvestParams { bytes32 rewardsRoot; int160 reward; uint160 unlockedMevReward; bytes32[] proof; } /** * @notice Previous Rewards Root * @return The previous merkle tree root of the rewards accumulated by the Vaults */ function prevRewardsRoot() external view returns (bytes32); /** * @notice Rewards Root * @return The latest merkle tree root of the rewards accumulated by the Vaults */ function rewardsRoot() external view returns (bytes32); /** * @notice Rewards Nonce * @return The nonce used for updating rewards merkle tree root */ function rewardsNonce() external view returns (uint64); /** * @notice The last rewards update * @return The timestamp of the last rewards update */ function lastRewardsTimestamp() external view returns (uint64); /** * @notice The minimum number of oracles required to update rewards * @return The minimum number of oracles */ function rewardsMinOracles() external view returns (uint256); /** * @notice The rewards delay * @return The delay in seconds between rewards updates */ function rewardsDelay() external view returns (uint256); /** * @notice Get last synced Vault cumulative reward * @param vault The address of the Vault * @return assets The last synced reward assets * @return nonce The last synced reward nonce */ function rewards(address vault) external view returns (int192 assets, uint64 nonce); /** * @notice Get last unlocked shared MEV Vault cumulative reward * @param vault The address of the Vault * @return assets The last synced reward assets * @return nonce The last synced reward nonce */ function unlockedMevRewards(address vault) external view returns (uint192 assets, uint64 nonce); /** * @notice Checks whether Vault must be harvested * @param vault The address of the Vault * @return `true` if the Vault requires harvesting, `false` otherwise */ function isHarvestRequired(address vault) external view returns (bool); /** * @notice Checks whether the Vault can be harvested * @param vault The address of the Vault * @return `true` if Vault can be harvested, `false` otherwise */ function canHarvest(address vault) external view returns (bool); /** * @notice Checks whether rewards can be updated * @return `true` if rewards can be updated, `false` otherwise */ function canUpdateRewards() external view returns (bool); /** * @notice Checks whether the Vault has registered validators * @param vault The address of the Vault * @return `true` if Vault is collateralized, `false` otherwise */ function isCollateralized(address vault) external view returns (bool); /** * @notice Update rewards data * @param params The struct containing rewards update parameters */ function updateRewards(RewardsUpdateParams calldata params) external; /** * @notice Harvest rewards. Can be called only by Vault. * @param params The struct containing rewards harvesting parameters * @return totalAssetsDelta The total reward/penalty accumulated by the Vault since the last sync * @return unlockedMevDelta The Vault execution reward that can be withdrawn from shared MEV escrow. Only used by shared MEV Vaults. * @return harvested `true` when the rewards were harvested, `false` otherwise */ function harvest( HarvestParams calldata params ) external returns (int256 totalAssetsDelta, uint256 unlockedMevDelta, bool harvested); /** * @notice Set min number of oracles for confirming rewards update. Can only be called by the owner. * @param _rewardsMinOracles The new min number of oracles for confirming rewards update */ function setRewardsMinOracles(uint256 _rewardsMinOracles) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; /** * @title IVaultState * @author StakeWise * @notice Defines the interface for the VaultAdmin contract */ interface IVaultAdmin { /** * @notice Event emitted on metadata ipfs hash update * @param caller The address of the function caller * @param metadataIpfsHash The new metadata IPFS hash */ event MetadataUpdated(address indexed caller, string metadataIpfsHash); /** * @notice The Vault admin * @return The address of the Vault admin */ function admin() external view returns (address); /** * @notice Function for updating the metadata IPFS hash. Can only be called by Vault admin. * @param metadataIpfsHash The new metadata IPFS hash */ function setMetadata(string calldata metadataIpfsHash) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IERC1822Proxiable} from '@openzeppelin/contracts/interfaces/draft-IERC1822.sol'; import {IVaultAdmin} from './IVaultAdmin.sol'; /** * @title IVaultVersion * @author StakeWise * @notice Defines the interface for VaultVersion contract */ interface IVaultVersion is IERC1822Proxiable, IVaultAdmin { /** * @notice Vault Unique Identifier * @return The unique identifier of the Vault */ function vaultId() external pure returns (bytes32); /** * @notice Version * @return The version of the Vault implementation contract */ function version() external pure returns (uint8); /** * @notice Implementation * @return The address of the Vault implementation contract */ function implementation() external view returns (address); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IVaultAdmin} from './IVaultAdmin.sol'; /** * @title IVaultFee * @author StakeWise * @notice Defines the interface for the VaultFee contract */ interface IVaultFee is IVaultAdmin { /** * @notice Event emitted on fee recipient update * @param caller The address of the function caller * @param feeRecipient The address of the new fee recipient */ event FeeRecipientUpdated(address indexed caller, address indexed feeRecipient); /** * @notice The Vault's fee recipient * @return The address of the Vault's fee recipient */ function feeRecipient() external view returns (address); /** * @notice The Vault's fee percent in BPS * @return The fee percent applied by the Vault on the rewards */ function feePercent() external view returns (uint16); /** * @notice Function for updating the fee recipient address. Can only be called by the admin. * @param _feeRecipient The address of the new fee recipient */ function setFeeRecipient(address _feeRecipient) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IKeeperRewards} from './IKeeperRewards.sol'; import {IVaultFee} from './IVaultFee.sol'; /** * @title IVaultState * @author StakeWise * @notice Defines the interface for the VaultState contract */ interface IVaultState is IVaultFee { /** * @notice Event emitted on checkpoint creation * @param shares The number of burned shares * @param assets The amount of exited assets */ event CheckpointCreated(uint256 shares, uint256 assets); /** * @notice Event emitted on minting fee recipient shares * @param receiver The address of the fee recipient * @param shares The number of minted shares * @param assets The amount of minted assets */ event FeeSharesMinted(address receiver, uint256 shares, uint256 assets); /** * @notice Event emitted when exiting assets are penalized * @param penalty The total penalty amount */ event ExitingAssetsPenalized(uint256 penalty); /** * @notice Total assets in the Vault * @return The total amount of the underlying asset that is "managed" by Vault */ function totalAssets() external view returns (uint256); /** * @notice Function for retrieving total shares * @return The amount of shares in existence */ function totalShares() external view returns (uint256); /** * @notice The Vault's capacity * @return The amount after which the Vault stops accepting deposits */ function capacity() external view returns (uint256); /** * @notice Total assets available in the Vault. They can be staked or withdrawn. * @return The total amount of withdrawable assets */ function withdrawableAssets() external view returns (uint256); /** * @notice Queued Shares * @return The total number of shares queued for exit */ function queuedShares() external view returns (uint128); /** * @notice Returns the number of shares held by an account * @param account The account for which to look up the number of shares it has, i.e. its balance * @return The number of shares held by the account */ function getShares(address account) external view returns (uint256); /** * @notice Converts assets to shares * @param assets The amount of assets to convert to shares * @return shares The amount of shares that the Vault would exchange for the amount of assets provided */ function convertToShares(uint256 assets) external view returns (uint256 shares); /** * @notice Converts shares to assets * @param shares The amount of shares to convert to assets * @return assets The amount of assets that the Vault would exchange for the amount of shares provided */ function convertToAssets(uint256 shares) external view returns (uint256 assets); /** * @notice Check whether state update is required * @return `true` if state update is required, `false` otherwise */ function isStateUpdateRequired() external view returns (bool); /** * @notice Updates the total amount of assets in the Vault and its exit queue * @param harvestParams The parameters for harvesting Keeper rewards */ function updateState(IKeeperRewards.HarvestParams calldata harvestParams) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IKeeperValidators} from './IKeeperValidators.sol'; import {IVaultAdmin} from './IVaultAdmin.sol'; import {IVaultState} from './IVaultState.sol'; /** * @title IVaultValidators * @author StakeWise * @notice Defines the interface for VaultValidators contract */ interface IVaultValidators is IVaultAdmin, IVaultState { /** * @notice Event emitted on validator registration * @param publicKey The public key of the validator that was registered */ event ValidatorRegistered(bytes publicKey); /** * @notice Event emitted on keys manager address update (deprecated) * @param caller The address of the function caller * @param keysManager The address of the new keys manager */ event KeysManagerUpdated(address indexed caller, address indexed keysManager); /** * @notice Event emitted on validators merkle tree root update (deprecated) * @param caller The address of the function caller * @param validatorsRoot The new validators merkle tree root */ event ValidatorsRootUpdated(address indexed caller, bytes32 indexed validatorsRoot); /** * @notice Event emitted on validators manager address update * @param caller The address of the function caller * @param validatorsManager The address of the new validators manager */ event ValidatorsManagerUpdated(address indexed caller, address indexed validatorsManager); /** * @notice The Vault validators manager address * @return The address that can register validators */ function validatorsManager() external view returns (address); /** * @notice Function for registering single or multiple validators * @param keeperParams The parameters for getting approval from Keeper oracles * @param validatorsManagerSignature The optional signature from the validators manager */ function registerValidators( IKeeperValidators.ApprovalParams calldata keeperParams, bytes calldata validatorsManagerSignature ) external; /** * @notice Function for updating the validators manager. Can only be called by the admin. Default is the DepositDataRegistry contract. * @param _validatorsManager The new validators manager address */ function setValidatorsManager(address _validatorsManager) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IVaultState} from './IVaultState.sol'; /** * @title IVaultEnterExit * @author StakeWise * @notice Defines the interface for the VaultEnterExit contract */ interface IVaultEnterExit is IVaultState { /** * @notice Event emitted on deposit * @param caller The address that called the deposit function * @param receiver The address that received the shares * @param assets The number of assets deposited by the caller * @param shares The number of shares received * @param referrer The address of the referrer */ event Deposited( address indexed caller, address indexed receiver, uint256 assets, uint256 shares, address referrer ); /** * @notice Event emitted on redeem * @param owner The address that owns the shares * @param receiver The address that received withdrawn assets * @param assets The total number of withdrawn assets * @param shares The total number of withdrawn shares */ event Redeemed(address indexed owner, address indexed receiver, uint256 assets, uint256 shares); /** * @notice Event emitted on shares added to the exit queue * @param owner The address that owns the shares * @param receiver The address that will receive withdrawn assets * @param positionTicket The exit queue ticket that was assigned to the position * @param shares The number of shares that queued for the exit */ event ExitQueueEntered( address indexed owner, address indexed receiver, uint256 positionTicket, uint256 shares ); /** * @notice Event emitted on shares added to the V2 exit queue (deprecated) * @param owner The address that owns the shares * @param receiver The address that will receive withdrawn assets * @param positionTicket The exit queue ticket that was assigned to the position * @param shares The number of shares that queued for the exit * @param assets The number of assets that queued for the exit */ event V2ExitQueueEntered( address indexed owner, address indexed receiver, uint256 positionTicket, uint256 shares, uint256 assets ); /** * @notice Event emitted on claim of the exited assets * @param receiver The address that has received withdrawn assets * @param prevPositionTicket The exit queue ticket received after the `enterExitQueue` call * @param newPositionTicket The new exit queue ticket in case not all the shares were withdrawn. Otherwise 0. * @param withdrawnAssets The total number of assets withdrawn */ event ExitedAssetsClaimed( address indexed receiver, uint256 prevPositionTicket, uint256 newPositionTicket, uint256 withdrawnAssets ); /** * @notice Locks shares to the exit queue. The shares continue earning rewards until they will be burned by the Vault. * @param shares The number of shares to lock * @param receiver The address that will receive assets upon withdrawal * @return positionTicket The position ticket of the exit queue. Returns uint256 max if no ticket created. */ function enterExitQueue( uint256 shares, address receiver ) external returns (uint256 positionTicket); /** * @notice Get the exit queue index to claim exited assets from * @param positionTicket The exit queue position ticket to get the index for * @return The exit queue index that should be used to claim exited assets. * Returns -1 in case such index does not exist. */ function getExitQueueIndex(uint256 positionTicket) external view returns (int256); /** * @notice Calculates the number of shares and assets that can be claimed from the exit queue. * @param receiver The address that will receive assets upon withdrawal * @param positionTicket The exit queue ticket received after the `enterExitQueue` call * @param timestamp The timestamp when the shares entered the exit queue * @param exitQueueIndex The exit queue index at which the shares were burned. It can be looked up by calling `getExitQueueIndex`. * @return leftTickets The number of tickets left in the queue * @return exitedTickets The number of tickets that have already exited * @return exitedAssets The number of assets that can be claimed */ function calculateExitedAssets( address receiver, uint256 positionTicket, uint256 timestamp, uint256 exitQueueIndex ) external view returns (uint256 leftTickets, uint256 exitedTickets, uint256 exitedAssets); /** * @notice Claims assets that were withdrawn by the Vault. It can be called only after the `enterExitQueue` call by the `receiver`. * @param positionTicket The exit queue ticket received after the `enterExitQueue` call * @param timestamp The timestamp when the assets entered the exit queue * @param exitQueueIndex The exit queue index at which the shares were burned. * It can be looked up by calling `getExitQueueIndex`. */ function claimExitedAssets( uint256 positionTicket, uint256 timestamp, uint256 exitQueueIndex ) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IVaultState} from './IVaultState.sol'; import {IVaultEnterExit} from './IVaultEnterExit.sol'; /** * @title IVaultOsToken * @author StakeWise * @notice Defines the interface for the VaultOsToken contract */ interface IVaultOsToken is IVaultState, IVaultEnterExit { /** * @notice Event emitted on minting osToken * @param caller The address of the function caller * @param receiver The address of the osToken receiver * @param assets The amount of minted assets * @param shares The amount of minted shares * @param referrer The address of the referrer */ event OsTokenMinted( address indexed caller, address receiver, uint256 assets, uint256 shares, address referrer ); /** * @notice Event emitted on burning OsToken * @param caller The address of the function caller * @param assets The amount of burned assets * @param shares The amount of burned shares */ event OsTokenBurned(address indexed caller, uint256 assets, uint256 shares); /** * @notice Event emitted on osToken position liquidation * @param caller The address of the function caller * @param user The address of the user liquidated * @param receiver The address of the receiver of the liquidated assets * @param osTokenShares The amount of osToken shares to liquidate * @param shares The amount of vault shares burned * @param receivedAssets The amount of assets received */ event OsTokenLiquidated( address indexed caller, address indexed user, address receiver, uint256 osTokenShares, uint256 shares, uint256 receivedAssets ); /** * @notice Event emitted on osToken position redemption * @param caller The address of the function caller * @param user The address of the position owner to redeem from * @param receiver The address of the receiver of the redeemed assets * @param osTokenShares The amount of osToken shares to redeem * @param shares The amount of vault shares burned * @param assets The amount of assets received */ event OsTokenRedeemed( address indexed caller, address indexed user, address receiver, uint256 osTokenShares, uint256 shares, uint256 assets ); /** * @notice Struct of osToken position * @param shares The total number of minted osToken shares. Will increase based on the treasury fee. * @param cumulativeFeePerShare The cumulative fee per share */ struct OsTokenPosition { uint128 shares; uint128 cumulativeFeePerShare; } /** * @notice Get total amount of minted osToken shares * @param user The address of the user * @return shares The number of minted osToken shares */ function osTokenPositions(address user) external view returns (uint128 shares); /** * @notice Mints OsToken shares * @param receiver The address that will receive the minted OsToken shares * @param osTokenShares The number of OsToken shares to mint to the receiver. To mint the maximum amount of shares, use 2^256 - 1. * @param referrer The address of the referrer * @return assets The number of assets minted to the receiver */ function mintOsToken( address receiver, uint256 osTokenShares, address referrer ) external returns (uint256 assets); /** * @notice Burns osToken shares * @param osTokenShares The number of shares to burn * @return assets The number of assets burned */ function burnOsToken(uint128 osTokenShares) external returns (uint256 assets); /** * @notice Liquidates a user position and returns the number of received assets. * Can only be called when health factor is below 1 by the liquidator. * @param osTokenShares The number of shares to cover * @param owner The address of the position owner to liquidate * @param receiver The address of the receiver of the liquidated assets */ function liquidateOsToken(uint256 osTokenShares, address owner, address receiver) external; /** * @notice Redeems osToken shares for assets. Can only be called when health factor is above redeemFromHealthFactor by the redeemer. * @param osTokenShares The number of osToken shares to redeem * @param owner The address of the position owner to redeem from * @param receiver The address of the receiver of the redeemed assets */ function redeemOsToken(uint256 osTokenShares, address owner, address receiver) external; /** * @notice Transfers minted osToken shares to the OsTokenVaultEscrow contract, enters the exit queue for staked assets * @param osTokenShares The number of osToken shares to transfer * @return positionTicket The exit position ticket */ function transferOsTokenPositionToEscrow( uint256 osTokenShares ) external returns (uint256 positionTicket); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IVaultState} from './IVaultState.sol'; /** * @title IVaultMev * @author StakeWise * @notice Common interface for the VaultMev contracts */ interface IVaultMev is IVaultState { /** * @notice The contract that accumulates MEV rewards * @return The MEV escrow contract address */ function mevEscrow() external view returns (address); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IVaultState} from './IVaultState.sol'; import {IVaultValidators} from './IVaultValidators.sol'; import {IVaultEnterExit} from './IVaultEnterExit.sol'; import {IKeeperRewards} from './IKeeperRewards.sol'; import {IVaultMev} from './IVaultMev.sol'; /** * @title IVaultEthStaking * @author StakeWise * @notice Defines the interface for the VaultEthStaking contract */ interface IVaultEthStaking is IVaultState, IVaultValidators, IVaultEnterExit, IVaultMev { /** * @notice Deposit ETH to the Vault * @param receiver The address that will receive Vault's shares * @param referrer The address of the referrer. Set to zero address if not used. * @return shares The number of shares minted */ function deposit(address receiver, address referrer) external payable returns (uint256 shares); /** * @notice Used by MEV escrow to transfer ETH. */ function receiveFromMevEscrow() external payable; /** * @notice Updates Vault state and deposits ETH to the Vault * @param receiver The address that will receive Vault's shares * @param referrer The address of the referrer. Set to zero address if not used. * @param harvestParams The parameters for harvesting Keeper rewards * @return shares The number of shares minted */ function updateStateAndDeposit( address receiver, address referrer, IKeeperRewards.HarvestParams calldata harvestParams ) external payable returns (uint256 shares); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.22; /** * @title Multicall * @author Uniswap * @notice Adopted from https://github.com/Uniswap/v3-periphery/blob/1d69caf0d6c8cfeae9acd1f34ead30018d6e6400/contracts/base/Multicall.sol * @notice Enables calling multiple methods in a single call to the contract */ interface IMulticall { /** * @notice Call multiple functions in the current contract and return the data from all of them if they all succeed * @param data The encoded function data for each of the calls to make to this contract * @return results The results from each of the calls passed in via data */ function multicall(bytes[] calldata data) external returns (bytes[] memory results); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @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 value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/Clones.sol) pragma solidity ^0.8.20; /** * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for * deploying minimal proxy contracts, also known as "clones". * * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies * > a minimal bytecode implementation that delegates all calls to a known, fixed address. * * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2` * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the * deterministic method. */ library Clones { /** * @dev A clone instance deployment failed. */ error ERC1167FailedCreateClone(); /** * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. * * This function uses the create opcode, which should never revert. */ function clone(address implementation) internal returns (address instance) { /// @solidity memory-safe-assembly assembly { // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes // of the `implementation` address with the bytecode before the address. mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) instance := create(0, 0x09, 0x37) } if (instance == address(0)) { revert ERC1167FailedCreateClone(); } } /** * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. * * This function uses the create2 opcode and a `salt` to deterministically deploy * the clone. Using the same `implementation` and `salt` multiple time will revert, since * the clones cannot be deployed twice at the same address. */ function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) { /// @solidity memory-safe-assembly assembly { // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes // of the `implementation` address with the bytecode before the address. mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) instance := create2(0, 0x09, 0x37, salt) } if (instance == address(0)) { revert ERC1167FailedCreateClone(); } } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress( address implementation, bytes32 salt, address deployer ) internal pure returns (address predicted) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(add(ptr, 0x38), deployer) mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff) mstore(add(ptr, 0x14), implementation) mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73) mstore(add(ptr, 0x58), salt) mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37)) predicted := keccak256(add(ptr, 0x43), 0x55) } } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress( address implementation, bytes32 salt ) internal view returns (address predicted) { return predictDeterministicAddress(implementation, salt, address(this)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.22; import '../interfaces/IMulticall.sol'; /** * @title Multicall * @author Uniswap * @notice Adopted from https://github.com/Uniswap/v3-periphery/blob/1d69caf0d6c8cfeae9acd1f34ead30018d6e6400/contracts/base/Multicall.sol * @notice Enables calling multiple methods in a single call to the contract */ abstract contract Multicall is IMulticall { /// @inheritdoc IMulticall function multicall(bytes[] calldata data) external override returns (bytes[] memory results) { uint256 dataLength = data.length; results = new bytes[](dataLength); for (uint256 i = 0; i < dataLength; i++) { (bool success, bytes memory result) = address(this).delegatecall(data[i]); if (!success) { // Next 5 lines from https://ethereum.stackexchange.com/a/83577 if (result.length < 68) revert(); assembly { result := add(result, 0x04) } revert(abi.decode(result, (string))); } results[i] = result; } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; /** * @title Errors * @author StakeWise * @notice Contains all the custom errors */ library Errors { error AccessDenied(); error InvalidShares(); error InvalidAssets(); error ZeroAddress(); error InsufficientAssets(); error CapacityExceeded(); error InvalidCapacity(); error InvalidSecurityDeposit(); error InvalidFeeRecipient(); error InvalidFeePercent(); error NotHarvested(); error NotCollateralized(); error InvalidProof(); error LowLtv(); error InvalidPosition(); error InvalidHealthFactor(); error InvalidReceivedAssets(); error InvalidTokenMeta(); error UpgradeFailed(); error InvalidValidators(); error DeadlineExpired(); error PermitInvalidSigner(); error InvalidValidatorsRegistryRoot(); error InvalidVault(); error AlreadyAdded(); error AlreadyRemoved(); error InvalidOracles(); error NotEnoughSignatures(); error InvalidOracle(); error TooEarlyUpdate(); error InvalidAvgRewardPerSecond(); error InvalidRewardsRoot(); error HarvestFailed(); error LiquidationDisabled(); error InvalidLiqThresholdPercent(); error InvalidLiqBonusPercent(); error InvalidLtvPercent(); error InvalidCheckpointIndex(); error InvalidCheckpointValue(); error MaxOraclesExceeded(); error ExitRequestNotProcessed(); error ValueNotChanged(); error InvalidWithdrawalCredentials(); error EigenPodNotFound(); error InvalidQueuedShares(); error FlashLoanFailed(); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IMulticall} from './IMulticall.sol'; /** * @title IOsTokenVaultEscrow * @author StakeWise * @notice Interface for OsTokenVaultEscrow contract */ interface IOsTokenVaultEscrow is IMulticall { /** * @notice Struct to store the escrow position details * @param owner The address of the assets owner * @param exitedAssets The amount of assets exited and ready to be claimed * @param osTokenShares The amount of osToken shares * @param cumulativeFeePerShare The cumulative fee per share used to calculate the osToken fee */ struct Position { address owner; uint96 exitedAssets; uint128 osTokenShares; uint128 cumulativeFeePerShare; } /** * @notice Event emitted on position creation * @param vault The address of the vault * @param exitPositionTicket The exit position ticket * @param owner The address of the assets owner * @param osTokenShares The amount of osToken shares * @param cumulativeFeePerShare The cumulative fee per share used to calculate the osToken fee */ event PositionCreated( address indexed vault, uint256 indexed exitPositionTicket, address owner, uint256 osTokenShares, uint256 cumulativeFeePerShare ); /** * @notice Event emitted on assets exit processing * @param vault The address of the vault * @param caller The address of the caller * @param exitPositionTicket The exit position ticket * @param exitedAssets The amount of exited assets claimed */ event ExitedAssetsProcessed( address indexed vault, address indexed caller, uint256 indexed exitPositionTicket, uint256 exitedAssets ); /** * @notice Event emitted on osToken liquidation * @param caller The address of the function caller * @param vault The address of the vault * @param exitPositionTicket The exit position ticket * @param receiver The address of the receiver of the liquidated assets * @param osTokenShares The amount of osToken shares to liquidate * @param receivedAssets The amount of assets received */ event OsTokenLiquidated( address indexed caller, address indexed vault, uint256 indexed exitPositionTicket, address receiver, uint256 osTokenShares, uint256 receivedAssets ); /** * @notice Event emitted on osToken redemption * @param caller The address of the function caller * @param vault The address of the vault * @param exitPositionTicket The exit position ticket * @param receiver The address of the receiver of the redeemed assets * @param osTokenShares The amount of osToken shares to redeem * @param receivedAssets The amount of assets received */ event OsTokenRedeemed( address indexed caller, address indexed vault, uint256 indexed exitPositionTicket, address receiver, uint256 osTokenShares, uint256 receivedAssets ); /** * @notice Event emitted on exited assets claim * @param receiver The address of the receiver of the exited assets * @param vault The address of the vault * @param exitPositionTicket The exit position ticket * @param osTokenShares The amount of osToken shares burned * @param assets The amount of assets claimed */ event ExitedAssetsClaimed( address indexed receiver, address indexed vault, uint256 indexed exitPositionTicket, uint256 osTokenShares, uint256 assets ); /** * @notice Event emitted on liquidation configuration update * @param liqThresholdPercent The liquidation threshold percent * @param liqBonusPercent The liquidation bonus percent */ event LiqConfigUpdated(uint64 liqThresholdPercent, uint256 liqBonusPercent); /** * @notice Event emitted on authenticator update * @param newAuthenticator The address of the new authenticator */ event AuthenticatorUpdated(address newAuthenticator); /** * @notice The liquidation threshold percent * @return The liquidation threshold percent starting from which the osToken shares can be liquidated */ function liqThresholdPercent() external view returns (uint64); /** * @notice The liquidation bonus percent * @return The liquidation bonus percent paid for liquidating the osToken shares */ function liqBonusPercent() external view returns (uint256); /** * @notice The address of the authenticator * @return The address of the authenticator contract */ function authenticator() external view returns (address); /** * @notice Get the position details * @param vault The address of the vault * @param positionTicket The exit position ticket * @return owner The address of the assets owner * @return exitedAssets The amount of assets exited and ready to be claimed * @return osTokenShares The amount of osToken shares */ function getPosition( address vault, uint256 positionTicket ) external view returns (address, uint256, uint256); /** * @notice Registers the new escrow position * @param owner The address of the exited assets owner * @param exitPositionTicket The exit position ticket * @param osTokenShares The amount of osToken shares * @param cumulativeFeePerShare The cumulative fee per share used to calculate the osToken fee */ function register( address owner, uint256 exitPositionTicket, uint256 osTokenShares, uint256 cumulativeFeePerShare ) external; /** * @notice Claims exited assets from the vault to the escrow * @param vault The address of the vault * @param exitPositionTicket The exit position ticket * @param timestamp The timestamp of the exit * @param exitQueueIndex The index of the exit in the queue */ function processExitedAssets( address vault, uint256 exitPositionTicket, uint256 timestamp, uint256 exitQueueIndex ) external; /** * @notice Claims the exited assets from the escrow to the owner. Can only be called by the position owner. * @param vault The address of the vault * @param exitPositionTicket The exit position ticket * @param osTokenShares The amount of osToken shares to burn * @return claimedAssets The amount of assets claimed */ function claimExitedAssets( address vault, uint256 exitPositionTicket, uint256 osTokenShares ) external returns (uint256 claimedAssets); /** * @notice Liquidates the osToken shares * @param vault The address of the vault * @param exitPositionTicket The exit position ticket * @param osTokenShares The amount of osToken shares to liquidate * @param receiver The address of the receiver of the liquidated assets */ function liquidateOsToken( address vault, uint256 exitPositionTicket, uint256 osTokenShares, address receiver ) external; /** * @notice Redeems the osToken shares. Can only be called by the osToken redeemer. * @param vault The address of the vault * @param exitPositionTicket The exit position ticket * @param osTokenShares The amount of osToken shares to redeem * @param receiver The address of the receiver of the redeemed assets */ function redeemOsToken( address vault, uint256 exitPositionTicket, uint256 osTokenShares, address receiver ) external; /** * @notice Updates the authenticator. Can only be called by the owner. * @param newAuthenticator The address of the new authenticator */ function setAuthenticator(address newAuthenticator) external; /** * @notice Updates the liquidation configuration. Can only be called by the owner. * @param _liqThresholdPercent The liquidation threshold percent * @param _liqBonusPercent The liquidation bonus percent */ function updateLiqConfig(uint64 _liqThresholdPercent, uint256 _liqBonusPercent) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; /** * @title IOsTokenVaultController * @author StakeWise * @notice Defines the interface for the OsTokenVaultController contract */ interface IOsTokenVaultController { /** * @notice Event emitted on minting shares * @param vault The address of the Vault * @param receiver The address that received the shares * @param assets The number of assets collateralized * @param shares The number of tokens the owner received */ event Mint(address indexed vault, address indexed receiver, uint256 assets, uint256 shares); /** * @notice Event emitted on burning shares * @param vault The address of the Vault * @param owner The address that owns the shares * @param assets The total number of assets withdrawn * @param shares The total number of shares burned */ event Burn(address indexed vault, address indexed owner, uint256 assets, uint256 shares); /** * @notice Event emitted on state update * @param profitAccrued The profit accrued since the last update * @param treasuryShares The number of shares minted for the treasury * @param treasuryAssets The number of assets minted for the treasury */ event StateUpdated(uint256 profitAccrued, uint256 treasuryShares, uint256 treasuryAssets); /** * @notice Event emitted on capacity update * @param capacity The amount after which the OsToken stops accepting deposits */ event CapacityUpdated(uint256 capacity); /** * @notice Event emitted on treasury address update * @param treasury The new treasury address */ event TreasuryUpdated(address indexed treasury); /** * @notice Event emitted on fee percent update * @param feePercent The new fee percent */ event FeePercentUpdated(uint16 feePercent); /** * @notice Event emitted on average reward per second update * @param avgRewardPerSecond The new average reward per second */ event AvgRewardPerSecondUpdated(uint256 avgRewardPerSecond); /** * @notice Event emitted on keeper address update * @param keeper The new keeper address */ event KeeperUpdated(address keeper); /** * @notice The OsToken capacity * @return The amount after which the OsToken stops accepting deposits */ function capacity() external view returns (uint256); /** * @notice The DAO treasury address that receives OsToken fees * @return The address of the treasury */ function treasury() external view returns (address); /** * @notice The fee percent (multiplied by 100) * @return The fee percent applied by the OsToken on the rewards */ function feePercent() external view returns (uint64); /** * @notice The address that can update avgRewardPerSecond * @return The address of the keeper contract */ function keeper() external view returns (address); /** * @notice The average reward per second used to mint OsToken rewards * @return The average reward per second earned by the Vaults */ function avgRewardPerSecond() external view returns (uint256); /** * @notice The fee per share used for calculating the fee for every position * @return The cumulative fee per share */ function cumulativeFeePerShare() external view returns (uint256); /** * @notice The total number of shares controlled by the OsToken * @return The total number of shares */ function totalShares() external view returns (uint256); /** * @notice Total assets controlled by the OsToken * @return The total amount of the underlying asset that is "managed" by OsToken */ function totalAssets() external view returns (uint256); /** * @notice Converts shares to assets * @param assets The amount of assets to convert to shares * @return shares The amount of shares that the OsToken would exchange for the amount of assets provided */ function convertToShares(uint256 assets) external view returns (uint256 shares); /** * @notice Converts assets to shares * @param shares The amount of shares to convert to assets * @return assets The amount of assets that the OsToken would exchange for the amount of shares provided */ function convertToAssets(uint256 shares) external view returns (uint256 assets); /** * @notice Updates rewards and treasury fee checkpoint for the OsToken */ function updateState() external; /** * @notice Mint OsToken shares. Can only be called by the registered vault. * @param receiver The address that will receive the shares * @param shares The amount of shares to mint * @return assets The amount of assets minted */ function mintShares(address receiver, uint256 shares) external returns (uint256 assets); /** * @notice Burn shares for withdrawn assets. Can only be called by the registered vault. * @param owner The address that owns the shares * @param shares The amount of shares to burn * @return assets The amount of assets withdrawn */ function burnShares(address owner, uint256 shares) external returns (uint256 assets); /** * @notice Update treasury address. Can only be called by the owner. * @param _treasury The new treasury address */ function setTreasury(address _treasury) external; /** * @notice Update capacity. Can only be called by the owner. * @param _capacity The amount after which the OsToken stops accepting deposits */ function setCapacity(uint256 _capacity) external; /** * @notice Update fee percent. Can only be called by the owner. Cannot be larger than 10 000 (100%). * @param _feePercent The new fee percent */ function setFeePercent(uint16 _feePercent) external; /** * @notice Update keeper address. Can only be called by the owner. * @param _keeper The new keeper address */ function setKeeper(address _keeper) external; /** * @notice Updates average reward per second. Can only be called by the keeper. * @param _avgRewardPerSecond The new average reward per second */ function setAvgRewardPerSecond(uint256 _avgRewardPerSecond) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; /** * @title IOsTokenConfig * @author StakeWise * @notice Defines the interface for the OsTokenConfig contract */ interface IOsTokenConfig { /** * @notice Emitted when OsToken minting and liquidating configuration values are updated * @param vault The address of the vault to update the config for. Will be zero address if it is a default config. * @param liqBonusPercent The new liquidation bonus percent value * @param liqThresholdPercent The new liquidation threshold percent value * @param ltvPercent The new loan-to-value (LTV) percent value */ event OsTokenConfigUpdated( address vault, uint128 liqBonusPercent, uint64 liqThresholdPercent, uint64 ltvPercent ); /** * @notice Emitted when the OsToken redeemer address is updated * @param newRedeemer The address of the new redeemer */ event RedeemerUpdated(address newRedeemer); /** * @notice The OsToken minting and liquidating configuration values * @param liqThresholdPercent The liquidation threshold percent used to calculate health factor for OsToken position * @param liqBonusPercent The minimal bonus percent that liquidator earns on OsToken position liquidation * @param ltvPercent The percent used to calculate how much user can mint OsToken shares */ struct Config { uint128 liqBonusPercent; uint64 liqThresholdPercent; uint64 ltvPercent; } /** * @notice The address of the OsToken redeemer * @return The address of the redeemer */ function redeemer() external view returns (address); /** * @notice Returns the OsToken minting and liquidating configuration values for the vault * @param vault The address of the vault to get the config for * @return config The OsToken config for the vault */ function getConfig(address vault) external view returns (Config memory config); /** * @notice Sets the OsToken redeemer address. Can only be called by the owner. * @param newRedeemer The address of the new redeemer */ function setRedeemer(address newRedeemer) external; /** * @notice Updates the OsToken minting and liquidating configuration values. Can only be called by the owner. * @param vault The address of the vault. Set to zero address to update the default config. * @param config The new OsToken configuration */ function updateConfig(address vault, Config memory config) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; /** * @title IOsTokenFlashLoans * @author StakeWise * @notice Interface for OsTokenFlashLoans contract */ interface IOsTokenFlashLoans { /** * @notice Event emitted on flash loan * @param caller The address of the caller * @param amount The flashLoan osToken shares amount */ event OsTokenFlashLoan(address indexed caller, uint256 amount); /** * @notice Flash loan OsToken shares * @param osTokenShares The flashLoan osToken shares amount * @param userData Arbitrary data passed to the `IOsTokenFlashLoanRecipient.receiveFlashLoan` function */ function flashLoan(uint256 osTokenShares, bytes memory userData) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; /** * @title IOsTokenFlashLoanRecipient * @author StakeWise * @notice Interface for OsTokenFlashLoanRecipient contract */ interface IOsTokenFlashLoanRecipient { /** * @notice Receive flash loan hook * @param osTokenShares The osToken flash loan amount * @param userData Arbitrary data passed to the hook */ function receiveFlashLoan(uint256 osTokenShares, bytes memory userData) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.26; /** * @title IBalancerVault * @author Balancer * @notice Interface for the Balancer Vault contract */ interface IBalancerVault { enum SwapKind { GIVEN_IN, GIVEN_OUT } /** * @dev Data for a single swap executed by `swap`. `amount` is either `amountIn` or `amountOut` depending on * the `kind` value. * * `assetIn` and `assetOut` are either token addresses, or the IAsset sentinel value for ETH (the zero address). * Note that Pools never interact with ETH directly: it will be wrapped to or unwrapped from WETH by the Vault. * * The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be * used to extend swap behavior. */ struct SingleSwap { bytes32 poolId; SwapKind kind; address assetIn; address assetOut; uint256 amount; bytes userData; } /** * @dev All tokens in a swap are either sent from the `sender` account to the Vault, or from the Vault to the * `recipient` account. * * If the caller is not `sender`, it must be an authorized relayer for them. * * If `fromInternalBalance` is true, the `sender`'s Internal Balance will be preferred, performing an ERC20 * transfer for the difference between the requested amount and the User's Internal Balance (if any). The `sender` * must have allowed the Vault to use their tokens via `IERC20.approve()`. This matches the behavior of * `joinPool`. * * If `toInternalBalance` is true, tokens will be deposited to `recipient`'s internal balance instead of * transferred. This matches the behavior of `exitPool`. * * Note that ETH cannot be deposited to or withdrawn from Internal Balance: attempting to do so will trigger a * revert. */ struct FundManagement { address sender; bool fromInternalBalance; address payable recipient; bool toInternalBalance; } /** * @dev Performs a swap with a single Pool. * * If the swap is 'given in' (the number of tokens to send to the Pool is known), it returns the amount of tokens * taken from the Pool, which must be greater than or equal to `limit`. * * If the swap is 'given out' (the number of tokens to take from the Pool is known), it returns the amount of tokens * sent to the Pool, which must be less than or equal to `limit`. * * Internal Balance usage and the recipient are determined by the `funds` struct. * * Emits a `Swap` event. */ function swap( SingleSwap memory singleSwap, FundManagement memory funds, uint256 limit, uint256 deadline ) external payable returns (uint256); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.26; import {IKeeperRewards} from '@stakewise-core/interfaces/IKeeperRewards.sol'; import {IOsTokenFlashLoanRecipient} from '@stakewise-core/interfaces/IOsTokenFlashLoanRecipient.sol'; import {IStrategy} from '../../interfaces/IStrategy.sol'; /** * @title ILeverageStrategy * @author StakeWise * @notice Interface for LeverageStrategy contract */ interface ILeverageStrategy is IOsTokenFlashLoanRecipient, IStrategy { error InvalidFlashloanAction(); error InvalidMaxSlippagePercent(); error ExitQueueNotEntered(); error InvalidExitQueuePercent(); error InvalidExitQueueTicket(); error InvalidBalancerPoolId(); /** * @notice Enum for flashloan actions * @param Deposit Deposit assets * @param ClaimExitedAssets Claim exited assets * @param RescueVaultAssets Rescue vault assets * @param RescueLendingAssets Rescue lending assets */ enum FlashloanAction { Deposit, ClaimExitedAssets, RescueVaultAssets, RescueLendingAssets } /** * @notice Struct to store the exit position * @param positionTicket The exit position ticket * @param timestamp The timestamp of the exit position * @param exitQueueIndex The index of the exit position in the processed queue */ struct ExitPosition { uint256 positionTicket; uint256 timestamp; uint256 exitQueueIndex; } /** * @notice Event emitted when the strategy proxy is created * @param strategyProxyId The id of the strategy proxy * @param vault The address of the vault * @param user The address of the user * @param proxy The address of the proxy created */ event StrategyProxyCreated( bytes32 indexed strategyProxyId, address indexed vault, address indexed user, address proxy ); /** * @notice Deposit assets to the strategy * @param vault The address of the vault * @param user The address of the user * @param osTokenShares Amount of osToken shares to deposit * @param leverageOsTokenShares Amount of osToken shares leveraged */ event Deposited(address indexed vault, address indexed user, uint256 osTokenShares, uint256 leverageOsTokenShares); /** * @notice Enter the OsToken escrow exit queue * @param vault The address of the vault * @param user The address of the user * @param positionTicket The exit position ticket * @param timestamp The timestamp of the exit position ticket * @param osTokenShares The amount of osToken shares to exit * @param positionPercent The percent of the position that is exiting from strategy */ event ExitQueueEntered( address indexed vault, address indexed user, uint256 positionTicket, uint256 timestamp, uint256 osTokenShares, uint256 positionPercent ); /** * @notice Claim exited assets * @param osTokenShares The amount of osToken shares claimed by the user * @param assets The amount of assets claimed by the user */ event ExitedAssetsClaimed(address indexed vault, address indexed user, uint256 osTokenShares, uint256 assets); /** * @notice Event emitted when the strategy proxy is upgraded * @param vault The address of the vault * @param user The address of the user * @param strategy The address of the new strategy */ event StrategyProxyUpgraded(address indexed vault, address indexed user, address strategy); /** * @notice Event emitted when the vault assets are rescued * @param vault The address of the vault * @param user The address of the user * @param osTokenShares The amount of osToken shares rescued * @param assets The amount of assets rescued */ event VaultAssetsRescued(address indexed vault, address indexed user, uint256 osTokenShares, uint256 assets); /** * @notice Event emitted when the lending assets are rescued * @param vault The address of the vault * @param user The address of the user * @param osTokenShares The amount of osToken shares rescued * @param assets The amount of assets rescued */ event LendingAssetsRescued(address indexed vault, address indexed user, uint256 osTokenShares, uint256 assets); /** * @notice Get the strategy proxy address * @param vault The address of the vault * @param user The address of the user * @return proxy The address of the strategy proxy */ function getStrategyProxy(address vault, address user) external view returns (address proxy); /** * @notice Checks if the proxy is exiting * @param proxy The address of the proxy * @return isExiting True if the proxy is exiting */ function isStrategyProxyExiting( address proxy ) external view returns (bool isExiting); /** * @notice Updates the vault state * @param vault The address of the vault * @param harvestParams The harvest parameters */ function updateVaultState(address vault, IKeeperRewards.HarvestParams calldata harvestParams) external; /** * @notice Approves the osToken transfers from the user to the strategy * @param vault The address of the vault * @param osTokenShares Amount of osToken shares to approve * @param deadline Unix timestamp after which the transaction will revert * @param v ECDSA signature v * @param r ECDSA signature r * @param s ECDSA signature s */ function permit(address vault, uint256 osTokenShares, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external; /** * @notice Deposit assets to the strategy * @param vault The address of the vault * @param osTokenShares Amount of osToken shares to deposit */ function deposit(address vault, uint256 osTokenShares) external; /** * @notice Enter the OsToken escrow exit queue. Can only be called by the position owner. * @param vault The address of the vault * @param positionPercent The percent of the position to exit from strategy * @return positionTicket The exit position ticket */ function enterExitQueue(address vault, uint256 positionPercent) external returns (uint256 positionTicket); /** * @notice Force enter the OsToken escrow exit queue. Can be called by anyone if approaching liquidation. * @param vault The address of the vault * @param user The address of the user * @return positionTicket The exit position ticket */ function forceEnterExitQueue(address vault, address user) external returns (uint256 positionTicket); /** * @notice Claim exited assets. Can be called by anyone. * @param vault The address of the vault * @param user The address of the user * @param exitPosition The exit position to process */ function claimExitedAssets(address vault, address user, ExitPosition calldata exitPosition) external; /** * @notice Rescue vault assets. Can only be called by the position owner to rescue the vault assets in case of lending protocol liquidation. * @param vault The address of the vault * @param exitPosition The exit position to process */ function rescueVaultAssets(address vault, ExitPosition calldata exitPosition) external; /** * @notice Rescue lending assets. Can only be called by the position owner to rescue the lending assets in case of vault liquidation. * @param vault The address of the vault * @param assets The amount of assets to repay * @param maxSlippagePercent The maximum slippage percent */ function rescueLendingAssets(address vault, uint256 assets, uint256 maxSlippagePercent) external; /** * @notice Upgrade the strategy proxy. Can only be called by the proxy owner. * @param vault The address of the vault */ function upgradeProxy( address vault ) external; }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.26; /** * @title IStrategiesRegistry * @author StakeWise * @notice Defines the interface for the StrategiesRegistry contract */ interface IStrategiesRegistry { error InvalidStrategyId(); error InvalidStrategyProxyId(); /** * @notice Event emitted on a Strategy update * @param caller The address that called the function * @param strategy The address of the updated strategy * @param enabled The new status of the strategy */ event StrategyUpdated(address indexed caller, address strategy, bool enabled); /** * @notice Event emitted on adding Strategy proxy contract * @param strategy The address of the Strategy that added the proxy * @param strategyProxyId The ID of the added proxy * @param proxy The address of the added proxy */ event StrategyProxyAdded(address indexed strategy, bytes32 indexed strategyProxyId, address indexed proxy); /** * @notice Event emitted on updating the strategy configuration * @param strategyId The ID of the strategy to update the configuration * @param configName The name of the configuration to update * @param value The new value of the configuration */ event StrategyConfigUpdated(bytes32 indexed strategyId, string configName, bytes value); /** * @notice Registered Strategies * @param strategy The address of the strategy to check whether it is registered * @return `true` for the registered Strategy, `false` otherwise */ function strategies( address strategy ) external view returns (bool); /** * @notice Get the strategy proxy address based on the strategy proxy ID * @param strategyProxyId The ID of the strategy proxy to get the address * @return The address of the strategy proxy */ function strategyProxyIdToProxy( bytes32 strategyProxyId ) external view returns (address); /** * @notice Registered Strategy Proxies * @param proxy The address of the proxy to check whether it is registered * @return `true` for the registered Strategy proxy, `false` otherwise */ function strategyProxies( address proxy ) external view returns (bool); /** * @notice Get strategy configuration * @param strategyId The ID of the strategy to get the configuration * @param configName The name of the configuration * @return value The value of the configuration */ function getStrategyConfig( bytes32 strategyId, string calldata configName ) external view returns (bytes memory value); /** * @notice Set strategy configuration. Can only be called by the owner. * @param strategyId The ID of the strategy to set the configuration * @param configName The name of the configuration * @param value The value of the configuration */ function setStrategyConfig(bytes32 strategyId, string calldata configName, bytes calldata value) external; /** * @notice Function for enabling/disabling the Strategy. Can only be called by the owner. * @param strategy The address of the strategy to enable/disable * @param enabled The new status of the strategy */ function setStrategy(address strategy, bool enabled) external; /** * @notice Function for adding Strategy proxy contract. Can only be called by the registered strategy. * @param strategyProxyId The ID of the proxy to add * @param proxy The address of the proxy to add */ function addStrategyProxy(bytes32 strategyProxyId, address proxy) external; /** * @notice Function for initializing the registry. Can only be called once during the deployment. * @param _owner The address of the owner of the contract */ function initialize( address _owner ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, value); } } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, value); } } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, value); } } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, value); } } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, value); } } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, value); } } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, value); } } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, value); } } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, value); } } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, value); } } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, value); } } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, value); } } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, value); } } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, value); } } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, value); } } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, value); } } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, value); } } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, value); } } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, value); } } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, value); } } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, value); } } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, value); } } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, value); } } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, value); } } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, value); } } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, value); } } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, value); } } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, value); } } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, value); } } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, value); } } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IPoolAddressesProvider} from './IPoolAddressesProvider.sol'; import {DataTypes} from '../protocol/libraries/types/DataTypes.sol'; /** * @title IPool * @author Aave * @notice Defines the basic interface for an Aave Pool. */ interface IPool { /** * @dev Emitted on mintUnbacked() * @param reserve The address of the underlying asset of the reserve * @param user The address initiating the supply * @param onBehalfOf The beneficiary of the supplied assets, receiving the aTokens * @param amount The amount of supplied assets * @param referralCode The referral code used */ event MintUnbacked( address indexed reserve, address user, address indexed onBehalfOf, uint256 amount, uint16 indexed referralCode ); /** * @dev Emitted on backUnbacked() * @param reserve The address of the underlying asset of the reserve * @param backer The address paying for the backing * @param amount The amount added as backing * @param fee The amount paid in fees */ event BackUnbacked(address indexed reserve, address indexed backer, uint256 amount, uint256 fee); /** * @dev Emitted on supply() * @param reserve The address of the underlying asset of the reserve * @param user The address initiating the supply * @param onBehalfOf The beneficiary of the supply, receiving the aTokens * @param amount The amount supplied * @param referralCode The referral code used */ event Supply( address indexed reserve, address user, address indexed onBehalfOf, uint256 amount, uint16 indexed referralCode ); /** * @dev Emitted on withdraw() * @param reserve The address of the underlying asset being withdrawn * @param user The address initiating the withdrawal, owner of aTokens * @param to The address that will receive the underlying * @param amount The amount to be withdrawn */ event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount); /** * @dev Emitted on borrow() and flashLoan() when debt needs to be opened * @param reserve The address of the underlying asset being borrowed * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just * initiator of the transaction on flashLoan() * @param onBehalfOf The address that will be getting the debt * @param amount The amount borrowed out * @param interestRateMode The rate mode: 2 for Variable, 1 is deprecated (changed on v3.2.0) * @param borrowRate The numeric rate at which the user has borrowed, expressed in ray * @param referralCode The referral code used */ event Borrow( address indexed reserve, address user, address indexed onBehalfOf, uint256 amount, DataTypes.InterestRateMode interestRateMode, uint256 borrowRate, uint16 indexed referralCode ); /** * @dev Emitted on repay() * @param reserve The address of the underlying asset of the reserve * @param user The beneficiary of the repayment, getting his debt reduced * @param repayer The address of the user initiating the repay(), providing the funds * @param amount The amount repaid * @param useATokens True if the repayment is done using aTokens, `false` if done with underlying asset directly */ event Repay( address indexed reserve, address indexed user, address indexed repayer, uint256 amount, bool useATokens ); /** * @dev Emitted on borrow(), repay() and liquidationCall() when using isolated assets * @param asset The address of the underlying asset of the reserve * @param totalDebt The total isolation mode debt for the reserve */ event IsolationModeTotalDebtUpdated(address indexed asset, uint256 totalDebt); /** * @dev Emitted when the user selects a certain asset category for eMode * @param user The address of the user * @param categoryId The category id */ event UserEModeSet(address indexed user, uint8 categoryId); /** * @dev Emitted on setUserUseReserveAsCollateral() * @param reserve The address of the underlying asset of the reserve * @param user The address of the user enabling the usage as collateral */ event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user); /** * @dev Emitted on setUserUseReserveAsCollateral() * @param reserve The address of the underlying asset of the reserve * @param user The address of the user enabling the usage as collateral */ event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user); /** * @dev Emitted on flashLoan() * @param target The address of the flash loan receiver contract * @param initiator The address initiating the flash loan * @param asset The address of the asset being flash borrowed * @param amount The amount flash borrowed * @param interestRateMode The flashloan mode: 0 for regular flashloan, * 1 for Stable (Deprecated on v3.2.0), 2 for Variable * @param premium The fee flash borrowed * @param referralCode The referral code used */ event FlashLoan( address indexed target, address initiator, address indexed asset, uint256 amount, DataTypes.InterestRateMode interestRateMode, uint256 premium, uint16 indexed referralCode ); /** * @dev Emitted when a borrower is liquidated. * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation * @param user The address of the borrower getting liquidated * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover * @param liquidatedCollateralAmount The amount of collateral received by the liquidator * @param liquidator The address of the liquidator * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants * to receive the underlying collateral asset directly */ event LiquidationCall( address indexed collateralAsset, address indexed debtAsset, address indexed user, uint256 debtToCover, uint256 liquidatedCollateralAmount, address liquidator, bool receiveAToken ); /** * @dev Emitted when the state of a reserve is updated. * @param reserve The address of the underlying asset of the reserve * @param liquidityRate The next liquidity rate * @param stableBorrowRate The next stable borrow rate @note deprecated on v3.2.0 * @param variableBorrowRate The next variable borrow rate * @param liquidityIndex The next liquidity index * @param variableBorrowIndex The next variable borrow index */ event ReserveDataUpdated( address indexed reserve, uint256 liquidityRate, uint256 stableBorrowRate, uint256 variableBorrowRate, uint256 liquidityIndex, uint256 variableBorrowIndex ); /** * @dev Emitted when the protocol treasury receives minted aTokens from the accrued interest. * @param reserve The address of the reserve * @param amountMinted The amount minted to the treasury */ event MintedToTreasury(address indexed reserve, uint256 amountMinted); /** * @notice Mints an `amount` of aTokens to the `onBehalfOf` * @param asset The address of the underlying asset to mint * @param amount The amount to mint * @param onBehalfOf The address that will receive the aTokens * @param referralCode Code used to register the integrator originating the operation, for potential rewards. * 0 if the action is executed directly by the user, without any middle-man */ function mintUnbacked( address asset, uint256 amount, address onBehalfOf, uint16 referralCode ) external; /** * @notice Back the current unbacked underlying with `amount` and pay `fee`. * @param asset The address of the underlying asset to back * @param amount The amount to back * @param fee The amount paid in fees * @return The backed amount */ function backUnbacked(address asset, uint256 amount, uint256 fee) external returns (uint256); /** * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. * - E.g. User supplies 100 USDC and gets in return 100 aUSDC * @param asset The address of the underlying asset to supply * @param amount The amount to be supplied * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens * is a different wallet * @param referralCode Code used to register the integrator originating the operation, for potential rewards. * 0 if the action is executed directly by the user, without any middle-man */ function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external; /** * @notice Supply with transfer approval of asset to be supplied done via permit function * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713 * @param asset The address of the underlying asset to supply * @param amount The amount to be supplied * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens * is a different wallet * @param deadline The deadline timestamp that the permit is valid * @param referralCode Code used to register the integrator originating the operation, for potential rewards. * 0 if the action is executed directly by the user, without any middle-man * @param permitV The V parameter of ERC712 permit sig * @param permitR The R parameter of ERC712 permit sig * @param permitS The S parameter of ERC712 permit sig */ function supplyWithPermit( address asset, uint256 amount, address onBehalfOf, uint16 referralCode, uint256 deadline, uint8 permitV, bytes32 permitR, bytes32 permitS ) external; /** * @notice Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC * @param asset The address of the underlying asset to withdraw * @param amount The underlying amount to be withdrawn * - Send the value type(uint256).max in order to withdraw the whole aToken balance * @param to The address that will receive the underlying, same as msg.sender if the user * wants to receive it on his own wallet, or a different address if the beneficiary is a * different wallet * @return The final amount withdrawn */ function withdraw(address asset, uint256 amount, address to) external returns (uint256); /** * @notice Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower * already supplied enough collateral, or he was given enough allowance by a credit delegator on the VariableDebtToken * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet * and 100 variable debt tokens * @param asset The address of the underlying asset to borrow * @param amount The amount to be borrowed * @param interestRateMode 2 for Variable, 1 is deprecated on v3.2.0 * @param referralCode The code used to register the integrator originating the operation, for potential rewards. * 0 if the action is executed directly by the user, without any middle-man * @param onBehalfOf The address of the user who will receive the debt. Should be the address of the borrower itself * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator * if he has been given credit delegation allowance */ function borrow( address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf ) external; /** * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned * - E.g. User repays 100 USDC, burning 100 variable debt tokens of the `onBehalfOf` address * @param asset The address of the borrowed underlying asset previously borrowed * @param amount The amount to repay * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` * @param interestRateMode 2 for Variable, 1 is deprecated on v3.2.0 * @param onBehalfOf The address of the user who will get his debt reduced/removed. Should be the address of the * user calling the function if he wants to reduce/remove his own debt, or the address of any other * other borrower whose debt should be removed * @return The final amount repaid */ function repay( address asset, uint256 amount, uint256 interestRateMode, address onBehalfOf ) external returns (uint256); /** * @notice Repay with transfer approval of asset to be repaid done via permit function * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713 * @param asset The address of the borrowed underlying asset previously borrowed * @param amount The amount to repay * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` * @param interestRateMode 2 for Variable, 1 is deprecated on v3.2.0 * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the * user calling the function if he wants to reduce/remove his own debt, or the address of any other * other borrower whose debt should be removed * @param deadline The deadline timestamp that the permit is valid * @param permitV The V parameter of ERC712 permit sig * @param permitR The R parameter of ERC712 permit sig * @param permitS The S parameter of ERC712 permit sig * @return The final amount repaid */ function repayWithPermit( address asset, uint256 amount, uint256 interestRateMode, address onBehalfOf, uint256 deadline, uint8 permitV, bytes32 permitR, bytes32 permitS ) external returns (uint256); /** * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the * equivalent debt tokens * - E.g. User repays 100 USDC using 100 aUSDC, burning 100 variable debt tokens * @dev Passing uint256.max as amount will clean up any residual aToken dust balance, if the user aToken * balance is not enough to cover the whole debt * @param asset The address of the borrowed underlying asset previously borrowed * @param amount The amount to repay * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` * @param interestRateMode DEPRECATED in v3.2.0 * @return The final amount repaid */ function repayWithATokens( address asset, uint256 amount, uint256 interestRateMode ) external returns (uint256); /** * @notice Allows suppliers to enable/disable a specific supplied asset as collateral * @param asset The address of the underlying asset supplied * @param useAsCollateral True if the user wants to use the supply as collateral, false otherwise */ function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external; /** * @notice Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1 * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives * a proportionally amount of the `collateralAsset` plus a bonus to cover market risk * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation * @param user The address of the borrower getting liquidated * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants * to receive the underlying collateral asset directly */ function liquidationCall( address collateralAsset, address debtAsset, address user, uint256 debtToCover, bool receiveAToken ) external; /** * @notice Allows smartcontracts to access the liquidity of the pool within one transaction, * as long as the amount taken plus a fee is returned. * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept * into consideration. For further details please visit https://docs.aave.com/developers/ * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanReceiver interface * @param assets The addresses of the assets being flash-borrowed * @param amounts The amounts of the assets being flash-borrowed * @param interestRateModes Types of the debt to open if the flash loan is not returned: * 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver * 1 -> Deprecated on v3.2.0 * 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address * @param onBehalfOf The address that will receive the debt in the case of using 2 on `modes` * @param params Variadic packed params to pass to the receiver as extra information * @param referralCode The code used to register the integrator originating the operation, for potential rewards. * 0 if the action is executed directly by the user, without any middle-man */ function flashLoan( address receiverAddress, address[] calldata assets, uint256[] calldata amounts, uint256[] calldata interestRateModes, address onBehalfOf, bytes calldata params, uint16 referralCode ) external; /** * @notice Allows smartcontracts to access the liquidity of the pool within one transaction, * as long as the amount taken plus a fee is returned. * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept * into consideration. For further details please visit https://docs.aave.com/developers/ * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanSimpleReceiver interface * @param asset The address of the asset being flash-borrowed * @param amount The amount of the asset being flash-borrowed * @param params Variadic packed params to pass to the receiver as extra information * @param referralCode The code used to register the integrator originating the operation, for potential rewards. * 0 if the action is executed directly by the user, without any middle-man */ function flashLoanSimple( address receiverAddress, address asset, uint256 amount, bytes calldata params, uint16 referralCode ) external; /** * @notice Returns the user account data across all the reserves * @param user The address of the user * @return totalCollateralBase The total collateral of the user in the base currency used by the price feed * @return totalDebtBase The total debt of the user in the base currency used by the price feed * @return availableBorrowsBase The borrowing power left of the user in the base currency used by the price feed * @return currentLiquidationThreshold The liquidation threshold of the user * @return ltv The loan to value of The user * @return healthFactor The current health factor of the user */ function getUserAccountData( address user ) external view returns ( uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor ); /** * @notice Initializes a reserve, activating it, assigning an aToken and debt tokens and an * interest rate strategy * @dev Only callable by the PoolConfigurator contract * @param asset The address of the underlying asset of the reserve * @param aTokenAddress The address of the aToken that will be assigned to the reserve * @param variableDebtAddress The address of the VariableDebtToken that will be assigned to the reserve * @param interestRateStrategyAddress The address of the interest rate strategy contract */ function initReserve( address asset, address aTokenAddress, address variableDebtAddress, address interestRateStrategyAddress ) external; /** * @notice Drop a reserve * @dev Only callable by the PoolConfigurator contract * @dev Does not reset eMode flags, which must be considered when reusing the same reserve id for a different reserve. * @param asset The address of the underlying asset of the reserve */ function dropReserve(address asset) external; /** * @notice Updates the address of the interest rate strategy contract * @dev Only callable by the PoolConfigurator contract * @param asset The address of the underlying asset of the reserve * @param rateStrategyAddress The address of the interest rate strategy contract */ function setReserveInterestRateStrategyAddress( address asset, address rateStrategyAddress ) external; /** * @notice Accumulates interest to all indexes of the reserve * @dev Only callable by the PoolConfigurator contract * @dev To be used when required by the configurator, for example when updating interest rates strategy data * @param asset The address of the underlying asset of the reserve */ function syncIndexesState(address asset) external; /** * @notice Updates interest rates on the reserve data * @dev Only callable by the PoolConfigurator contract * @dev To be used when required by the configurator, for example when updating interest rates strategy data * @param asset The address of the underlying asset of the reserve */ function syncRatesState(address asset) external; /** * @notice Sets the configuration bitmap of the reserve as a whole * @dev Only callable by the PoolConfigurator contract * @param asset The address of the underlying asset of the reserve * @param configuration The new configuration bitmap */ function setConfiguration( address asset, DataTypes.ReserveConfigurationMap calldata configuration ) external; /** * @notice Returns the configuration of the reserve * @param asset The address of the underlying asset of the reserve * @return The configuration of the reserve */ function getConfiguration( address asset ) external view returns (DataTypes.ReserveConfigurationMap memory); /** * @notice Returns the configuration of the user across all the reserves * @param user The user address * @return The configuration of the user */ function getUserConfiguration( address user ) external view returns (DataTypes.UserConfigurationMap memory); /** * @notice Returns the normalized income of the reserve * @param asset The address of the underlying asset of the reserve * @return The reserve's normalized income */ function getReserveNormalizedIncome(address asset) external view returns (uint256); /** * @notice Returns the normalized variable debt per unit of asset * @dev WARNING: This function is intended to be used primarily by the protocol itself to get a * "dynamic" variable index based on time, current stored index and virtual rate at the current * moment (approx. a borrower would get if opening a position). This means that is always used in * combination with variable debt supply/balances. * If using this function externally, consider that is possible to have an increasing normalized * variable debt that is not equivalent to how the variable debt index would be updated in storage * (e.g. only updates with non-zero variable debt supply) * @param asset The address of the underlying asset of the reserve * @return The reserve normalized variable debt */ function getReserveNormalizedVariableDebt(address asset) external view returns (uint256); /** * @notice Returns the state and configuration of the reserve * @param asset The address of the underlying asset of the reserve * @return The state and configuration data of the reserve */ function getReserveData(address asset) external view returns (DataTypes.ReserveDataLegacy memory); /** * @notice Returns the state and configuration of the reserve, including extra data included with Aave v3.1 * @dev DEPRECATED use independent getters instead (getReserveData, getLiquidationGracePeriod) * @param asset The address of the underlying asset of the reserve * @return The state and configuration data of the reserve with virtual accounting */ function getReserveDataExtended( address asset ) external view returns (DataTypes.ReserveData memory); /** * @notice Returns the virtual underlying balance of the reserve * @param asset The address of the underlying asset of the reserve * @return The reserve virtual underlying balance */ function getVirtualUnderlyingBalance(address asset) external view returns (uint128); /** * @notice Validates and finalizes an aToken transfer * @dev Only callable by the overlying aToken of the `asset` * @param asset The address of the underlying asset of the aToken * @param from The user from which the aTokens are transferred * @param to The user receiving the aTokens * @param amount The amount being transferred/withdrawn * @param balanceFromBefore The aToken balance of the `from` user before the transfer * @param balanceToBefore The aToken balance of the `to` user before the transfer */ function finalizeTransfer( address asset, address from, address to, uint256 amount, uint256 balanceFromBefore, uint256 balanceToBefore ) external; /** * @notice Returns the list of the underlying assets of all the initialized reserves * @dev It does not include dropped reserves * @return The addresses of the underlying assets of the initialized reserves */ function getReservesList() external view returns (address[] memory); /** * @notice Returns the number of initialized reserves * @dev It includes dropped reserves * @return The count */ function getReservesCount() external view returns (uint256); /** * @notice Returns the address of the underlying asset of a reserve by the reserve id as stored in the DataTypes.ReserveData struct * @param id The id of the reserve as stored in the DataTypes.ReserveData struct * @return The address of the reserve associated with id */ function getReserveAddressById(uint16 id) external view returns (address); /** * @notice Returns the PoolAddressesProvider connected to this contract * @return The address of the PoolAddressesProvider */ function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider); /** * @notice Updates the protocol fee on the bridging * @param bridgeProtocolFee The part of the premium sent to the protocol treasury */ function updateBridgeProtocolFee(uint256 bridgeProtocolFee) external; /** * @notice Updates flash loan premiums. Flash loan premium consists of two parts: * - A part is sent to aToken holders as extra, one time accumulated interest * - A part is collected by the protocol treasury * @dev The total premium is calculated on the total borrowed amount * @dev The premium to protocol is calculated on the total premium, being a percentage of `flashLoanPremiumTotal` * @dev Only callable by the PoolConfigurator contract * @param flashLoanPremiumTotal The total premium, expressed in bps * @param flashLoanPremiumToProtocol The part of the premium sent to the protocol treasury, expressed in bps */ function updateFlashloanPremiums( uint128 flashLoanPremiumTotal, uint128 flashLoanPremiumToProtocol ) external; /** * @notice Configures a new or alters an existing collateral configuration of an eMode. * @dev In eMode, the protocol allows very high borrowing power to borrow assets of the same category. * The category 0 is reserved as it's the default for volatile assets * @param id The id of the category * @param config The configuration of the category */ function configureEModeCategory( uint8 id, DataTypes.EModeCategoryBaseConfiguration memory config ) external; /** * @notice Replaces the current eMode collateralBitmap. * @param id The id of the category * @param collateralBitmap The collateralBitmap of the category */ function configureEModeCategoryCollateralBitmap(uint8 id, uint128 collateralBitmap) external; /** * @notice Replaces the current eMode borrowableBitmap. * @param id The id of the category * @param borrowableBitmap The borrowableBitmap of the category */ function configureEModeCategoryBorrowableBitmap(uint8 id, uint128 borrowableBitmap) external; /** * @notice Returns the data of an eMode category * @dev DEPRECATED use independent getters instead * @param id The id of the category * @return The configuration data of the category */ function getEModeCategoryData( uint8 id ) external view returns (DataTypes.EModeCategoryLegacy memory); /** * @notice Returns the label of an eMode category * @param id The id of the category * @return The label of the category */ function getEModeCategoryLabel(uint8 id) external view returns (string memory); /** * @notice Returns the collateral config of an eMode category * @param id The id of the category * @return The ltv,lt,lb of the category */ function getEModeCategoryCollateralConfig( uint8 id ) external view returns (DataTypes.CollateralConfig memory); /** * @notice Returns the collateralBitmap of an eMode category * @param id The id of the category * @return The collateralBitmap of the category */ function getEModeCategoryCollateralBitmap(uint8 id) external view returns (uint128); /** * @notice Returns the borrowableBitmap of an eMode category * @param id The id of the category * @return The borrowableBitmap of the category */ function getEModeCategoryBorrowableBitmap(uint8 id) external view returns (uint128); /** * @notice Allows a user to use the protocol in eMode * @param categoryId The id of the category */ function setUserEMode(uint8 categoryId) external; /** * @notice Returns the eMode the user is using * @param user The address of the user * @return The eMode id */ function getUserEMode(address user) external view returns (uint256); /** * @notice Resets the isolation mode total debt of the given asset to zero * @dev It requires the given asset has zero debt ceiling * @param asset The address of the underlying asset to reset the isolationModeTotalDebt */ function resetIsolationModeTotalDebt(address asset) external; /** * @notice Sets the liquidation grace period of the given asset * @dev To enable a liquidation grace period, a timestamp in the future should be set, * To disable a liquidation grace period, any timestamp in the past works, like 0 * @param asset The address of the underlying asset to set the liquidationGracePeriod * @param until Timestamp when the liquidation grace period will end **/ function setLiquidationGracePeriod(address asset, uint40 until) external; /** * @notice Returns the liquidation grace period of the given asset * @param asset The address of the underlying asset * @return Timestamp when the liquidation grace period will end **/ function getLiquidationGracePeriod(address asset) external returns (uint40); /** * @notice Returns the total fee on flash loans * @return The total fee on flashloans */ function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128); /** * @notice Returns the part of the bridge fees sent to protocol * @return The bridge fee sent to the protocol treasury */ function BRIDGE_PROTOCOL_FEE() external view returns (uint256); /** * @notice Returns the part of the flashloan fees sent to protocol * @return The flashloan fee sent to the protocol treasury */ function FLASHLOAN_PREMIUM_TO_PROTOCOL() external view returns (uint128); /** * @notice Returns the maximum number of reserves supported to be listed in this Pool * @return The maximum number of reserves supported */ function MAX_NUMBER_RESERVES() external view returns (uint16); /** * @notice Mints the assets accrued through the reserve factor to the treasury in the form of aTokens * @param assets The list of reserves for which the minting needs to be executed */ function mintToTreasury(address[] calldata assets) external; /** * @notice Rescue and transfer tokens locked in this contract * @param token The address of the token * @param to The address of the recipient * @param amount The amount of token to transfer */ function rescueTokens(address token, address to, uint256 amount) external; /** * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. * - E.g. User supplies 100 USDC and gets in return 100 aUSDC * @dev Deprecated: Use the `supply` function instead * @param asset The address of the underlying asset to supply * @param amount The amount to be supplied * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens * is a different wallet * @param referralCode Code used to register the integrator originating the operation, for potential rewards. * 0 if the action is executed directly by the user, without any middle-man */ function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external; /** * @notice Gets the address of the external FlashLoanLogic */ function getFlashLoanLogic() external view returns (address); /** * @notice Gets the address of the external BorrowLogic */ function getBorrowLogic() external view returns (address); /** * @notice Gets the address of the external BridgeLogic */ function getBridgeLogic() external view returns (address); /** * @notice Gets the address of the external EModeLogic */ function getEModeLogic() external view returns (address); /** * @notice Gets the address of the external LiquidationLogic */ function getLiquidationLogic() external view returns (address); /** * @notice Gets the address of the external PoolLogic */ function getPoolLogic() external view returns (address); /** * @notice Gets the address of the external SupplyLogic */ function getSupplyLogic() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title IScaledBalanceToken * @author Aave * @notice Defines the basic interface for a scaled-balance token. */ interface IScaledBalanceToken { /** * @dev Emitted after the mint action * @param caller The address performing the mint * @param onBehalfOf The address of the user that will receive the minted tokens * @param value The scaled-up amount being minted (based on user entered amount and balance increase from interest) * @param balanceIncrease The increase in scaled-up balance since the last action of 'onBehalfOf' * @param index The next liquidity index of the reserve */ event Mint( address indexed caller, address indexed onBehalfOf, uint256 value, uint256 balanceIncrease, uint256 index ); /** * @dev Emitted after the burn action * @dev If the burn function does not involve a transfer of the underlying asset, the target defaults to zero address * @param from The address from which the tokens will be burned * @param target The address that will receive the underlying, if any * @param value The scaled-up amount being burned (user entered amount - balance increase from interest) * @param balanceIncrease The increase in scaled-up balance since the last action of 'from' * @param index The next liquidity index of the reserve */ event Burn( address indexed from, address indexed target, uint256 value, uint256 balanceIncrease, uint256 index ); /** * @notice Returns the scaled balance of the user. * @dev The scaled balance is the sum of all the updated stored balance divided by the reserve's liquidity index * at the moment of the update * @param user The user whose balance is calculated * @return The scaled balance of the user */ function scaledBalanceOf(address user) external view returns (uint256); /** * @notice Returns the scaled balance of the user and the scaled total supply. * @param user The address of the user * @return The scaled balance of the user * @return The scaled total supply */ function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256); /** * @notice Returns the scaled total supply of the scaled balance token. Represents sum(debt/index) * @return The scaled total supply */ function scaledTotalSupply() external view returns (uint256); /** * @notice Returns last index interest was accrued to the user's balance * @param user The address of the user * @return The last index interest was accrued to the user's balance, expressed in ray */ function getPreviousIndex(address user) external view returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; /** * @title WadRayMath library * @author Aave * @notice Provides functions to perform calculations with Wad and Ray units * @dev Provides mul and div function for wads (decimal numbers with 18 digits of precision) and rays (decimal numbers * with 27 digits of precision) * @dev Operations are rounded. If a value is >=.5, will be rounded up, otherwise rounded down. */ library WadRayMath { // HALF_WAD and HALF_RAY expressed with extended notation as constant with operations are not supported in Yul assembly uint256 internal constant WAD = 1e18; uint256 internal constant HALF_WAD = 0.5e18; uint256 internal constant RAY = 1e27; uint256 internal constant HALF_RAY = 0.5e27; uint256 internal constant WAD_RAY_RATIO = 1e9; /** * @dev Multiplies two wad, rounding half up to the nearest wad * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328 * @param a Wad * @param b Wad * @return c = a*b, in wad */ function wadMul(uint256 a, uint256 b) internal pure returns (uint256 c) { // to avoid overflow, a <= (type(uint256).max - HALF_WAD) / b assembly { if iszero(or(iszero(b), iszero(gt(a, div(sub(not(0), HALF_WAD), b))))) { revert(0, 0) } c := div(add(mul(a, b), HALF_WAD), WAD) } } /** * @dev Divides two wad, rounding half up to the nearest wad * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328 * @param a Wad * @param b Wad * @return c = a/b, in wad */ function wadDiv(uint256 a, uint256 b) internal pure returns (uint256 c) { // to avoid overflow, a <= (type(uint256).max - halfB) / WAD assembly { if or(iszero(b), iszero(iszero(gt(a, div(sub(not(0), div(b, 2)), WAD))))) { revert(0, 0) } c := div(add(mul(a, WAD), div(b, 2)), b) } } /** * @notice Multiplies two ray, rounding half up to the nearest ray * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328 * @param a Ray * @param b Ray * @return c = a raymul b */ function rayMul(uint256 a, uint256 b) internal pure returns (uint256 c) { // to avoid overflow, a <= (type(uint256).max - HALF_RAY) / b assembly { if iszero(or(iszero(b), iszero(gt(a, div(sub(not(0), HALF_RAY), b))))) { revert(0, 0) } c := div(add(mul(a, b), HALF_RAY), RAY) } } /** * @notice Divides two ray, rounding half up to the nearest ray * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328 * @param a Ray * @param b Ray * @return c = a raydiv b */ function rayDiv(uint256 a, uint256 b) internal pure returns (uint256 c) { // to avoid overflow, a <= (type(uint256).max - halfB) / RAY assembly { if or(iszero(b), iszero(iszero(gt(a, div(sub(not(0), div(b, 2)), RAY))))) { revert(0, 0) } c := div(add(mul(a, RAY), div(b, 2)), b) } } /** * @dev Casts ray down to wad * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328 * @param a Ray * @return b = a converted to wad, rounded half up to the nearest wad */ function rayToWad(uint256 a) internal pure returns (uint256 b) { assembly { b := div(a, WAD_RAY_RATIO) let remainder := mod(a, WAD_RAY_RATIO) if iszero(lt(remainder, div(WAD_RAY_RATIO, 2))) { b := add(b, 1) } } } /** * @dev Converts wad up to ray * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328 * @param a Wad * @return b = a converted in ray */ function wadToRay(uint256 a) internal pure returns (uint256 b) { // to avoid overflow, b/WAD_RAY_RATIO == a assembly { b := mul(a, WAD_RAY_RATIO) if iszero(eq(div(b, WAD_RAY_RATIO), a)) { revert(0, 0) } } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IERC5267} from '@openzeppelin/contracts/interfaces/IERC5267.sol'; /** * @title IKeeperOracles * @author StakeWise * @notice Defines the interface for the KeeperOracles contract */ interface IKeeperOracles is IERC5267 { /** * @notice Event emitted on the oracle addition * @param oracle The address of the added oracle */ event OracleAdded(address indexed oracle); /** * @notice Event emitted on the oracle removal * @param oracle The address of the removed oracle */ event OracleRemoved(address indexed oracle); /** * @notice Event emitted on oracles config update * @param configIpfsHash The IPFS hash of the new config */ event ConfigUpdated(string configIpfsHash); /** * @notice Function for verifying whether oracle is registered or not * @param oracle The address of the oracle to check * @return `true` for the registered oracle, `false` otherwise */ function isOracle(address oracle) external view returns (bool); /** * @notice Total Oracles * @return The total number of oracles registered */ function totalOracles() external view returns (uint256); /** * @notice Function for adding oracle to the set * @param oracle The address of the oracle to add */ function addOracle(address oracle) external; /** * @notice Function for removing oracle from the set * @param oracle The address of the oracle to remove */ function removeOracle(address oracle) external; /** * @notice Function for updating the config IPFS hash * @param configIpfsHash The new config IPFS hash */ function updateConfig(string calldata configIpfsHash) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.20; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IKeeperRewards} from './IKeeperRewards.sol'; import {IKeeperOracles} from './IKeeperOracles.sol'; /** * @title IKeeperValidators * @author StakeWise * @notice Defines the interface for the Keeper validators */ interface IKeeperValidators is IKeeperOracles, IKeeperRewards { /** * @notice Event emitted on validators approval * @param vault The address of the Vault * @param exitSignaturesIpfsHash The IPFS hash with the validators' exit signatures */ event ValidatorsApproval(address indexed vault, string exitSignaturesIpfsHash); /** * @notice Event emitted on exit signatures update * @param caller The address of the function caller * @param vault The address of the Vault * @param nonce The nonce used for verifying Oracles' signatures * @param exitSignaturesIpfsHash The IPFS hash with the validators' exit signatures */ event ExitSignaturesUpdated( address indexed caller, address indexed vault, uint256 nonce, string exitSignaturesIpfsHash ); /** * @notice Event emitted on validators min oracles number update * @param oracles The new minimum number of oracles required to approve validators */ event ValidatorsMinOraclesUpdated(uint256 oracles); /** * @notice Get nonce for the next vault exit signatures update * @param vault The address of the Vault to get the nonce for * @return The nonce of the Vault for updating signatures */ function exitSignaturesNonces(address vault) external view returns (uint256); /** * @notice Struct for approving registration of one or more validators * @param validatorsRegistryRoot The deposit data root used to verify that oracles approved validators * @param deadline The deadline for submitting the approval * @param validators The concatenation of the validators' public key, signature and deposit data root * @param signatures The concatenation of Oracles' signatures * @param exitSignaturesIpfsHash The IPFS hash with the validators' exit signatures */ struct ApprovalParams { bytes32 validatorsRegistryRoot; uint256 deadline; bytes validators; bytes signatures; string exitSignaturesIpfsHash; } /** * @notice The minimum number of oracles required to update validators * @return The minimum number of oracles */ function validatorsMinOracles() external view returns (uint256); /** * @notice Function for approving validators registration * @param params The parameters for approving validators registration */ function approveValidators(ApprovalParams calldata params) external; /** * @notice Function for updating exit signatures for every hard fork * @param vault The address of the Vault to update signatures for * @param deadline The deadline for submitting signatures update * @param exitSignaturesIpfsHash The IPFS hash with the validators' exit signatures * @param oraclesSignatures The concatenation of Oracles' signatures */ function updateExitSignatures( address vault, uint256 deadline, string calldata exitSignaturesIpfsHash, bytes calldata oraclesSignatures ) external; /** * @notice Function for updating validators min oracles number * @param _validatorsMinOracles The new minimum number of oracles required to approve validators */ function setValidatorsMinOracles(uint256 _validatorsMinOracles) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title IPoolAddressesProvider * @author Aave * @notice Defines the basic interface for a Pool Addresses Provider. */ interface IPoolAddressesProvider { /** * @dev Emitted when the market identifier is updated. * @param oldMarketId The old id of the market * @param newMarketId The new id of the market */ event MarketIdSet(string indexed oldMarketId, string indexed newMarketId); /** * @dev Emitted when the pool is updated. * @param oldAddress The old address of the Pool * @param newAddress The new address of the Pool */ event PoolUpdated(address indexed oldAddress, address indexed newAddress); /** * @dev Emitted when the pool configurator is updated. * @param oldAddress The old address of the PoolConfigurator * @param newAddress The new address of the PoolConfigurator */ event PoolConfiguratorUpdated(address indexed oldAddress, address indexed newAddress); /** * @dev Emitted when the price oracle is updated. * @param oldAddress The old address of the PriceOracle * @param newAddress The new address of the PriceOracle */ event PriceOracleUpdated(address indexed oldAddress, address indexed newAddress); /** * @dev Emitted when the ACL manager is updated. * @param oldAddress The old address of the ACLManager * @param newAddress The new address of the ACLManager */ event ACLManagerUpdated(address indexed oldAddress, address indexed newAddress); /** * @dev Emitted when the ACL admin is updated. * @param oldAddress The old address of the ACLAdmin * @param newAddress The new address of the ACLAdmin */ event ACLAdminUpdated(address indexed oldAddress, address indexed newAddress); /** * @dev Emitted when the price oracle sentinel is updated. * @param oldAddress The old address of the PriceOracleSentinel * @param newAddress The new address of the PriceOracleSentinel */ event PriceOracleSentinelUpdated(address indexed oldAddress, address indexed newAddress); /** * @dev Emitted when the pool data provider is updated. * @param oldAddress The old address of the PoolDataProvider * @param newAddress The new address of the PoolDataProvider */ event PoolDataProviderUpdated(address indexed oldAddress, address indexed newAddress); /** * @dev Emitted when a new proxy is created. * @param id The identifier of the proxy * @param proxyAddress The address of the created proxy contract * @param implementationAddress The address of the implementation contract */ event ProxyCreated( bytes32 indexed id, address indexed proxyAddress, address indexed implementationAddress ); /** * @dev Emitted when a new non-proxied contract address is registered. * @param id The identifier of the contract * @param oldAddress The address of the old contract * @param newAddress The address of the new contract */ event AddressSet(bytes32 indexed id, address indexed oldAddress, address indexed newAddress); /** * @dev Emitted when the implementation of the proxy registered with id is updated * @param id The identifier of the contract * @param proxyAddress The address of the proxy contract * @param oldImplementationAddress The address of the old implementation contract * @param newImplementationAddress The address of the new implementation contract */ event AddressSetAsProxy( bytes32 indexed id, address indexed proxyAddress, address oldImplementationAddress, address indexed newImplementationAddress ); /** * @notice Returns the id of the Aave market to which this contract points to. * @return The market id */ function getMarketId() external view returns (string memory); /** * @notice Associates an id with a specific PoolAddressesProvider. * @dev This can be used to create an onchain registry of PoolAddressesProviders to * identify and validate multiple Aave markets. * @param newMarketId The market id */ function setMarketId(string calldata newMarketId) external; /** * @notice Returns an address by its identifier. * @dev The returned address might be an EOA or a contract, potentially proxied * @dev It returns ZERO if there is no registered address with the given id * @param id The id * @return The address of the registered for the specified id */ function getAddress(bytes32 id) external view returns (address); /** * @notice General function to update the implementation of a proxy registered with * certain `id`. If there is no proxy registered, it will instantiate one and * set as implementation the `newImplementationAddress`. * @dev IMPORTANT Use this function carefully, only for ids that don't have an explicit * setter function, in order to avoid unexpected consequences * @param id The id * @param newImplementationAddress The address of the new implementation */ function setAddressAsProxy(bytes32 id, address newImplementationAddress) external; /** * @notice Sets an address for an id replacing the address saved in the addresses map. * @dev IMPORTANT Use this function carefully, as it will do a hard replacement * @param id The id * @param newAddress The address to set */ function setAddress(bytes32 id, address newAddress) external; /** * @notice Returns the address of the Pool proxy. * @return The Pool proxy address */ function getPool() external view returns (address); /** * @notice Updates the implementation of the Pool, or creates a proxy * setting the new `pool` implementation when the function is called for the first time. * @param newPoolImpl The new Pool implementation */ function setPoolImpl(address newPoolImpl) external; /** * @notice Returns the address of the PoolConfigurator proxy. * @return The PoolConfigurator proxy address */ function getPoolConfigurator() external view returns (address); /** * @notice Updates the implementation of the PoolConfigurator, or creates a proxy * setting the new `PoolConfigurator` implementation when the function is called for the first time. * @param newPoolConfiguratorImpl The new PoolConfigurator implementation */ function setPoolConfiguratorImpl(address newPoolConfiguratorImpl) external; /** * @notice Returns the address of the price oracle. * @return The address of the PriceOracle */ function getPriceOracle() external view returns (address); /** * @notice Updates the address of the price oracle. * @param newPriceOracle The address of the new PriceOracle */ function setPriceOracle(address newPriceOracle) external; /** * @notice Returns the address of the ACL manager. * @return The address of the ACLManager */ function getACLManager() external view returns (address); /** * @notice Updates the address of the ACL manager. * @param newAclManager The address of the new ACLManager */ function setACLManager(address newAclManager) external; /** * @notice Returns the address of the ACL admin. * @return The address of the ACL admin */ function getACLAdmin() external view returns (address); /** * @notice Updates the address of the ACL admin. * @param newAclAdmin The address of the new ACL admin */ function setACLAdmin(address newAclAdmin) external; /** * @notice Returns the address of the price oracle sentinel. * @return The address of the PriceOracleSentinel */ function getPriceOracleSentinel() external view returns (address); /** * @notice Updates the address of the price oracle sentinel. * @param newPriceOracleSentinel The address of the new PriceOracleSentinel */ function setPriceOracleSentinel(address newPriceOracleSentinel) external; /** * @notice Returns the address of the data provider. * @return The address of the DataProvider */ function getPoolDataProvider() external view returns (address); /** * @notice Updates the address of the data provider. * @param newDataProvider The address of the new DataProvider */ function setPoolDataProvider(address newDataProvider) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library DataTypes { /** * This exists specifically to maintain the `getReserveData()` interface, since the new, internal * `ReserveData` struct includes the reserve's `virtualUnderlyingBalance`. */ struct ReserveDataLegacy { //stores the reserve configuration ReserveConfigurationMap configuration; //the liquidity index. Expressed in ray uint128 liquidityIndex; //the current supply rate. Expressed in ray uint128 currentLiquidityRate; //variable borrow index. Expressed in ray uint128 variableBorrowIndex; //the current variable borrow rate. Expressed in ray uint128 currentVariableBorrowRate; // DEPRECATED on v3.2.0 uint128 currentStableBorrowRate; //timestamp of last update uint40 lastUpdateTimestamp; //the id of the reserve. Represents the position in the list of the active reserves uint16 id; //aToken address address aTokenAddress; // DEPRECATED on v3.2.0 address stableDebtTokenAddress; //variableDebtToken address address variableDebtTokenAddress; //address of the interest rate strategy address interestRateStrategyAddress; //the current treasury balance, scaled uint128 accruedToTreasury; //the outstanding unbacked aTokens minted through the bridging feature uint128 unbacked; //the outstanding debt borrowed against this asset in isolation mode uint128 isolationModeTotalDebt; } struct ReserveData { //stores the reserve configuration ReserveConfigurationMap configuration; //the liquidity index. Expressed in ray uint128 liquidityIndex; //the current supply rate. Expressed in ray uint128 currentLiquidityRate; //variable borrow index. Expressed in ray uint128 variableBorrowIndex; //the current variable borrow rate. Expressed in ray uint128 currentVariableBorrowRate; // DEPRECATED on v3.2.0 uint128 __deprecatedStableBorrowRate; //timestamp of last update uint40 lastUpdateTimestamp; //the id of the reserve. Represents the position in the list of the active reserves uint16 id; //timestamp until when liquidations are not allowed on the reserve, if set to past liquidations will be allowed uint40 liquidationGracePeriodUntil; //aToken address address aTokenAddress; // DEPRECATED on v3.2.0 address __deprecatedStableDebtTokenAddress; //variableDebtToken address address variableDebtTokenAddress; //address of the interest rate strategy address interestRateStrategyAddress; //the current treasury balance, scaled uint128 accruedToTreasury; //the outstanding unbacked aTokens minted through the bridging feature uint128 unbacked; //the outstanding debt borrowed against this asset in isolation mode uint128 isolationModeTotalDebt; //the amount of underlying accounted for by the protocol uint128 virtualUnderlyingBalance; } struct ReserveConfigurationMap { //bit 0-15: LTV //bit 16-31: Liq. threshold //bit 32-47: Liq. bonus //bit 48-55: Decimals //bit 56: reserve is active //bit 57: reserve is frozen //bit 58: borrowing is enabled //bit 59: DEPRECATED: stable rate borrowing enabled //bit 60: asset is paused //bit 61: borrowing in isolation mode is enabled //bit 62: siloed borrowing enabled //bit 63: flashloaning enabled //bit 64-79: reserve factor //bit 80-115: borrow cap in whole tokens, borrowCap == 0 => no cap //bit 116-151: supply cap in whole tokens, supplyCap == 0 => no cap //bit 152-167: liquidation protocol fee //bit 168-175: DEPRECATED: eMode category //bit 176-211: unbacked mint cap in whole tokens, unbackedMintCap == 0 => minting disabled //bit 212-251: debt ceiling for isolation mode with (ReserveConfiguration::DEBT_CEILING_DECIMALS) decimals //bit 252: virtual accounting is enabled for the reserve //bit 253-255 unused uint256 data; } struct UserConfigurationMap { /** * @dev Bitmap of the users collaterals and borrows. It is divided in pairs of bits, one pair per asset. * The first bit indicates if an asset is used as collateral by the user, the second whether an * asset is borrowed by the user. */ uint256 data; } // DEPRECATED: kept for backwards compatibility, might be removed in a future version struct EModeCategoryLegacy { // each eMode category has a custom ltv and liquidation threshold uint16 ltv; uint16 liquidationThreshold; uint16 liquidationBonus; // DEPRECATED address priceSource; string label; } struct CollateralConfig { uint16 ltv; uint16 liquidationThreshold; uint16 liquidationBonus; } struct EModeCategoryBaseConfiguration { uint16 ltv; uint16 liquidationThreshold; uint16 liquidationBonus; string label; } struct EModeCategory { // each eMode category has a custom ltv and liquidation threshold uint16 ltv; uint16 liquidationThreshold; uint16 liquidationBonus; uint128 collateralBitmap; string label; uint128 borrowableBitmap; } enum InterestRateMode { NONE, __DEPRECATED, VARIABLE } struct ReserveCache { uint256 currScaledVariableDebt; uint256 nextScaledVariableDebt; uint256 currLiquidityIndex; uint256 nextLiquidityIndex; uint256 currVariableBorrowIndex; uint256 nextVariableBorrowIndex; uint256 currLiquidityRate; uint256 currVariableBorrowRate; uint256 reserveFactor; ReserveConfigurationMap reserveConfiguration; address aTokenAddress; address variableDebtTokenAddress; uint40 reserveLastUpdateTimestamp; } struct ExecuteLiquidationCallParams { uint256 reservesCount; uint256 debtToCover; address collateralAsset; address debtAsset; address user; bool receiveAToken; address priceOracle; uint8 userEModeCategory; address priceOracleSentinel; } struct ExecuteSupplyParams { address asset; uint256 amount; address onBehalfOf; uint16 referralCode; } struct ExecuteBorrowParams { address asset; address user; address onBehalfOf; uint256 amount; InterestRateMode interestRateMode; uint16 referralCode; bool releaseUnderlying; uint256 reservesCount; address oracle; uint8 userEModeCategory; address priceOracleSentinel; } struct ExecuteRepayParams { address asset; uint256 amount; InterestRateMode interestRateMode; address onBehalfOf; bool useATokens; } struct ExecuteWithdrawParams { address asset; uint256 amount; address to; uint256 reservesCount; address oracle; uint8 userEModeCategory; } struct ExecuteSetUserEModeParams { uint256 reservesCount; address oracle; uint8 categoryId; } struct FinalizeTransferParams { address asset; address from; address to; uint256 amount; uint256 balanceFromBefore; uint256 balanceToBefore; uint256 reservesCount; address oracle; uint8 fromEModeCategory; } struct FlashloanParams { address receiverAddress; address[] assets; uint256[] amounts; uint256[] interestRateModes; address onBehalfOf; bytes params; uint16 referralCode; uint256 flashLoanPremiumToProtocol; uint256 flashLoanPremiumTotal; uint256 reservesCount; address addressesProvider; address pool; uint8 userEModeCategory; bool isAuthorizedFlashBorrower; } struct FlashloanSimpleParams { address receiverAddress; address asset; uint256 amount; bytes params; uint16 referralCode; uint256 flashLoanPremiumToProtocol; uint256 flashLoanPremiumTotal; } struct FlashLoanRepaymentParams { uint256 amount; uint256 totalPremium; uint256 flashLoanPremiumToProtocol; address asset; address receiverAddress; uint16 referralCode; } struct CalculateUserAccountDataParams { UserConfigurationMap userConfig; uint256 reservesCount; address user; address oracle; uint8 userEModeCategory; } struct ValidateBorrowParams { ReserveCache reserveCache; UserConfigurationMap userConfig; address asset; address userAddress; uint256 amount; InterestRateMode interestRateMode; uint256 reservesCount; address oracle; uint8 userEModeCategory; address priceOracleSentinel; bool isolationModeActive; address isolationModeCollateralAddress; uint256 isolationModeDebtCeiling; } struct ValidateLiquidationCallParams { ReserveCache debtReserveCache; uint256 totalDebt; uint256 healthFactor; address priceOracleSentinel; } struct CalculateInterestRatesParams { uint256 unbacked; uint256 liquidityAdded; uint256 liquidityTaken; uint256 totalDebt; uint256 reserveFactor; address reserve; bool usingVirtualBalance; uint256 virtualUnderlyingBalance; } struct InitReserveParams { address asset; address aTokenAddress; address variableDebtAddress; address interestRateStrategyAddress; uint16 reservesCount; uint16 maxNumberReserves; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol) pragma solidity ^0.8.20; interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); }
{ "remappings": [ "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@stakewise-core/=lib/v3-core/contracts/", "@aave-core/=lib/aave-v3-origin/src/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "aave-v3-core/=lib/aave-v3-origin/src/core/", "aave-v3-origin/=lib/aave-v3-origin/", "aave-v3-periphery/=lib/aave-v3-origin/src/periphery/", "ds-test/=lib/aave-v3-origin/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "forge-gas-snapshot/=lib/forge-gas-snapshot/src/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/", "solidity-stringutils/=lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/", "solidity-utils/=lib/aave-v3-origin/lib/solidity-utils/", "v3-core/=lib/v3-core/contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": true, "libraries": {} }
[{"inputs":[{"internalType":"address","name":"osToken","type":"address"},{"internalType":"address","name":"assetToken","type":"address"},{"internalType":"address","name":"osTokenVaultController","type":"address"},{"internalType":"address","name":"osTokenConfig","type":"address"},{"internalType":"address","name":"osTokenFlashLoans","type":"address"},{"internalType":"address","name":"osTokenVaultEscrow","type":"address"},{"internalType":"address","name":"strategiesRegistry","type":"address"},{"internalType":"address","name":"strategyProxyImplementation","type":"address"},{"internalType":"address","name":"balancerVault","type":"address"},{"internalType":"address","name":"aavePool","type":"address"},{"internalType":"address","name":"aaveOsToken","type":"address"},{"internalType":"address","name":"aaveVarDebtAssetToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessDenied","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"ERC1167FailedCreateClone","type":"error"},{"inputs":[],"name":"ExitQueueNotEntered","type":"error"},{"inputs":[],"name":"ExitRequestNotProcessed","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidAssets","type":"error"},{"inputs":[],"name":"InvalidBalancerPoolId","type":"error"},{"inputs":[],"name":"InvalidExitQueuePercent","type":"error"},{"inputs":[],"name":"InvalidExitQueueTicket","type":"error"},{"inputs":[],"name":"InvalidFlashloanAction","type":"error"},{"inputs":[],"name":"InvalidMaxSlippagePercent","type":"error"},{"inputs":[],"name":"InvalidPosition","type":"error"},{"inputs":[],"name":"InvalidShares","type":"error"},{"inputs":[],"name":"InvalidVault","type":"error"},{"inputs":[],"name":"MathOverflowedMulDiv","type":"error"},{"inputs":[],"name":"NotHarvested","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"UpgradeFailed","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"osTokenShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"leverageOsTokenShares","type":"uint256"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"positionTicket","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"osTokenShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"positionPercent","type":"uint256"}],"name":"ExitQueueEntered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"osTokenShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"ExitedAssetsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"osTokenShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"LendingAssetsRescued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"strategyProxyId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"proxy","type":"address"}],"name":"StrategyProxyCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"strategy","type":"address"}],"name":"StrategyProxyUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"osTokenShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"VaultAssetsRescued","type":"event"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"user","type":"address"},{"components":[{"internalType":"uint256","name":"positionTicket","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"exitQueueIndex","type":"uint256"}],"internalType":"struct ILeverageStrategy.ExitPosition","name":"exitPosition","type":"tuple"}],"name":"claimExitedAssets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"osTokenShares","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"positionPercent","type":"uint256"}],"name":"enterExitQueue","outputs":[{"internalType":"uint256","name":"positionTicket","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"user","type":"address"}],"name":"forceEnterExitQueue","outputs":[{"internalType":"uint256","name":"positionTicket","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"user","type":"address"}],"name":"getStrategyProxy","outputs":[{"internalType":"address","name":"proxy","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxy","type":"address"}],"name":"isStrategyProxyExiting","outputs":[{"internalType":"bool","name":"isExiting","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"osTokenShares","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":"osTokenShares","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"receiveFlashLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"uint256","name":"maxSlippagePercent","type":"uint256"}],"name":"rescueLendingAssets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"components":[{"internalType":"uint256","name":"positionTicket","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"exitQueueIndex","type":"uint256"}],"internalType":"struct ILeverageStrategy.ExitPosition","name":"exitPosition","type":"tuple"}],"name":"rescueVaultAssets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"strategyId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"components":[{"internalType":"bytes32","name":"rewardsRoot","type":"bytes32"},{"internalType":"int160","name":"reward","type":"int160"},{"internalType":"uint160","name":"unlockedMevReward","type":"uint160"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"internalType":"struct IKeeperRewards.HarvestParams","name":"harvestParams","type":"tuple"}],"name":"updateVaultState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"upgradeProxy","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
610200346102f857601f61484f38819003918201601f19168301916001600160401b038311848410176102fc57808492610180946040528339810103126102f85761004981610310565b9061005660208201610310565b61006260408301610310565b61006e60608401610310565b61007a60808501610310565b61008660a08601610310565b61009260c08701610310565b9161009f60e08801610310565b936100ad6101008901610310565b956100bb6101208a01610310565b976100d66101606100cf6101408d01610310565b9b01610310565b6001600160a01b039b8c1661016052908b1661018052908a1660c05290891660e052908816610100529087166101205290861660805260a091909152908416610140529083166101a0529082166101c052166101e05260405161452a908161032582396080518181816105670152818161160d01528181612a07015281816130210152818161343201528181613a050152613e5f015260a0518181816116710152613eea015260c05181818161018a015281816111ea015281816132e7015281816137460152818161383801528181613af80152613bd0015260e051818181613c8401526140f60152610100518181816101f60152818161108f0152818161145a015281816119cf01528181611cb70152818161324a0152818161355501526138b301526101205181818161194201528181611c2a015261433b0152610140518161313501526101605181818161082201528181610fd3015281816120640152818161228c0152818161250c0152818161281001528181612c0c01528181612deb01528181612fe6015281816133f10152818161366f015281816137a50152614295015261018051818181611f92015281816122f9015281816125a601528181612acc01528181612ba8015281816130a3015281816134e30152818161422901526143e201526101a051818181611fce015281816120a00152818161245e01528181612879015261298e01526101c05181611ed601526101e05181611f410152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b03821682036102f85756fe60806040526004361015610011575f80fd5b5f3560e01c80632a5a0d7e146100f45780633ab7f631146100ef5780633b0c6d67146100ea57806347e7ef24146100e5578063492f4e18146100e057806374474d28146100db5780637ac2ff7b146100d65780639ab02a0f146100d1578063a6ed20f0146100cc578063ac9650d8146100c7578063b580e046146100c2578063d694dd24146100bd578063e28e20e4146100b85763e368fdb7146100b3575f80fd5b610cf6565b610cb4565b610af8565b610ac4565b610a54565b6109a6565b610909565b610762565b6104fa565b6104c0565b61048d565b61044e565b61033c565b61010e565b6001600160a01b0381160361010a57565b5f80fd5b3461010a57606036600319011261010a5760043561012b816100f9565b604435602435670de0b6b3a764000082101561032d5761014b33846115cb565b9161015583611eac565b508215908115610323575b50610314576040516363737ac960e11b815260048101839052906020826024816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa9081156102da576101cf925f926102df575b506101c99082612147565b90610e5c565b60408051600360208201526001600160a01b038581169282019290925260608101939093527f0000000000000000000000000000000000000000000000000000000000000000169161022e81608081015b03601f1981018352826108ad565b823b1561010a57610258925f9283604051809681958294635296a43160e01b845260048401610e8c565b03925af180156102da576102bb927fb7972ed828b18abfbec411ed2ee61877a59573dd54d2145a70099fa408f737a992610299926102c0575b50339061226d565b60408051928352602083019190915233946001600160a01b0316938291820190565b0390a3005b806102ce5f6102d4936108ad565b806104b6565b5f610291565b610e2a565b6101c99192506103069060203d60201161030d575b6102fe81836108ad565b810190610e1b565b91906101be565b503d6102f4565b6318374fd160e21b5f5260045ffd5b905082115f610160565b63edbc804d60e01b5f5260045ffd5b3461010a57604036600319011261010a57600435610359816100f9565b6024356001600160401b03811161010a5780360391608060031984011261010a576001600160a01b031690813b1561010a5760405192631a7ff55360e01b8452602060048501528160040135602485015260248201358060130b80910361010a57604485015260448201356103cd816100f9565b6001600160a01b0316606485810191909152820135906022190181121561010a5701602460048201359101916001600160401b03821161010a578160051b3603831361010a57835f8161042e829682966080608485015260a4840191610ea3565b03925af180156102da5761043e57005b806102ce5f61044c936108ad565b005b3461010a57602036600319011261010a5760043561046b816100f9565b60018060a01b03165f525f602052602060ff60405f2054166040519015158152f35b3461010a57604036600319011261010a5761044c6004356104ad816100f9565b60243590610f49565b5f91031261010a57565b3461010a575f36600319011261010a5760206040517f8b74cefe9f33d72ccd3521e6d331272921607e547c75c914c2c56cfdad9defed8152f35b3461010a57602036600319011261010a57600435610517816100f9565b61052133826115cb565b6001600160a01b0381165f908152602081905260409020610544905b5460ff1690565b61074857604051633933604760e11b81526001600160a01b0382811660048301527f00000000000000000000000000000000000000000000000000000000000000001690602081602481855afa9081156102da575f91610719575b501561070a575f6105ce916105b2611333565b90604051808095819463682d2ff360e01b83526004830161135a565b03915afa9081156102da575f916106e8575b508051156106d9576105fe8160208061060a94518301019101611391565b6001600160a01b031690565b906001600160a01b03821680159081156106cf575b506106c0576001600160a01b0316803b1561010a5760405163f2fde38b60e01b81526001600160a01b0383166004820152905f908290602490829084905af180156102da576106ac575b506040516001600160a01b0391821681523392909116907f746871013d9225e5b11b13b9256515b47fa5378b085f1ba9b07b5f5112480ccf9080602081016102bb565b806102ce5f6106ba936108ad565b5f610669565b638c8728c760e01b5f5260045ffd5b905030145f61061f565b6355299b4960e01b5f5260045ffd5b61070491503d805f833e6106fc81836108ad565b810190610ec7565b5f6105e0565b634ca8886760e01b5f5260045ffd5b61073b915060203d602011610741575b61073381836108ad565b810190611307565b5f61059f565b503d610729565b630e3d8e8d60e11b5f5260045ffd5b60ff81160361010a57565b3461010a5760c036600319011261010a575f80610853600435610784816100f9565b60243561080b604435916102206064359461079e86610757565b6084356107af60a435923390612634565b5060405163d505accf60e01b60208201523360248201526001600160a01b03821660448201526064810195909552608485019690965260ff90961660a484015260c483019590955260e482019490945291928290610104820190565b604051631cff79cd60e01b815294859384928391907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660048401610f27565b03926001600160a01b03165af161086657005b61044c903d805f833e6106fc81836108ad565b634e487b7160e01b5f52604160045260245ffd5b606081019081106001600160401b038211176108a857604052565b610879565b90601f801991011681019081106001600160401b038211176108a857604052565b604051906108dd60c0836108ad565b565b604051906108dd6080836108ad565b6001600160401b0381116108a857601f01601f191660200190565b3461010a57604036600319011261010a576024356004356001600160401b03821161010a573660238301121561010a57816004013590610948826108ee565b9161095660405193846108ad565b808352366024828601011161010a576020815f92602461044c97018387013784010152611458565b604090600319011261010a57600435610996816100f9565b906024356109a3816100f9565b90565b3461010a5760206109bf6109b93661097e565b906115cb565b6040516001600160a01b039091168152f35b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b602081016020825282518091526040820191602060408360051b8301019401925f915b838310610a2757505050505090565b9091929394602080610a45600193603f1986820301875289516109d1565b97019301930191939290610a18565b3461010a57602036600319011261010a576004356001600160401b03811161010a573660238201121561010a578060040135906001600160401b03821161010a573660248360051b8301011161010a57610ac0916024610ab49201611818565b604051918291826109f5565b0390f35b3461010a57608036600319011261010a57600435610ae1816100f9565b606036602319011261010a57602461044c916118e5565b3461010a57604036600319011261010a57600435610b15816100f9565b6024359081158015610ca3575b610c9457610b3033826115cb565b90610b4d61053d8360018060a01b03165f525f60205260405f2090565b61074857610b6683610b5f8484612666565b9050612147565b8015610c8557604051634933c21560e11b602082015260248101829052610bb1905f90610b968160448101610220565b60405180938192631cff79cd60e01b83528760048401610f27565b0381836001600160a01b0389165af180156102da57602095610c31610c24610c0e610c60947f91cd78d9994c342f6ef7d71956ecef9721d78270434de929d6d35a762ef3d041965f91610c6b575b508a8082518301019101610e1b565b9760018060a01b03165f525f60205260405f2090565b805460ff19166001179055565b6040805187815242602082015290810194909452606084015233936001600160a01b0316929081906080820190565b0390a3604051908152f35b610c7f91503d805f833e6106fc81836108ad565b5f610bff565b63673f032f60e11b5f5260045ffd5b6326bf739360e21b5f5260045ffd5b50670de0b6b3a76400008211610b22565b3461010a5760a036600319011261010a57600435610cd1816100f9565b60243590610cde826100f9565b606036604319011261010a5761044c91604491611bd1565b3461010a57610d043661097e565b90610d0f82826139f8565b1561070a57610d1e82826115cb565b90610d3b61053d8360018060a01b03165f525f60205260405f2090565b61074857610d55670de0b6b3a7640000610b5f8484612666565b8015610c8557604051634933c21560e11b602082015260248101829052610d85905f90610b968160448101610220565b0381836001600160a01b0389165af180156102da57602095610de7610c24610c0e670de0b6b3a7640000947f91cd78d9994c342f6ef7d71956ecef9721d78270434de929d6d35a762ef3d041965f91610c6b57508a8082518301019101610e1b565b604080518781524260208201529081019490945260608401919091526001600160a01b039081169316918060808101610c60565b9081602091031261010a575190565b6040513d5f823e3d90fd5b634e487b7160e01b5f52601160045260245ffd5b9060028201809211610e5757565b610e35565b91908201809211610e5757565b634e487b7160e01b5f52602160045260245ffd5b60041115610e8757565b610e69565b6040906109a39392815281602082015201906109d1565b81835290916001600160fb1b03831161010a5760209260051b809284830137010190565b60208183031261010a578051906001600160401b03821161010a570181601f8201121561010a57602081519101610efd826108ee565b92610f0b60405194856108ad565b8284528282011161010a57815f926020928386015e8301015290565b6001600160a01b0390911681526040602082018190526109a3929101906109d1565b9080156112f857610f5a3383612634565b506001600160a01b0381165f908152602081905260409020610f7b9061053d565b610748576040516323b872dd60e01b60208201523360248201526001600160a01b038216604482015260648101839052611004905f90610fbe8160848101610220565b604051631cff79cd60e01b81529283918291907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660048401610f27565b0381836001600160a01b0387165af180156102da576112e0575b506110298184612666565b908361103484611eac565b9093829315908115916112d6575b5080156112cd575b80156112c4575b6111ac575b5050611063915084612eb7565b801561116657604080515f60208201526001600160a01b038681169282019290925292811660608401527f0000000000000000000000000000000000000000000000000000000000000000166110c683608081015b03601f1981018552846108ad565b803b1561010a57604051635296a43160e01b8152925f9184918290849082906110f3908860048401610e8c565b03925af19081156102da577ff5681f9d0db1b911ac18ee83d515a1cf1051853a9eae418316a2fdf7dea427c59261114d92611152575b5060408051948552602085019190915233946001600160a01b031693918291820190565b0390a3565b806102ce5f611160936108ad565b5f611129565b5050604080519182525f602083015233926001600160a01b0316917ff5681f9d0db1b911ac18ee83d515a1cf1051853a9eae418316a2fdf7dea427c5918190810161114d565b6111e69250816111c7916111c2602094886127f6565b610e5c565b604051809381926303d1689d60e11b8352600483019190602083019252565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa80156102da57611234915f916112a5575b5061122e61296a565b90612147565b8082101561125d5761106391611256910361124f8185612ab2565b8386612b5b565b835f611056565b5050604080519283525f602084015233936001600160a01b0316927ff5681f9d0db1b911ac18ee83d515a1cf1051853a9eae418316a2fdf7dea427c59250908190810161114d565b6112be915060203d60201161030d576102fe81836108ad565b5f611225565b50801515611051565b5083151561104a565b905015155f611042565b6112f3903d805f833e6106fc81836108ad565b61101e565b636edcc52360e01b5f5260045ffd5b9081602091031261010a5751801515810361010a5790565b6040519061132e6020836108ad565b5f8252565b604051906113426040836108ad565b600982526875706772616465563160b81b6020830152565b9060406109a3927f8b74cefe9f33d72ccd3521e6d331272921607e547c75c914c2c56cfdad9defed815281602082015201906109d1565b9081602091031261010a57516109a3816100f9565b5190600482101561010a57565b9081602091031261010a576109a3906113a6565b9081606091031261010a576113db816113a6565b91604060208301516113ec816100f9565b92015190565b919082608091031261010a57611407826113a6565b916020810151611416816100f9565b91606060408301516113ec816100f9565b9081606091031261010a5761143b816113a6565b916040602083015161144c816100f9565b9201516109a3816100f9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361070a5781519161149d602080830194830101846113b3565b6114a681610e7d565b806114d357506108dd926020826114c09351010190611427565b6001600160a01b039081169250166137a3565b6114dc81610e7d565b6001810361150d57506108dd926020826114f993510101906113f2565b92506001600160a01b039081169116613665565b61151681610e7d565b6002810361154757506108dd9260208261153393510101906113f2565b92506001600160a01b0390811691166133e8565b80611553600392610e7d565b0361157c576108dd9260208261156c93510101906113c7565b91506001600160a01b0316612fe3565b63adc9f0f960e01b5f5260045ffd5b7f8b74cefe9f33d72ccd3521e6d331272921607e547c75c914c2c56cfdad9defed81526001600160a01b0391821660208201529116604082015260600190565b906115e46102209160405192839160208301958661158b565b5190206040516338e1dd3160e21b81526004810182905291906020836024816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa9283156102da575f936116cc575b506001600160a01b038316156116505750565b6040513060388201526f5af43d82803e903d91602b57fd5bf3ff60248201527f00000000000000000000000000000000000000000000000000000000000000006014820152733d602d80600a3d3981f3363d3d373d3d3d363d73815260588101919091526037600c820120607882015260556043909101209150565b6116ef91935060203d6020116116f6575b6116e781836108ad565b810190611391565b915f61163d565b503d6116dd565b6001600160401b0381116108a85760051b60200190565b9061171e826116fd565b61172b60405191826108ad565b828152809261173c601f19916116fd565b01905f5b82811061174c57505050565b806060602080938501015201611740565b634e487b7160e01b5f52603260045260245ffd5b91908110156117b25760051b81013590601e198136030182121561010a5701908135916001600160401b03831161010a57602001823603811361010a579190565b61175d565b908092918237015f815290565b3d156117ee573d906117d5826108ee565b916117e360405193846108ad565b82523d5f602084013e565b606090565b9060206109a39281815201906109d1565b80518210156117b25760209160051b010190565b91909161182483611714565b925f5b81811061183357505050565b5f80611840838587611771565b90611850604051809381936117b7565b0390305af461185d6117c4565b901561188357906001916118718288611804565b5261187c8187611804565b5001611827565b604481511061010a576118a58160248060046118bd9501518301019101610ec7565b60405162461bcd60e51b8152918291600483016117f3565b0390fd5b9081606091031261010a5780516118d7816100f9565b916040602083015192015190565b906118f033836115cb565b9061191461191061053d8460018060a01b03165f525f60205260405f2090565b1590565b611bc257604051633adbb5af60e01b81526001600160a01b03848116600483015282356024830181905292907f000000000000000000000000000000000000000000000000000000000000000016606083604481845afa9283156102da575f80915f95611b8d575b506001600160a01b03878116911603611b7e576001841115611b185715611aa2575b505060408051600260208201526001600160a01b0386811692820192909252848216606082015260808101939093527f000000000000000000000000000000000000000000000000000000000000000016916119fd8160a08101610220565b823b1561010a57611a27925f9283604051809681958294635296a43160e01b845260048401610e8c565b03925af180156102da5761114d927f0751a391154a0437ff29e885c1cfbd7f0e63201c8fc308298cee3ba65ef470579261029992611a8e575b506001600160a01b0381165f908152602081905260409020611a87905b805460ff19169055565b339061226d565b806102ce5f611a9c936108ad565b5f611a60565b60408201359160200135813b1561010a576040516398e99bb760e01b81526001600160a01b038816600482015260248101869052604481019190915260648101929092525f908290608490829084905af180156102da57611b04575b8061199e565b806102ce5f611b12936108ad565b5f611afe565b5050505050611a7d611b399160018060a01b03165f525f60205260405f2090565b604080515f808252602082015233926001600160a01b0316917f0751a391154a0437ff29e885c1cfbd7f0e63201c8fc308298cee3ba65ef4705791908190810161114d565b63154a26f760e21b5f5260045ffd5b915050611bb391935060603d606011611bbb575b611bab81836108ad565b8101906118c1565b93915f61197c565b503d611ba1565b63171a12d760e21b5f5260045ffd5b91611bdc82846115cb565b91611bfc61191061053d8560018060a01b03165f525f60205260405f2090565b611bc257604051633adbb5af60e01b81526001600160a01b03858116600483015283356024830181905293907f000000000000000000000000000000000000000000000000000000000000000016606083604481845afa9283156102da575f80915f95611e87575b506001600160a01b03888116911603611b7e576001841115611e1c5715611da6575b505060408051600160208201526001600160a01b0387811692820192909252858216606082015260808101949094527f00000000000000000000000000000000000000000000000000000000000000001692611ce58160a08101610220565b833b1561010a57611d0f935f9283604051809781958294635296a43160e01b845260048401610e8c565b03925af19081156102da577f0692d4883b7fdb846537c159a4f16ab7f36fd8be83e2b46f05f66e563e01286e92611a7d92611d92575b50611d6b611d53828661226d565b93909560018060a01b03165f525f60205260405f2090565b6040805194855260208501929092526001600160a01b03908116941692908190810161114d565b806102ce5f611da0936108ad565b5f611d45565b60408201359160200135813b1561010a576040516398e99bb760e01b81526001600160a01b038916600482015260248101879052604481019190915260648101929092525f908290608490829084905af180156102da57611e08575b80611c86565b806102ce5f611e16936108ad565b5f611e02565b5050505091611e3f9150611a7d9060018060a01b03165f525f60205260405f2090565b604080515f80825260208201526001600160a01b0392831693909216917f0692d4883b7fdb846537c159a4f16ab7f36fd8be83e2b46f05f66e563e01286e918190810161114d565b915050611ea491935060603d606011611bbb57611bab81836108ad565b93915f611c64565b604051630ed1279f60e11b81526001600160a01b03821660048201529091602082806024810103817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9182156102da575f92612108575b508180612055575b50604051630ed1279f60e11b81526001600160a01b03909316600484015260208380602481015b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9283156102da575f93612034575b508280611f835750565b60405163386497fd60e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166004820152919350602082806024810103817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156102da57612010925f92612013575b50613d2e565b91565b61202d91925060203d60201161030d576102fe81836108ad565b905f61200a565b61204e91935060203d60201161030d576102fe81836108ad565b915f611f79565b60405163d15e005360e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166004820152939250602084806024810103817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9384156102da57611f3d946020926120e8925f926120f05750613d2e565b929350611f16565b61202d919250843d861161030d576102fe81836108ad565b61212291925060203d60201161030d576102fe81836108ad565b905f611f0e565b8115612133570490565b634e487b7160e01b5f52601260045260245ffd5b808202905f19838209908280831092039180830392146121c05781670de0b6b3a764000011156121b1577faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac1066993670de0b6b3a7640000910990828211900360ee1b910360121c170290565b63227bc15360e01b5f5260045ffd5b50670de0b6b3a76400009250500490565b90670de0b6b3a76400008202905f19670de0b6b3a764000084099282808510940393808503941461226157838211156121b157670de0b6b3a7640000829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b50906109a39250612129565b6040516370a0823160e01b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016939190602081602481885afa9081156102da575f916123ff575b50809481612366575b50506040516370a0823160e01b81526001600160a01b0382166004820152602081806024810103817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156102da575f91612347575b5080938161233e57505050565b6108dd92613d6a565b612360915060203d60201161030d576102fe81836108ad565b5f612331565b60405163a9059cbb60e01b60208201526001600160a01b038616602482015260448101929092526123c5915f916123aa82606481015b03601f1981018452836108ad565b604051631cff79cd60e01b8152938492839260048401610f27565b0381836001600160a01b0387165af180156102da576123e5575b806122cf565b6123f8903d805f833e6106fc81836108ad565b505f6123df565b612418915060203d60201161030d576102fe81836108ad565b5f6122c6565b600161242991613e34565b90918183811561262e5750506040516328530a4760e01b6020820152600160248201526124ab906001600160a01b03858116917f0000000000000000000000000000000000000000000000000000000000000000909116905f906124908160448101610220565b60405180958192631cff79cd60e01b83528560048401610f27565b038183865af19283156102da5761253d93612616575b5060405163095ea7b360e01b60208201526001600160a01b03821660248201525f1960448201525f906124f78160648101610220565b604051631cff79cd60e01b81529485918291907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660048401610f27565b038183865af19182156102da5761022061258f6125d7935f9687966125fe575b5060405163095ea7b360e01b60208201526001600160a01b0390911660248201525f1960448201529182906064820190565b604051631cff79cd60e01b815294859384928391907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660048401610f27565b03925af180156102da576125e85750565b6125fb903d805f833e6106fc81836108ad565b50565b612611903d8089833e6106fc81836108ad565b61255d565b612629903d805f833e6106fc81836108ad565b6124c1565b93509150565b9061242991613e34565b51906001600160801b038216820361010a57565b9081602091031261010a576109a39061263e565b604051630e56821560e31b81525f9392916001600160a01b031690602081600481855afa9081156102da575f916127d7575b506127c85760405163f04da65b60e01b81526001600160a01b0383166004820152602081602481855afa9081156102da575f916127a9575b508061274c575b50604051632764b59160e11b81526001600160a01b03909216600483015260209082908180602481015b03915afa80156102da576001600160801b03915f9161271f57501690565b612741915060203d602011612745575b61273981836108ad565b810190612652565b1690565b503d61272f565b6040516303d1689d60e11b81526004810191909152909350602081602481875afa9182156102da57612701926020925f9161278c575b50949150916126d7565b6127a39150833d851161030d576102fe81836108ad565b5f612782565b6127c2915060203d60201161030d576102fe81836108ad565b5f6126d0565b63e775715160e01b5f5260045ffd5b6127f0915060203d6020116107415761073381836108ad565b5f612698565b60405163617ba03760e01b60208201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482019390935291811660648301525f608483018190529182916128aa916128628160a48101610220565b604051631cff79cd60e01b815294859384928391907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660048401610f27565b03926001600160a01b03165af180156102da576125e85750565b519061ffff8216820361010a57565b9081606091031261010a5761291160408051926128ef8461088d565b6128f8816128c4565b8452612906602082016128c4565b6020850152016128c4565b604082015290565b90655af3107a4000820291808304655af3107a40001490151715610e5757565b604051906129486040836108ad565b60138252721b585e109bdc9c9bddd31d1d94195c98d95b9d606a1b6020830152565b60405163b286f46760e01b8152600160048201526060816024816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa80156102da576129d16129d8916129dd935f91612a83575b505161ffff1690565b61ffff1690565b612919565b612a035f6129e9612939565b6040518093819263682d2ff360e01b83526004830161135a565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156102da575f91612a69575b5080518015612a645781602080612a5e936109a3969501019101610e1b565b9061408b565b505090565b612a7d91503d805f833e6106fc81836108ad565b5f612a3f565b612aa5915060603d606011612aab575b612a9d81836108ad565b8101906128d3565b5f6129c8565b503d612a93565b60405163a415bcad60e01b60208201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301526044820193909352600260648201525f6084820181905292821660a482015282916128aa916128628160c48101610220565b939291612b499060409260018060a01b031686526060602087015260608601906109d1565b930152565b91908203918211610e5757565b604051632e1a7d4d60e01b6020820152602481018490526001600160a01b03831693919290612bd9905f90612b938160448101610220565b604051631cff79cd60e01b81529283918291907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660048401610f27565b038183895af180156102da57612d67575b506040516370a0823160e01b81526001600160a01b03828116600483015290947f00000000000000000000000000000000000000000000000000000000000000009091169290602086602481875afa9485156102da57612ca9965f96612d40575b50604051631b7f2ce960e11b60208201526001600160a01b03851660248201525f1960448201525f606482018190529392918490612c8c83608481016110b8565b60405163fa4bb79d60e01b8152998a958694859360048501612b24565b03925af19182156102da57612cee94602093612d28575b506040516370a0823160e01b81526001600160a01b0390921660048301529093849190829081906024820190565b03915afa80156102da576109a3925f91612d09575b50612b4e565b612d22915060203d60201161030d576102fe81836108ad565b5f612d03565b612d3b903d805f833e6106fc81836108ad565b612cc0565b5f9392919650612d5e9060203d60201161030d576102fe81836108ad565b95909192612c4b565b612d7a903d805f833e6106fc81836108ad565b612bea565b604051632e1a7d4d60e01b6020820152602481018490529093926001600160a01b0383169291612db8905f90612b938160448101610220565b038183885af180156102da57612e9f575b506040516370a0823160e01b81526001600160a01b03838116600483015290957f00000000000000000000000000000000000000000000000000000000000000009091169390602087602481885afa9586156102da57612ca9975f97612e6c575b50604051631b7f2ce960e11b60208201526001600160a01b038616602482015260448101919091525f606482018190529392918490612c8c83608481016110b8565b6110b89197505f949392612c8c612e92879360203d60201161030d576102fe81836108ad565b9993505092939450612e2a565b612eb2903d805f833e6106fc81836108ad565b612dc9565b612ec3612ecb916140cd565b61122e61296a565b670de0b6b3a764000003670de0b6b3a76400008111610e5757612eee90826121d1565b908103908111610e575790565b60405190612f0a6040836108ad565b600e82526d18985b185b98d95c941bdbdb125960921b6020830152565b909194939260e08252825160e083015260208301516002811015610e875761010083015260408301516001600160a01b03908116610120840152606084015116610140830152608083015161016083015260a09092015160c061018083018190529290612fda90612f9d906101a08501906109d1565b9660208401906060809160018060a01b03815116845260208101511515602085015260018060a01b03604082015116604085015201511515910152565b60a08201520152565b917f00000000000000000000000000000000000000000000000000000000000000009261301182828661415d565b61301d5f6129e9612efb565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156102da575f916133a5575b50805115613396578060208061307493518301019101610e1b565b6001600160a01b03909416936130886108ce565b908152600160208201526001600160a01b03851660408201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660608201528360808201526130de61131f565b60a08201526001600160a01b038216936131956130f96108df565b6001600160a01b0385168152925f60208501526001600160a01b03871660408501525f6060850181905260405163095ea7b360e01b60208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166024820181905260448201899052919061317a8160648101610220565b60405180958192631cff79cd60e01b83528d60048401610f27565b0381838c5af19283156102da576131f09561239c89946131d5935f9761337e575b506040516352bbbe2960e01b6020820152958693429260248601612f27565b604051631cff79cd60e01b8152948592839260048401610f27565b038183895af19182156102da5761320d92613366575b508261420f565b61321681611eac565b809291806132a6575b5050936132896110b8936132385f96946125d79861427b565b60405163a9059cbb60e01b60208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316602482015260448101919091529384906064820190565b83604051809681958294631cff79cd60e01b845260048401610f27565b6132e3949196929593506132c46020916132be61296a565b906121d1565b604051809681926363737ac960e11b8352600483019190602083019252565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156102da576132385f96613338613289946125d79a6110b8998b926133455750612b4e565b959750939750509361321f565b61335f91925060203d60201161030d576102fe81836108ad565b905f612d03565b613379903d805f833e6106fc81836108ad565b613206565b613391903d808a833e6106fc81836108ad565b6131b6565b635904ec9360e11b5f5260045ffd5b6133b991503d805f833e6106fc81836108ad565b5f613059565b604051906133ce6040836108ad565b600b82526a1c995cd8dd5955985d5b1d60aa1b6020830152565b918361342191837f00000000000000000000000000000000000000000000000000000000000000009561341c84838961415d565b6142e0565b9161342e5f6129e96133bf565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156102da575f9161364b575b5080511561363c5761348b6105fe8260208061351495518301019101611391565b936134958561241e565b5060405163a9059cbb60e01b60208201526001600160a01b0382166024820152604481018390529095905f906134ce8160648101610220565b604051631cff79cd60e01b81529485918291907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660048401610f27565b0381836001600160a01b038a165af19081156102da5761353b938792613624575b50612b5b565b60405163a9059cbb60e01b60208201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018790529194821692909116906135b9905f9061359e8160648101610220565b60405180938192631cff79cd60e01b83528660048401610f27565b038183875af180156102da576125d7965f96613289936135dd9361360c5750612b4e565b60405163a9059cbb60e01b60208201526001600160a01b039095166024860152604485015283606481016110b8565b61361f903d808b833e6106fc81836108ad565b612d03565b613637903d805f833e6106fc81836108ad565b613535565b630681d31960e51b5f5260045ffd5b61365f91503d805f833e6106fc81836108ad565b5f61346a565b90918361369a91847f00000000000000000000000000000000000000000000000000000000000000009461341c84838861415d565b6136a383611eac565b906136af82938261408b565b6136b9818761420f565b808203613705575b505050916110b8916136db6128aa956132385f968561427b565b604051631cff79cd60e01b815294859384928692849290916001600160a01b031660048401610f27565b61374294929593506020916137239161371c61296a565b91036121d1565b604051809581926363737ac960e11b8352600483019190602083019252565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa80156102da576128aa956132386137966136db935f986110b8988a926133455750612b4e565b94965050958294506136c1565b7f00000000000000000000000000000000000000000000000000000000000000006137cf84848361415d565b6040516370a0823160e01b81526001600160a01b038481166004830152919091169290602081602481875afa80156102da57613813915f91613911575b50826127f6565b6040516303d1689d60e11b815260048101859052926020846024816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa9283156102da57856138a06128aa97613289938661389061388b6110b89a5f9c8d916138f2575b506132be856140cd565b610e49565b9161389b8383612ab2565b612d7f565b5060405163a9059cbb60e01b60208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316602482015260448101919091529384906064820190565b61390b915060203d60201161030d576102fe81836108ad565b5f613881565b61392a915060203d60201161030d576102fe81836108ad565b5f61380c565b6040519061393f6040836108ad565b601882527f7661756c74466f726365457869744c747650657263656e7400000000000000006020830152565b51906001600160401b038216820361010a57565b9081606091031261010a57612911604080519261399b8461088d565b6139a48161263e565b84526139b26020820161396b565b60208501520161396b565b604051906139cc6040836108ad565b601982527f626f72726f77466f726365457869744c747650657263656e74000000000000006020830152565b90613a0390826115cb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031691613a55905f613a3b613930565b6040518094819263682d2ff360e01b83526004830161135a565b0381875afa9182156102da575f92613d12575b508151151580613c5b575b613b9b575b50505f613aa392613a876139bd565b90604051808096819463682d2ff360e01b83526004830161135a565b03915afa9182156102da575f92613b7f575b508151613ac3575b50505f90565b602091613ad2613af492611eac565b604094919451809481926303d1689d60e11b8352600483019190602083019252565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156102da57613b48925f92613b5a575b508060208061122e93518301019101610e1b565b1115613b55575f80613abd565b600190565b61122e919250613b789060203d60201161030d576102fe81836108ad565b9190613b34565b613b949192503d805f833e6106fc81836108ad565b905f613ab5565b6020613baa84613bcc93612666565b604092919251809481926303d1689d60e11b8352600483019190602083019252565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9182156102da575f92613c34575b5061122e83602080613c209596518301019101610e1b565b1115613c2d575f80613a78565b5050600190565b613c209250613c5461122e9160203d60201161030d576102fe81836108ad565b9250613c08565b5060405163e48a5f7b60e01b81526001600160a01b0382166004820152606081806024810103817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156102da57613cdb60206001600160401b039384935f91613ce3575b5001516001600160401b031690565b161415613a73565b613d05915060603d606011613d0b575b613cfd81836108ad565b81019061397f565b5f613ccc565b503d613cf3565b613d279192503d805f833e6106fc81836108ad565b905f613a68565b816b019d971e4fe8401e7400000019048111158215171561010a576b033b2e3c9fd0803ce800000091026b019d971e4fe8401e74000000010490565b604051632e1a7d4d60e01b6020820152602481018490526001600160a01b03919091169290613da2905f90612b938160448101610220565b038183885af180156102da57613e07575b50823b1561010a576040516324a084df60e01b81526001600160a01b039290921660048301526024820152905f908290604490829084905af180156102da57613df95750565b806102ce5f6108dd936108ad565b613e1a903d805f833e6106fc81836108ad565b613db3565b9081602091031261010a57516109a381610757565b9091613e4083836115cb565b604051633933604760e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016939190602081602481885afa9081156102da575f9161406c575b5061406457506001600160a01b038416908115614055576001600160a01b0381169485158015613ff3575b61363c57613ee06102209160405192839160208301958661158b565b51902093613f0e857f0000000000000000000000000000000000000000000000000000000000000000614433565b946001946001600160a01b038716803b1561010a5760405163189acdbd60e31b8152306004820152905f908290602490829084905af180156102da57613fdf575b50803b1561010a576040516307a64c9360e11b8152600481018390526001600160a01b0388166024820152905f908290604490829084905af180156102da57613fcb575b506040516001600160a01b03871681527f5f321e0bf9a864b125a672da82d50bc69795f0d681bf419a50a1f63eeaf77fe490602090a4565b806102ce5f613fd9936108ad565b5f613f93565b806102ce5f613fed936108ad565b5f613f4f565b5060405163054fd4d560e41b81526020816004818a5afa9081156102da5760039160ff915f91614026575b501610613ec4565b614048915060203d60201161404e575b61404081836108ad565b810190613e1f565b5f61401e565b503d614036565b63d92e233d60e01b5f5260045ffd5b93505f925050565b614085915060203d6020116107415761073381836108ad565b5f613e99565b9080821015614098575090565b905090565b604051906140ac6040836108ad565b60128252711b585e15985d5b1d131d1d94195c98d95b9d60721b6020830152565b60405163e48a5f7b60e01b81526001600160a01b039091166004820152606081806024810103817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa80156102da57604061414591614151935f91613ce3575001516001600160401b031690565b6001600160401b031690565b612a035f6129e961409d565b60405163a9059cbb60e01b602082019081526001600160a01b039390931660248201526044808201949094529283526141be915f918291906141a06064876108ad565b60018060a01b031694519082865af16141b76117c4565b9083614496565b80519081151591826141f4575b50506141d45750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b6142079250602080918301019101611307565b155f806141cb565b60405163573ade8160e01b60208201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116602483015260448201939093526002606482015291811660848301525f9182916128aa916128628160a48101610220565b604051631a4ca37b60e21b60208201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482019390935291811660648301525f9182916128aa916128628160848101610220565b604051630a2ebb1960e11b60208201526001600160a01b0390911660248201526044810192909252606482019290925290919061436c905f906143268160848101610220565b604051631cff79cd60e01b81529283918291907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660048401610f27565b0381836001600160a01b0388165af180156102da5761439c915f91614419575b5060208082518301019101610e1b565b918215614413575f836128aa92604051630d0e30db60e41b6020820152600481526143c86024826108ad565b60405163fa4bb79d60e01b815294859384928692849290917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660048501612b24565b505f9150565b61442d91503d805f833e6106fc81836108ad565b5f61438c565b6e5af43d82803e903d91602b57fd5bf390763d602d80600a3d3981f3363d3d373d3d3d363d7300000062ffffff8260881c16175f5260781b17602052603760095ff5906001600160a01b0382161561448757565b6330be1a3d60e21b5f5260045ffd5b906144ba57508051156144ab57805190602001fd5b630a12f52160e11b5f5260045ffd5b815115806144eb575b6144cb575090565b639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b50803b156144c356fea2646970667358221220ec3f01e9b59c3752410b7e3fad006a0670c5646888bbbe7123b92fcc702e57f664736f6c634300081a0033000000000000000000000000f603c5a3f774f05d4d848a9bb13980979089086400000000000000000000000094373a4919b3240d86ea41593d5eba789fef38480000000000000000000000007bbc1733ee018f103a9a9052a18fa9273255cf36000000000000000000000000124c33d07f94b31adf87c12f7ca3a586d35109280000000000000000000000003e30370cabd4b4d95be17706d840ff9de1addb67000000000000000000000000807305c086a99cbdbff07cb4256ce556d9d6f0af000000000000000000000000fc8e3e7c919b4392d9f5b27015688e49c80015f00000000000000000000000007f90bde2cd466a01b93979faa26be277297b2563000000000000000000000000cd4f0b056f56bcc28193ca2ca9b98aedd940308d000000000000000000000000a2f0e49f17c11d63c1c3d66cd98f5c15401242da000000000000000000000000c7baa4851f55a449671004cccc37a0d72eec48650000000000000000000000009d57a962fe6c10eec98d6878bd7a084b393791a1
Deployed Bytecode
0x60806040526004361015610011575f80fd5b5f3560e01c80632a5a0d7e146100f45780633ab7f631146100ef5780633b0c6d67146100ea57806347e7ef24146100e5578063492f4e18146100e057806374474d28146100db5780637ac2ff7b146100d65780639ab02a0f146100d1578063a6ed20f0146100cc578063ac9650d8146100c7578063b580e046146100c2578063d694dd24146100bd578063e28e20e4146100b85763e368fdb7146100b3575f80fd5b610cf6565b610cb4565b610af8565b610ac4565b610a54565b6109a6565b610909565b610762565b6104fa565b6104c0565b61048d565b61044e565b61033c565b61010e565b6001600160a01b0381160361010a57565b5f80fd5b3461010a57606036600319011261010a5760043561012b816100f9565b604435602435670de0b6b3a764000082101561032d5761014b33846115cb565b9161015583611eac565b508215908115610323575b50610314576040516363737ac960e11b815260048101839052906020826024816001600160a01b037f0000000000000000000000007bbc1733ee018f103a9a9052a18fa9273255cf36165afa9081156102da576101cf925f926102df575b506101c99082612147565b90610e5c565b60408051600360208201526001600160a01b038581169282019290925260608101939093527f0000000000000000000000003e30370cabd4b4d95be17706d840ff9de1addb67169161022e81608081015b03601f1981018352826108ad565b823b1561010a57610258925f9283604051809681958294635296a43160e01b845260048401610e8c565b03925af180156102da576102bb927fb7972ed828b18abfbec411ed2ee61877a59573dd54d2145a70099fa408f737a992610299926102c0575b50339061226d565b60408051928352602083019190915233946001600160a01b0316938291820190565b0390a3005b806102ce5f6102d4936108ad565b806104b6565b5f610291565b610e2a565b6101c99192506103069060203d60201161030d575b6102fe81836108ad565b810190610e1b565b91906101be565b503d6102f4565b6318374fd160e21b5f5260045ffd5b905082115f610160565b63edbc804d60e01b5f5260045ffd5b3461010a57604036600319011261010a57600435610359816100f9565b6024356001600160401b03811161010a5780360391608060031984011261010a576001600160a01b031690813b1561010a5760405192631a7ff55360e01b8452602060048501528160040135602485015260248201358060130b80910361010a57604485015260448201356103cd816100f9565b6001600160a01b0316606485810191909152820135906022190181121561010a5701602460048201359101916001600160401b03821161010a578160051b3603831361010a57835f8161042e829682966080608485015260a4840191610ea3565b03925af180156102da5761043e57005b806102ce5f61044c936108ad565b005b3461010a57602036600319011261010a5760043561046b816100f9565b60018060a01b03165f525f602052602060ff60405f2054166040519015158152f35b3461010a57604036600319011261010a5761044c6004356104ad816100f9565b60243590610f49565b5f91031261010a57565b3461010a575f36600319011261010a5760206040517f8b74cefe9f33d72ccd3521e6d331272921607e547c75c914c2c56cfdad9defed8152f35b3461010a57602036600319011261010a57600435610517816100f9565b61052133826115cb565b6001600160a01b0381165f908152602081905260409020610544905b5460ff1690565b61074857604051633933604760e11b81526001600160a01b0382811660048301527f000000000000000000000000fc8e3e7c919b4392d9f5b27015688e49c80015f01690602081602481855afa9081156102da575f91610719575b501561070a575f6105ce916105b2611333565b90604051808095819463682d2ff360e01b83526004830161135a565b03915afa9081156102da575f916106e8575b508051156106d9576105fe8160208061060a94518301019101611391565b6001600160a01b031690565b906001600160a01b03821680159081156106cf575b506106c0576001600160a01b0316803b1561010a5760405163f2fde38b60e01b81526001600160a01b0383166004820152905f908290602490829084905af180156102da576106ac575b506040516001600160a01b0391821681523392909116907f746871013d9225e5b11b13b9256515b47fa5378b085f1ba9b07b5f5112480ccf9080602081016102bb565b806102ce5f6106ba936108ad565b5f610669565b638c8728c760e01b5f5260045ffd5b905030145f61061f565b6355299b4960e01b5f5260045ffd5b61070491503d805f833e6106fc81836108ad565b810190610ec7565b5f6105e0565b634ca8886760e01b5f5260045ffd5b61073b915060203d602011610741575b61073381836108ad565b810190611307565b5f61059f565b503d610729565b630e3d8e8d60e11b5f5260045ffd5b60ff81160361010a57565b3461010a5760c036600319011261010a575f80610853600435610784816100f9565b60243561080b604435916102206064359461079e86610757565b6084356107af60a435923390612634565b5060405163d505accf60e01b60208201523360248201526001600160a01b03821660448201526064810195909552608485019690965260ff90961660a484015260c483019590955260e482019490945291928290610104820190565b604051631cff79cd60e01b815294859384928391907f000000000000000000000000f603c5a3f774f05d4d848a9bb1398097908908646001600160a01b031660048401610f27565b03926001600160a01b03165af161086657005b61044c903d805f833e6106fc81836108ad565b634e487b7160e01b5f52604160045260245ffd5b606081019081106001600160401b038211176108a857604052565b610879565b90601f801991011681019081106001600160401b038211176108a857604052565b604051906108dd60c0836108ad565b565b604051906108dd6080836108ad565b6001600160401b0381116108a857601f01601f191660200190565b3461010a57604036600319011261010a576024356004356001600160401b03821161010a573660238301121561010a57816004013590610948826108ee565b9161095660405193846108ad565b808352366024828601011161010a576020815f92602461044c97018387013784010152611458565b604090600319011261010a57600435610996816100f9565b906024356109a3816100f9565b90565b3461010a5760206109bf6109b93661097e565b906115cb565b6040516001600160a01b039091168152f35b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b602081016020825282518091526040820191602060408360051b8301019401925f915b838310610a2757505050505090565b9091929394602080610a45600193603f1986820301875289516109d1565b97019301930191939290610a18565b3461010a57602036600319011261010a576004356001600160401b03811161010a573660238201121561010a578060040135906001600160401b03821161010a573660248360051b8301011161010a57610ac0916024610ab49201611818565b604051918291826109f5565b0390f35b3461010a57608036600319011261010a57600435610ae1816100f9565b606036602319011261010a57602461044c916118e5565b3461010a57604036600319011261010a57600435610b15816100f9565b6024359081158015610ca3575b610c9457610b3033826115cb565b90610b4d61053d8360018060a01b03165f525f60205260405f2090565b61074857610b6683610b5f8484612666565b9050612147565b8015610c8557604051634933c21560e11b602082015260248101829052610bb1905f90610b968160448101610220565b60405180938192631cff79cd60e01b83528760048401610f27565b0381836001600160a01b0389165af180156102da57602095610c31610c24610c0e610c60947f91cd78d9994c342f6ef7d71956ecef9721d78270434de929d6d35a762ef3d041965f91610c6b575b508a8082518301019101610e1b565b9760018060a01b03165f525f60205260405f2090565b805460ff19166001179055565b6040805187815242602082015290810194909452606084015233936001600160a01b0316929081906080820190565b0390a3604051908152f35b610c7f91503d805f833e6106fc81836108ad565b5f610bff565b63673f032f60e11b5f5260045ffd5b6326bf739360e21b5f5260045ffd5b50670de0b6b3a76400008211610b22565b3461010a5760a036600319011261010a57600435610cd1816100f9565b60243590610cde826100f9565b606036604319011261010a5761044c91604491611bd1565b3461010a57610d043661097e565b90610d0f82826139f8565b1561070a57610d1e82826115cb565b90610d3b61053d8360018060a01b03165f525f60205260405f2090565b61074857610d55670de0b6b3a7640000610b5f8484612666565b8015610c8557604051634933c21560e11b602082015260248101829052610d85905f90610b968160448101610220565b0381836001600160a01b0389165af180156102da57602095610de7610c24610c0e670de0b6b3a7640000947f91cd78d9994c342f6ef7d71956ecef9721d78270434de929d6d35a762ef3d041965f91610c6b57508a8082518301019101610e1b565b604080518781524260208201529081019490945260608401919091526001600160a01b039081169316918060808101610c60565b9081602091031261010a575190565b6040513d5f823e3d90fd5b634e487b7160e01b5f52601160045260245ffd5b9060028201809211610e5757565b610e35565b91908201809211610e5757565b634e487b7160e01b5f52602160045260245ffd5b60041115610e8757565b610e69565b6040906109a39392815281602082015201906109d1565b81835290916001600160fb1b03831161010a5760209260051b809284830137010190565b60208183031261010a578051906001600160401b03821161010a570181601f8201121561010a57602081519101610efd826108ee565b92610f0b60405194856108ad565b8284528282011161010a57815f926020928386015e8301015290565b6001600160a01b0390911681526040602082018190526109a3929101906109d1565b9080156112f857610f5a3383612634565b506001600160a01b0381165f908152602081905260409020610f7b9061053d565b610748576040516323b872dd60e01b60208201523360248201526001600160a01b038216604482015260648101839052611004905f90610fbe8160848101610220565b604051631cff79cd60e01b81529283918291907f000000000000000000000000f603c5a3f774f05d4d848a9bb1398097908908646001600160a01b031660048401610f27565b0381836001600160a01b0387165af180156102da576112e0575b506110298184612666565b908361103484611eac565b9093829315908115916112d6575b5080156112cd575b80156112c4575b6111ac575b5050611063915084612eb7565b801561116657604080515f60208201526001600160a01b038681169282019290925292811660608401527f0000000000000000000000003e30370cabd4b4d95be17706d840ff9de1addb67166110c683608081015b03601f1981018552846108ad565b803b1561010a57604051635296a43160e01b8152925f9184918290849082906110f3908860048401610e8c565b03925af19081156102da577ff5681f9d0db1b911ac18ee83d515a1cf1051853a9eae418316a2fdf7dea427c59261114d92611152575b5060408051948552602085019190915233946001600160a01b031693918291820190565b0390a3565b806102ce5f611160936108ad565b5f611129565b5050604080519182525f602083015233926001600160a01b0316917ff5681f9d0db1b911ac18ee83d515a1cf1051853a9eae418316a2fdf7dea427c5918190810161114d565b6111e69250816111c7916111c2602094886127f6565b610e5c565b604051809381926303d1689d60e11b8352600483019190602083019252565b03817f0000000000000000000000007bbc1733ee018f103a9a9052a18fa9273255cf366001600160a01b03165afa80156102da57611234915f916112a5575b5061122e61296a565b90612147565b8082101561125d5761106391611256910361124f8185612ab2565b8386612b5b565b835f611056565b5050604080519283525f602084015233936001600160a01b0316927ff5681f9d0db1b911ac18ee83d515a1cf1051853a9eae418316a2fdf7dea427c59250908190810161114d565b6112be915060203d60201161030d576102fe81836108ad565b5f611225565b50801515611051565b5083151561104a565b905015155f611042565b6112f3903d805f833e6106fc81836108ad565b61101e565b636edcc52360e01b5f5260045ffd5b9081602091031261010a5751801515810361010a5790565b6040519061132e6020836108ad565b5f8252565b604051906113426040836108ad565b600982526875706772616465563160b81b6020830152565b9060406109a3927f8b74cefe9f33d72ccd3521e6d331272921607e547c75c914c2c56cfdad9defed815281602082015201906109d1565b9081602091031261010a57516109a3816100f9565b5190600482101561010a57565b9081602091031261010a576109a3906113a6565b9081606091031261010a576113db816113a6565b91604060208301516113ec816100f9565b92015190565b919082608091031261010a57611407826113a6565b916020810151611416816100f9565b91606060408301516113ec816100f9565b9081606091031261010a5761143b816113a6565b916040602083015161144c816100f9565b9201516109a3816100f9565b7f0000000000000000000000003e30370cabd4b4d95be17706d840ff9de1addb676001600160a01b0316330361070a5781519161149d602080830194830101846113b3565b6114a681610e7d565b806114d357506108dd926020826114c09351010190611427565b6001600160a01b039081169250166137a3565b6114dc81610e7d565b6001810361150d57506108dd926020826114f993510101906113f2565b92506001600160a01b039081169116613665565b61151681610e7d565b6002810361154757506108dd9260208261153393510101906113f2565b92506001600160a01b0390811691166133e8565b80611553600392610e7d565b0361157c576108dd9260208261156c93510101906113c7565b91506001600160a01b0316612fe3565b63adc9f0f960e01b5f5260045ffd5b7f8b74cefe9f33d72ccd3521e6d331272921607e547c75c914c2c56cfdad9defed81526001600160a01b0391821660208201529116604082015260600190565b906115e46102209160405192839160208301958661158b565b5190206040516338e1dd3160e21b81526004810182905291906020836024816001600160a01b037f000000000000000000000000fc8e3e7c919b4392d9f5b27015688e49c80015f0165afa9283156102da575f936116cc575b506001600160a01b038316156116505750565b6040513060388201526f5af43d82803e903d91602b57fd5bf3ff60248201527f0000000000000000000000007f90bde2cd466a01b93979faa26be277297b25636014820152733d602d80600a3d3981f3363d3d373d3d3d363d73815260588101919091526037600c820120607882015260556043909101209150565b6116ef91935060203d6020116116f6575b6116e781836108ad565b810190611391565b915f61163d565b503d6116dd565b6001600160401b0381116108a85760051b60200190565b9061171e826116fd565b61172b60405191826108ad565b828152809261173c601f19916116fd565b01905f5b82811061174c57505050565b806060602080938501015201611740565b634e487b7160e01b5f52603260045260245ffd5b91908110156117b25760051b81013590601e198136030182121561010a5701908135916001600160401b03831161010a57602001823603811361010a579190565b61175d565b908092918237015f815290565b3d156117ee573d906117d5826108ee565b916117e360405193846108ad565b82523d5f602084013e565b606090565b9060206109a39281815201906109d1565b80518210156117b25760209160051b010190565b91909161182483611714565b925f5b81811061183357505050565b5f80611840838587611771565b90611850604051809381936117b7565b0390305af461185d6117c4565b901561188357906001916118718288611804565b5261187c8187611804565b5001611827565b604481511061010a576118a58160248060046118bd9501518301019101610ec7565b60405162461bcd60e51b8152918291600483016117f3565b0390fd5b9081606091031261010a5780516118d7816100f9565b916040602083015192015190565b906118f033836115cb565b9061191461191061053d8460018060a01b03165f525f60205260405f2090565b1590565b611bc257604051633adbb5af60e01b81526001600160a01b03848116600483015282356024830181905292907f000000000000000000000000807305c086a99cbdbff07cb4256ce556d9d6f0af16606083604481845afa9283156102da575f80915f95611b8d575b506001600160a01b03878116911603611b7e576001841115611b185715611aa2575b505060408051600260208201526001600160a01b0386811692820192909252848216606082015260808101939093527f0000000000000000000000003e30370cabd4b4d95be17706d840ff9de1addb6716916119fd8160a08101610220565b823b1561010a57611a27925f9283604051809681958294635296a43160e01b845260048401610e8c565b03925af180156102da5761114d927f0751a391154a0437ff29e885c1cfbd7f0e63201c8fc308298cee3ba65ef470579261029992611a8e575b506001600160a01b0381165f908152602081905260409020611a87905b805460ff19169055565b339061226d565b806102ce5f611a9c936108ad565b5f611a60565b60408201359160200135813b1561010a576040516398e99bb760e01b81526001600160a01b038816600482015260248101869052604481019190915260648101929092525f908290608490829084905af180156102da57611b04575b8061199e565b806102ce5f611b12936108ad565b5f611afe565b5050505050611a7d611b399160018060a01b03165f525f60205260405f2090565b604080515f808252602082015233926001600160a01b0316917f0751a391154a0437ff29e885c1cfbd7f0e63201c8fc308298cee3ba65ef4705791908190810161114d565b63154a26f760e21b5f5260045ffd5b915050611bb391935060603d606011611bbb575b611bab81836108ad565b8101906118c1565b93915f61197c565b503d611ba1565b63171a12d760e21b5f5260045ffd5b91611bdc82846115cb565b91611bfc61191061053d8560018060a01b03165f525f60205260405f2090565b611bc257604051633adbb5af60e01b81526001600160a01b03858116600483015283356024830181905293907f000000000000000000000000807305c086a99cbdbff07cb4256ce556d9d6f0af16606083604481845afa9283156102da575f80915f95611e87575b506001600160a01b03888116911603611b7e576001841115611e1c5715611da6575b505060408051600160208201526001600160a01b0387811692820192909252858216606082015260808101949094527f0000000000000000000000003e30370cabd4b4d95be17706d840ff9de1addb671692611ce58160a08101610220565b833b1561010a57611d0f935f9283604051809781958294635296a43160e01b845260048401610e8c565b03925af19081156102da577f0692d4883b7fdb846537c159a4f16ab7f36fd8be83e2b46f05f66e563e01286e92611a7d92611d92575b50611d6b611d53828661226d565b93909560018060a01b03165f525f60205260405f2090565b6040805194855260208501929092526001600160a01b03908116941692908190810161114d565b806102ce5f611da0936108ad565b5f611d45565b60408201359160200135813b1561010a576040516398e99bb760e01b81526001600160a01b038916600482015260248101879052604481019190915260648101929092525f908290608490829084905af180156102da57611e08575b80611c86565b806102ce5f611e16936108ad565b5f611e02565b5050505091611e3f9150611a7d9060018060a01b03165f525f60205260405f2090565b604080515f80825260208201526001600160a01b0392831693909216917f0692d4883b7fdb846537c159a4f16ab7f36fd8be83e2b46f05f66e563e01286e918190810161114d565b915050611ea491935060603d606011611bbb57611bab81836108ad565b93915f611c64565b604051630ed1279f60e11b81526001600160a01b03821660048201529091602082806024810103817f000000000000000000000000c7baa4851f55a449671004cccc37a0d72eec48656001600160a01b03165afa9182156102da575f92612108575b508180612055575b50604051630ed1279f60e11b81526001600160a01b03909316600484015260208380602481015b03817f0000000000000000000000009d57a962fe6c10eec98d6878bd7a084b393791a16001600160a01b03165afa9283156102da575f93612034575b508280611f835750565b60405163386497fd60e01b81527f00000000000000000000000094373a4919b3240d86ea41593d5eba789fef38486001600160a01b03166004820152919350602082806024810103817f000000000000000000000000a2f0e49f17c11d63c1c3d66cd98f5c15401242da6001600160a01b03165afa9081156102da57612010925f92612013575b50613d2e565b91565b61202d91925060203d60201161030d576102fe81836108ad565b905f61200a565b61204e91935060203d60201161030d576102fe81836108ad565b915f611f79565b60405163d15e005360e01b81527f000000000000000000000000f603c5a3f774f05d4d848a9bb1398097908908646001600160a01b03166004820152939250602084806024810103817f000000000000000000000000a2f0e49f17c11d63c1c3d66cd98f5c15401242da6001600160a01b03165afa9384156102da57611f3d946020926120e8925f926120f05750613d2e565b929350611f16565b61202d919250843d861161030d576102fe81836108ad565b61212291925060203d60201161030d576102fe81836108ad565b905f611f0e565b8115612133570490565b634e487b7160e01b5f52601260045260245ffd5b808202905f19838209908280831092039180830392146121c05781670de0b6b3a764000011156121b1577faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac1066993670de0b6b3a7640000910990828211900360ee1b910360121c170290565b63227bc15360e01b5f5260045ffd5b50670de0b6b3a76400009250500490565b90670de0b6b3a76400008202905f19670de0b6b3a764000084099282808510940393808503941461226157838211156121b157670de0b6b3a7640000829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b50906109a39250612129565b6040516370a0823160e01b81526001600160a01b0382811660048301527f000000000000000000000000f603c5a3f774f05d4d848a9bb13980979089086416939190602081602481885afa9081156102da575f916123ff575b50809481612366575b50506040516370a0823160e01b81526001600160a01b0382166004820152602081806024810103817f00000000000000000000000094373a4919b3240d86ea41593d5eba789fef38486001600160a01b03165afa9081156102da575f91612347575b5080938161233e57505050565b6108dd92613d6a565b612360915060203d60201161030d576102fe81836108ad565b5f612331565b60405163a9059cbb60e01b60208201526001600160a01b038616602482015260448101929092526123c5915f916123aa82606481015b03601f1981018452836108ad565b604051631cff79cd60e01b8152938492839260048401610f27565b0381836001600160a01b0387165af180156102da576123e5575b806122cf565b6123f8903d805f833e6106fc81836108ad565b505f6123df565b612418915060203d60201161030d576102fe81836108ad565b5f6122c6565b600161242991613e34565b90918183811561262e5750506040516328530a4760e01b6020820152600160248201526124ab906001600160a01b03858116917f000000000000000000000000a2f0e49f17c11d63c1c3d66cd98f5c15401242da909116905f906124908160448101610220565b60405180958192631cff79cd60e01b83528560048401610f27565b038183865af19283156102da5761253d93612616575b5060405163095ea7b360e01b60208201526001600160a01b03821660248201525f1960448201525f906124f78160648101610220565b604051631cff79cd60e01b81529485918291907f000000000000000000000000f603c5a3f774f05d4d848a9bb1398097908908646001600160a01b031660048401610f27565b038183865af19182156102da5761022061258f6125d7935f9687966125fe575b5060405163095ea7b360e01b60208201526001600160a01b0390911660248201525f1960448201529182906064820190565b604051631cff79cd60e01b815294859384928391907f00000000000000000000000094373a4919b3240d86ea41593d5eba789fef38486001600160a01b031660048401610f27565b03925af180156102da576125e85750565b6125fb903d805f833e6106fc81836108ad565b50565b612611903d8089833e6106fc81836108ad565b61255d565b612629903d805f833e6106fc81836108ad565b6124c1565b93509150565b9061242991613e34565b51906001600160801b038216820361010a57565b9081602091031261010a576109a39061263e565b604051630e56821560e31b81525f9392916001600160a01b031690602081600481855afa9081156102da575f916127d7575b506127c85760405163f04da65b60e01b81526001600160a01b0383166004820152602081602481855afa9081156102da575f916127a9575b508061274c575b50604051632764b59160e11b81526001600160a01b03909216600483015260209082908180602481015b03915afa80156102da576001600160801b03915f9161271f57501690565b612741915060203d602011612745575b61273981836108ad565b810190612652565b1690565b503d61272f565b6040516303d1689d60e11b81526004810191909152909350602081602481875afa9182156102da57612701926020925f9161278c575b50949150916126d7565b6127a39150833d851161030d576102fe81836108ad565b5f612782565b6127c2915060203d60201161030d576102fe81836108ad565b5f6126d0565b63e775715160e01b5f5260045ffd5b6127f0915060203d6020116107415761073381836108ad565b5f612698565b60405163617ba03760e01b60208201526001600160a01b037f000000000000000000000000f603c5a3f774f05d4d848a9bb13980979089086481166024830152604482019390935291811660648301525f608483018190529182916128aa916128628160a48101610220565b604051631cff79cd60e01b815294859384928391907f000000000000000000000000a2f0e49f17c11d63c1c3d66cd98f5c15401242da6001600160a01b031660048401610f27565b03926001600160a01b03165af180156102da576125e85750565b519061ffff8216820361010a57565b9081606091031261010a5761291160408051926128ef8461088d565b6128f8816128c4565b8452612906602082016128c4565b6020850152016128c4565b604082015290565b90655af3107a4000820291808304655af3107a40001490151715610e5757565b604051906129486040836108ad565b60138252721b585e109bdc9c9bddd31d1d94195c98d95b9d606a1b6020830152565b60405163b286f46760e01b8152600160048201526060816024816001600160a01b037f000000000000000000000000a2f0e49f17c11d63c1c3d66cd98f5c15401242da165afa80156102da576129d16129d8916129dd935f91612a83575b505161ffff1690565b61ffff1690565b612919565b612a035f6129e9612939565b6040518093819263682d2ff360e01b83526004830161135a565b03817f000000000000000000000000fc8e3e7c919b4392d9f5b27015688e49c80015f06001600160a01b03165afa9081156102da575f91612a69575b5080518015612a645781602080612a5e936109a3969501019101610e1b565b9061408b565b505090565b612a7d91503d805f833e6106fc81836108ad565b5f612a3f565b612aa5915060603d606011612aab575b612a9d81836108ad565b8101906128d3565b5f6129c8565b503d612a93565b60405163a415bcad60e01b60208201526001600160a01b037f00000000000000000000000094373a4919b3240d86ea41593d5eba789fef3848811660248301526044820193909352600260648201525f6084820181905292821660a482015282916128aa916128628160c48101610220565b939291612b499060409260018060a01b031686526060602087015260608601906109d1565b930152565b91908203918211610e5757565b604051632e1a7d4d60e01b6020820152602481018490526001600160a01b03831693919290612bd9905f90612b938160448101610220565b604051631cff79cd60e01b81529283918291907f00000000000000000000000094373a4919b3240d86ea41593d5eba789fef38486001600160a01b031660048401610f27565b038183895af180156102da57612d67575b506040516370a0823160e01b81526001600160a01b03828116600483015290947f000000000000000000000000f603c5a3f774f05d4d848a9bb1398097908908649091169290602086602481875afa9485156102da57612ca9965f96612d40575b50604051631b7f2ce960e11b60208201526001600160a01b03851660248201525f1960448201525f606482018190529392918490612c8c83608481016110b8565b60405163fa4bb79d60e01b8152998a958694859360048501612b24565b03925af19182156102da57612cee94602093612d28575b506040516370a0823160e01b81526001600160a01b0390921660048301529093849190829081906024820190565b03915afa80156102da576109a3925f91612d09575b50612b4e565b612d22915060203d60201161030d576102fe81836108ad565b5f612d03565b612d3b903d805f833e6106fc81836108ad565b612cc0565b5f9392919650612d5e9060203d60201161030d576102fe81836108ad565b95909192612c4b565b612d7a903d805f833e6106fc81836108ad565b612bea565b604051632e1a7d4d60e01b6020820152602481018490529093926001600160a01b0383169291612db8905f90612b938160448101610220565b038183885af180156102da57612e9f575b506040516370a0823160e01b81526001600160a01b03838116600483015290957f000000000000000000000000f603c5a3f774f05d4d848a9bb1398097908908649091169390602087602481885afa9586156102da57612ca9975f97612e6c575b50604051631b7f2ce960e11b60208201526001600160a01b038616602482015260448101919091525f606482018190529392918490612c8c83608481016110b8565b6110b89197505f949392612c8c612e92879360203d60201161030d576102fe81836108ad565b9993505092939450612e2a565b612eb2903d805f833e6106fc81836108ad565b612dc9565b612ec3612ecb916140cd565b61122e61296a565b670de0b6b3a764000003670de0b6b3a76400008111610e5757612eee90826121d1565b908103908111610e575790565b60405190612f0a6040836108ad565b600e82526d18985b185b98d95c941bdbdb125960921b6020830152565b909194939260e08252825160e083015260208301516002811015610e875761010083015260408301516001600160a01b03908116610120840152606084015116610140830152608083015161016083015260a09092015160c061018083018190529290612fda90612f9d906101a08501906109d1565b9660208401906060809160018060a01b03815116845260208101511515602085015260018060a01b03604082015116604085015201511515910152565b60a08201520152565b917f000000000000000000000000f603c5a3f774f05d4d848a9bb1398097908908649261301182828661415d565b61301d5f6129e9612efb565b03817f000000000000000000000000fc8e3e7c919b4392d9f5b27015688e49c80015f06001600160a01b03165afa9081156102da575f916133a5575b50805115613396578060208061307493518301019101610e1b565b6001600160a01b03909416936130886108ce565b908152600160208201526001600160a01b03851660408201527f00000000000000000000000094373a4919b3240d86ea41593d5eba789fef38486001600160a01b031660608201528360808201526130de61131f565b60a08201526001600160a01b038216936131956130f96108df565b6001600160a01b0385168152925f60208501526001600160a01b03871660408501525f6060850181905260405163095ea7b360e01b60208201527f000000000000000000000000cd4f0b056f56bcc28193ca2ca9b98aedd940308d6001600160a01b03166024820181905260448201899052919061317a8160648101610220565b60405180958192631cff79cd60e01b83528d60048401610f27565b0381838c5af19283156102da576131f09561239c89946131d5935f9761337e575b506040516352bbbe2960e01b6020820152958693429260248601612f27565b604051631cff79cd60e01b8152948592839260048401610f27565b038183895af19182156102da5761320d92613366575b508261420f565b61321681611eac565b809291806132a6575b5050936132896110b8936132385f96946125d79861427b565b60405163a9059cbb60e01b60208201527f0000000000000000000000003e30370cabd4b4d95be17706d840ff9de1addb676001600160a01b0316602482015260448101919091529384906064820190565b83604051809681958294631cff79cd60e01b845260048401610f27565b6132e3949196929593506132c46020916132be61296a565b906121d1565b604051809681926363737ac960e11b8352600483019190602083019252565b03817f0000000000000000000000007bbc1733ee018f103a9a9052a18fa9273255cf366001600160a01b03165afa9081156102da576132385f96613338613289946125d79a6110b8998b926133455750612b4e565b959750939750509361321f565b61335f91925060203d60201161030d576102fe81836108ad565b905f612d03565b613379903d805f833e6106fc81836108ad565b613206565b613391903d808a833e6106fc81836108ad565b6131b6565b635904ec9360e11b5f5260045ffd5b6133b991503d805f833e6106fc81836108ad565b5f613059565b604051906133ce6040836108ad565b600b82526a1c995cd8dd5955985d5b1d60aa1b6020830152565b918361342191837f000000000000000000000000f603c5a3f774f05d4d848a9bb1398097908908649561341c84838961415d565b6142e0565b9161342e5f6129e96133bf565b03817f000000000000000000000000fc8e3e7c919b4392d9f5b27015688e49c80015f06001600160a01b03165afa9081156102da575f9161364b575b5080511561363c5761348b6105fe8260208061351495518301019101611391565b936134958561241e565b5060405163a9059cbb60e01b60208201526001600160a01b0382166024820152604481018390529095905f906134ce8160648101610220565b604051631cff79cd60e01b81529485918291907f00000000000000000000000094373a4919b3240d86ea41593d5eba789fef38486001600160a01b031660048401610f27565b0381836001600160a01b038a165af19081156102da5761353b938792613624575b50612b5b565b60405163a9059cbb60e01b60208201526001600160a01b037f0000000000000000000000003e30370cabd4b4d95be17706d840ff9de1addb6781166024830152604482018790529194821692909116906135b9905f9061359e8160648101610220565b60405180938192631cff79cd60e01b83528660048401610f27565b038183875af180156102da576125d7965f96613289936135dd9361360c5750612b4e565b60405163a9059cbb60e01b60208201526001600160a01b039095166024860152604485015283606481016110b8565b61361f903d808b833e6106fc81836108ad565b612d03565b613637903d805f833e6106fc81836108ad565b613535565b630681d31960e51b5f5260045ffd5b61365f91503d805f833e6106fc81836108ad565b5f61346a565b90918361369a91847f000000000000000000000000f603c5a3f774f05d4d848a9bb1398097908908649461341c84838861415d565b6136a383611eac565b906136af82938261408b565b6136b9818761420f565b808203613705575b505050916110b8916136db6128aa956132385f968561427b565b604051631cff79cd60e01b815294859384928692849290916001600160a01b031660048401610f27565b61374294929593506020916137239161371c61296a565b91036121d1565b604051809581926363737ac960e11b8352600483019190602083019252565b03817f0000000000000000000000007bbc1733ee018f103a9a9052a18fa9273255cf366001600160a01b03165afa80156102da576128aa956132386137966136db935f986110b8988a926133455750612b4e565b94965050958294506136c1565b7f000000000000000000000000f603c5a3f774f05d4d848a9bb1398097908908646137cf84848361415d565b6040516370a0823160e01b81526001600160a01b038481166004830152919091169290602081602481875afa80156102da57613813915f91613911575b50826127f6565b6040516303d1689d60e11b815260048101859052926020846024816001600160a01b037f0000000000000000000000007bbc1733ee018f103a9a9052a18fa9273255cf36165afa9283156102da57856138a06128aa97613289938661389061388b6110b89a5f9c8d916138f2575b506132be856140cd565b610e49565b9161389b8383612ab2565b612d7f565b5060405163a9059cbb60e01b60208201527f0000000000000000000000003e30370cabd4b4d95be17706d840ff9de1addb676001600160a01b0316602482015260448101919091529384906064820190565b61390b915060203d60201161030d576102fe81836108ad565b5f613881565b61392a915060203d60201161030d576102fe81836108ad565b5f61380c565b6040519061393f6040836108ad565b601882527f7661756c74466f726365457869744c747650657263656e7400000000000000006020830152565b51906001600160401b038216820361010a57565b9081606091031261010a57612911604080519261399b8461088d565b6139a48161263e565b84526139b26020820161396b565b60208501520161396b565b604051906139cc6040836108ad565b601982527f626f72726f77466f726365457869744c747650657263656e74000000000000006020830152565b90613a0390826115cb565b7f000000000000000000000000fc8e3e7c919b4392d9f5b27015688e49c80015f06001600160a01b031691613a55905f613a3b613930565b6040518094819263682d2ff360e01b83526004830161135a565b0381875afa9182156102da575f92613d12575b508151151580613c5b575b613b9b575b50505f613aa392613a876139bd565b90604051808096819463682d2ff360e01b83526004830161135a565b03915afa9182156102da575f92613b7f575b508151613ac3575b50505f90565b602091613ad2613af492611eac565b604094919451809481926303d1689d60e11b8352600483019190602083019252565b03817f0000000000000000000000007bbc1733ee018f103a9a9052a18fa9273255cf366001600160a01b03165afa9081156102da57613b48925f92613b5a575b508060208061122e93518301019101610e1b565b1115613b55575f80613abd565b600190565b61122e919250613b789060203d60201161030d576102fe81836108ad565b9190613b34565b613b949192503d805f833e6106fc81836108ad565b905f613ab5565b6020613baa84613bcc93612666565b604092919251809481926303d1689d60e11b8352600483019190602083019252565b03817f0000000000000000000000007bbc1733ee018f103a9a9052a18fa9273255cf366001600160a01b03165afa9182156102da575f92613c34575b5061122e83602080613c209596518301019101610e1b565b1115613c2d575f80613a78565b5050600190565b613c209250613c5461122e9160203d60201161030d576102fe81836108ad565b9250613c08565b5060405163e48a5f7b60e01b81526001600160a01b0382166004820152606081806024810103817f000000000000000000000000124c33d07f94b31adf87c12f7ca3a586d35109286001600160a01b03165afa9081156102da57613cdb60206001600160401b039384935f91613ce3575b5001516001600160401b031690565b161415613a73565b613d05915060603d606011613d0b575b613cfd81836108ad565b81019061397f565b5f613ccc565b503d613cf3565b613d279192503d805f833e6106fc81836108ad565b905f613a68565b816b019d971e4fe8401e7400000019048111158215171561010a576b033b2e3c9fd0803ce800000091026b019d971e4fe8401e74000000010490565b604051632e1a7d4d60e01b6020820152602481018490526001600160a01b03919091169290613da2905f90612b938160448101610220565b038183885af180156102da57613e07575b50823b1561010a576040516324a084df60e01b81526001600160a01b039290921660048301526024820152905f908290604490829084905af180156102da57613df95750565b806102ce5f6108dd936108ad565b613e1a903d805f833e6106fc81836108ad565b613db3565b9081602091031261010a57516109a381610757565b9091613e4083836115cb565b604051633933604760e11b81526001600160a01b0382811660048301527f000000000000000000000000fc8e3e7c919b4392d9f5b27015688e49c80015f016939190602081602481885afa9081156102da575f9161406c575b5061406457506001600160a01b038416908115614055576001600160a01b0381169485158015613ff3575b61363c57613ee06102209160405192839160208301958661158b565b51902093613f0e857f0000000000000000000000007f90bde2cd466a01b93979faa26be277297b2563614433565b946001946001600160a01b038716803b1561010a5760405163189acdbd60e31b8152306004820152905f908290602490829084905af180156102da57613fdf575b50803b1561010a576040516307a64c9360e11b8152600481018390526001600160a01b0388166024820152905f908290604490829084905af180156102da57613fcb575b506040516001600160a01b03871681527f5f321e0bf9a864b125a672da82d50bc69795f0d681bf419a50a1f63eeaf77fe490602090a4565b806102ce5f613fd9936108ad565b5f613f93565b806102ce5f613fed936108ad565b5f613f4f565b5060405163054fd4d560e41b81526020816004818a5afa9081156102da5760039160ff915f91614026575b501610613ec4565b614048915060203d60201161404e575b61404081836108ad565b810190613e1f565b5f61401e565b503d614036565b63d92e233d60e01b5f5260045ffd5b93505f925050565b614085915060203d6020116107415761073381836108ad565b5f613e99565b9080821015614098575090565b905090565b604051906140ac6040836108ad565b60128252711b585e15985d5b1d131d1d94195c98d95b9d60721b6020830152565b60405163e48a5f7b60e01b81526001600160a01b039091166004820152606081806024810103817f000000000000000000000000124c33d07f94b31adf87c12f7ca3a586d35109286001600160a01b03165afa80156102da57604061414591614151935f91613ce3575001516001600160401b031690565b6001600160401b031690565b612a035f6129e961409d565b60405163a9059cbb60e01b602082019081526001600160a01b039390931660248201526044808201949094529283526141be915f918291906141a06064876108ad565b60018060a01b031694519082865af16141b76117c4565b9083614496565b80519081151591826141f4575b50506141d45750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b6142079250602080918301019101611307565b155f806141cb565b60405163573ade8160e01b60208201526001600160a01b037f00000000000000000000000094373a4919b3240d86ea41593d5eba789fef38488116602483015260448201939093526002606482015291811660848301525f9182916128aa916128628160a48101610220565b604051631a4ca37b60e21b60208201526001600160a01b037f000000000000000000000000f603c5a3f774f05d4d848a9bb13980979089086481166024830152604482019390935291811660648301525f9182916128aa916128628160848101610220565b604051630a2ebb1960e11b60208201526001600160a01b0390911660248201526044810192909252606482019290925290919061436c905f906143268160848101610220565b604051631cff79cd60e01b81529283918291907f000000000000000000000000807305c086a99cbdbff07cb4256ce556d9d6f0af6001600160a01b031660048401610f27565b0381836001600160a01b0388165af180156102da5761439c915f91614419575b5060208082518301019101610e1b565b918215614413575f836128aa92604051630d0e30db60e41b6020820152600481526143c86024826108ad565b60405163fa4bb79d60e01b815294859384928692849290917f00000000000000000000000094373a4919b3240d86ea41593d5eba789fef38486001600160a01b031660048501612b24565b505f9150565b61442d91503d805f833e6106fc81836108ad565b5f61438c565b6e5af43d82803e903d91602b57fd5bf390763d602d80600a3d3981f3363d3d373d3d3d363d7300000062ffffff8260881c16175f5260781b17602052603760095ff5906001600160a01b0382161561448757565b6330be1a3d60e21b5f5260045ffd5b906144ba57508051156144ab57805190602001fd5b630a12f52160e11b5f5260045ffd5b815115806144eb575b6144cb575090565b639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b50803b156144c356fea2646970667358221220ec3f01e9b59c3752410b7e3fad006a0670c5646888bbbe7123b92fcc702e57f664736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000f603c5a3f774f05d4d848a9bb13980979089086400000000000000000000000094373a4919b3240d86ea41593d5eba789fef38480000000000000000000000007bbc1733ee018f103a9a9052a18fa9273255cf36000000000000000000000000124c33d07f94b31adf87c12f7ca3a586d35109280000000000000000000000003e30370cabd4b4d95be17706d840ff9de1addb67000000000000000000000000807305c086a99cbdbff07cb4256ce556d9d6f0af000000000000000000000000fc8e3e7c919b4392d9f5b27015688e49c80015f00000000000000000000000007f90bde2cd466a01b93979faa26be277297b2563000000000000000000000000cd4f0b056f56bcc28193ca2ca9b98aedd940308d000000000000000000000000a2f0e49f17c11d63c1c3d66cd98f5c15401242da000000000000000000000000c7baa4851f55a449671004cccc37a0d72eec48650000000000000000000000009d57a962fe6c10eec98d6878bd7a084b393791a1
-----Decoded View---------------
Arg [0] : osToken (address): 0xF603c5A3F774F05d4D848A9bB139809790890864
Arg [1] : assetToken (address): 0x94373a4919B3240D86eA41593D5eBa789FEF3848
Arg [2] : osTokenVaultController (address): 0x7BbC1733ee018f103A9a9052a18fA9273255Cf36
Arg [3] : osTokenConfig (address): 0x124C33d07F94B31aDF87C12F7cA3a586d3510928
Arg [4] : osTokenFlashLoans (address): 0x3e30370cabD4B4D95Be17706D840FF9de1ADdb67
Arg [5] : osTokenVaultEscrow (address): 0x807305c086A99cbDBff07cB4256cE556d9d6F0af
Arg [6] : strategiesRegistry (address): 0xFc8E3E7c919b4392D9F5B27015688e49c80015f0
Arg [7] : strategyProxyImplementation (address): 0x7f90bDe2cD466A01b93979fAa26bE277297b2563
Arg [8] : balancerVault (address): 0xCd4f0b056F56BCc28193Ca2Ca9B98AEdd940308d
Arg [9] : aavePool (address): 0xa2F0E49f17c11d63C1c3d66cd98F5c15401242da
Arg [10] : aaveOsToken (address): 0xC7BAa4851f55A449671004Cccc37A0D72EEc4865
Arg [11] : aaveVarDebtAssetToken (address): 0x9d57a962Fe6c10eEc98D6878bd7a084b393791A1
-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 000000000000000000000000f603c5a3f774f05d4d848a9bb139809790890864
Arg [1] : 00000000000000000000000094373a4919b3240d86ea41593d5eba789fef3848
Arg [2] : 0000000000000000000000007bbc1733ee018f103a9a9052a18fa9273255cf36
Arg [3] : 000000000000000000000000124c33d07f94b31adf87c12f7ca3a586d3510928
Arg [4] : 0000000000000000000000003e30370cabd4b4d95be17706d840ff9de1addb67
Arg [5] : 000000000000000000000000807305c086a99cbdbff07cb4256ce556d9d6f0af
Arg [6] : 000000000000000000000000fc8e3e7c919b4392d9f5b27015688e49c80015f0
Arg [7] : 0000000000000000000000007f90bde2cd466a01b93979faa26be277297b2563
Arg [8] : 000000000000000000000000cd4f0b056f56bcc28193ca2ca9b98aedd940308d
Arg [9] : 000000000000000000000000a2f0e49f17c11d63c1c3d66cd98f5c15401242da
Arg [10] : 000000000000000000000000c7baa4851f55a449671004cccc37a0d72eec4865
Arg [11] : 0000000000000000000000009d57a962fe6c10eec98d6878bd7a084b393791a1
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.