Branch data Line data Source code
1 : : // SPDX-License-Identifier: BUSL-1.1
2 : : pragma solidity ^0.8.0;
3 : :
4 : : import {ERC20Upgradeable, ERC20PermitUpgradeable} from 'openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/ERC20PermitUpgradeable.sol';
5 : : import {IERC20Metadata} from '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';
6 : : import {PausableUpgradeable} from 'openzeppelin-contracts-upgradeable/contracts/utils/PausableUpgradeable.sol';
7 : : import {IRescuable, Rescuable} from 'solidity-utils/contracts/utils/Rescuable.sol';
8 : : import {IRescuableBase, RescuableBase} from 'solidity-utils/contracts/utils/RescuableBase.sol';
9 : : import {IERC20Permit} from '@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol';
10 : :
11 : : import {IACLManager} from '../../../contracts/interfaces/IACLManager.sol';
12 : : import {ERC4626Upgradeable, ERC4626StataTokenUpgradeable, IPool, Math, IERC20} from './ERC4626StataTokenUpgradeable.sol';
13 : : import {ERC20AaveLMUpgradeable, IRewardsController} from './ERC20AaveLMUpgradeable.sol';
14 : : import {IStataTokenV2} from './interfaces/IStataTokenV2.sol';
15 : : import {IAToken} from './interfaces/IAToken.sol';
16 : :
17 : : /**
18 : : * @title StataTokenV2
19 : : * @notice A 4626 Vault which wrapps aTokens in order to translate the rebasing nature of yield accrual into a non-rebasing value accrual.
20 : : * @author BGD labs
21 : : */
22 : : contract StataTokenV2 is
23 : : ERC20PermitUpgradeable,
24 : : ERC20AaveLMUpgradeable,
25 : : ERC4626StataTokenUpgradeable,
26 : : PausableUpgradeable,
27 : : Rescuable,
28 : : IStataTokenV2
29 : : {
30 : : using Math for uint256;
31 : :
32 : : constructor(
33 : : IPool pool,
34 : : IRewardsController rewardsController
35 : : ) ERC20AaveLMUpgradeable(rewardsController) ERC4626StataTokenUpgradeable(pool) {
36 : 0 : _disableInitializers();
37 : : }
38 : :
39 : : modifier onlyPauseGuardian() {
40 : 1007 : if (!canPause(_msgSender())) revert OnlyPauseGuardian(_msgSender());
41 : : _;
42 : : }
43 : :
44 : : function initialize(
45 : : address aToken,
46 : : string calldata staticATokenName,
47 : : string calldata staticATokenSymbol
48 : : ) external initializer {
49 : 69 : __ERC20_init(staticATokenName, staticATokenSymbol);
50 : 69 : __ERC20Permit_init(staticATokenName);
51 : 69 : __ERC20AaveLM_init(aToken);
52 : 69 : __ERC4626StataToken_init(aToken);
53 : 69 : __Pausable_init();
54 : : }
55 : :
56 : : ///@inheritdoc IStataTokenV2
57 : : function setPaused(bool paused) external onlyPauseGuardian {
58 : 7 : if (paused) _pause();
59 : 0 : else _unpause();
60 : : }
61 : :
62 : : /// @inheritdoc IRescuable
63 : : function whoCanRescue() public view override returns (address) {
64 : 1003 : return POOL_ADDRESSES_PROVIDER.getACLAdmin();
65 : : }
66 : :
67 : : /// @inheritdoc IRescuableBase
68 : : function maxRescue(
69 : : address asset
70 : : ) public view override(IRescuableBase, RescuableBase) returns (uint256) {
71 : 1002 : IERC20 cachedAToken = aToken();
72 : 1002 : if (asset == address(cachedAToken)) {
73 : 1001 : uint256 requiredBacking = _convertToAssets(totalSupply(), Math.Rounding.Ceil);
74 : 1001 : uint256 balance = cachedAToken.balanceOf(address(this));
75 : 1001 : return balance > requiredBacking ? balance - requiredBacking : 0;
76 : : }
77 : 1 : return type(uint256).max;
78 : : }
79 : :
80 : : ///@inheritdoc IStataTokenV2
81 : : function canPause(address actor) public view returns (bool) {
82 : 2008 : return IACLManager(POOL_ADDRESSES_PROVIDER.getACLManager()).isEmergencyAdmin(actor);
83 : : }
84 : :
85 : : ///@inheritdoc IERC20Permit
86 : : function nonces(
87 : : address owner
88 : : ) public view virtual override(ERC20PermitUpgradeable, IERC20Permit) returns (uint256) {
89 : 3 : return super.nonces(owner);
90 : : }
91 : :
92 : : ///@inheritdoc IERC20Metadata
93 : : function decimals()
94 : : public
95 : : view
96 : : override(IERC20Metadata, ERC20Upgradeable, ERC4626Upgradeable)
97 : : returns (uint8)
98 : : {
99 : : /// @notice The initialization of ERC4626Upgradeable already assures that decimal are
100 : : /// the same as the underlying asset of the StataTokenV2, e.g. decimals of WETH for stataWETH
101 : 1 : return ERC4626Upgradeable.decimals();
102 : : }
103 : :
104 : : function _claimRewardsOnBehalf(
105 : : address onBehalfOf,
106 : : address receiver,
107 : : address[] memory rewards
108 : : ) internal virtual override whenNotPaused {
109 : 0 : super._claimRewardsOnBehalf(onBehalfOf, receiver, rewards);
110 : : }
111 : :
112 : : // @notice to merge inheritance with ERC20AaveLMUpgradeable.sol properly we put
113 : : // `whenNotPaused` here instead of using ERC20PausableUpgradeable
114 : : function _update(
115 : : address from,
116 : : address to,
117 : : uint256 amount
118 : : ) internal virtual override(ERC20AaveLMUpgradeable, ERC20Upgradeable) whenNotPaused {
119 : 1004 : ERC20AaveLMUpgradeable._update(from, to, amount);
120 : : }
121 : : }
|