Branch data Line data Source code
1 : : // SPDX-License-Identifier: BUSL-1.1
2 : : pragma solidity ^0.8.10;
3 : :
4 : : import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
5 : : import {GPv2SafeERC20} from '../../dependencies/gnosis/contracts/GPv2SafeERC20.sol';
6 : : import {SafeCast} from '../../dependencies/openzeppelin/contracts/SafeCast.sol';
7 : : import {VersionedInitializable} from '../../misc/aave-upgradeability/VersionedInitializable.sol';
8 : : import {Errors} from '../libraries/helpers/Errors.sol';
9 : : import {WadRayMath} from '../libraries/math/WadRayMath.sol';
10 : : import {IPool} from '../../interfaces/IPool.sol';
11 : : import {IAToken} from '../../interfaces/IAToken.sol';
12 : : import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol';
13 : : import {IInitializableAToken} from '../../interfaces/IInitializableAToken.sol';
14 : : import {ScaledBalanceTokenBase} from './base/ScaledBalanceTokenBase.sol';
15 : : import {IncentivizedERC20} from './base/IncentivizedERC20.sol';
16 : : import {EIP712Base} from './base/EIP712Base.sol';
17 : :
18 : : /**
19 : : * @title Aave ERC20 AToken
20 : : * @author Aave
21 : : * @notice Implementation of the interest bearing token for the Aave protocol
22 : : */
23 : : abstract contract AToken is VersionedInitializable, ScaledBalanceTokenBase, EIP712Base, IAToken {
24 : : using WadRayMath for uint256;
25 : : using SafeCast for uint256;
26 : : using GPv2SafeERC20 for IERC20;
27 : :
28 : : bytes32 public constant PERMIT_TYPEHASH =
29 : : keccak256('Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)');
30 : :
31 : : address internal _treasury;
32 : : address internal _underlyingAsset;
33 : :
34 : : /**
35 : : * @dev Constructor.
36 : : * @param pool The address of the Pool contract
37 : : */
38 : : constructor(
39 : : IPool pool
40 : : ) ScaledBalanceTokenBase(pool, 'ATOKEN_IMPL', 'ATOKEN_IMPL', 0) EIP712Base() {
41 : : // Intentionally left blank
42 : : }
43 : :
44 : : /// @inheritdoc IInitializableAToken
45 : : function initialize(
46 : : IPool initializingPool,
47 : : address treasury,
48 : : address underlyingAsset,
49 : : IAaveIncentivesController incentivesController,
50 : : uint8 aTokenDecimals,
51 : : string calldata aTokenName,
52 : : string calldata aTokenSymbol,
53 : : bytes calldata params
54 : : ) public virtual;
55 : :
56 : : /// @inheritdoc IAToken
57 : : function mint(
58 : : address caller,
59 : : address onBehalfOf,
60 : : uint256 amount,
61 : : uint256 index
62 : : ) external virtual override onlyPool returns (bool) {
63 : 43526 : return _mintScaled(caller, onBehalfOf, amount, index);
64 : : }
65 : :
66 : : /// @inheritdoc IAToken
67 : : function burn(
68 : : address from,
69 : : address receiverOfUnderlying,
70 : : uint256 amount,
71 : : uint256 index
72 : : ) external virtual override onlyPool {
73 : 11053 : _burnScaled(from, receiverOfUnderlying, amount, index);
74 : 11051 : if (receiverOfUnderlying != address(this)) {
75 : 10046 : IERC20(_underlyingAsset).safeTransfer(receiverOfUnderlying, amount);
76 : : }
77 : : }
78 : :
79 : : /// @inheritdoc IAToken
80 : : function mintToTreasury(uint256 amount, uint256 index) external virtual override onlyPool {
81 : 6 : if (amount == 0) {
82 : 6 : return;
83 : : }
84 : 5 : _mintScaled(address(POOL), _treasury, amount, index);
85 : : }
86 : :
87 : : /// @inheritdoc IAToken
88 : : function transferOnLiquidation(
89 : : address from,
90 : : address to,
91 : : uint256 value
92 : : ) external virtual override onlyPool {
93 : : // Being a normal transfer, the Transfer() and BalanceTransfer() are emitted
94 : : // so no need to emit a specific event here
95 : 8013 : _transfer(from, to, value, false);
96 : : }
97 : :
98 : : /// @inheritdoc IERC20
99 : : function balanceOf(
100 : : address user
101 : : ) public view virtual override(IncentivizedERC20, IERC20) returns (uint256) {
102 : 31189 : return super.balanceOf(user).rayMul(POOL.getReserveNormalizedIncome(_underlyingAsset));
103 : : }
104 : :
105 : : /// @inheritdoc IERC20
106 : : function totalSupply() public view virtual override(IncentivizedERC20, IERC20) returns (uint256) {
107 : 18137 : uint256 currentSupplyScaled = super.totalSupply();
108 : :
109 : 18137 : if (currentSupplyScaled == 0) {
110 : 1982 : return 0;
111 : : }
112 : :
113 : 16155 : return currentSupplyScaled.rayMul(POOL.getReserveNormalizedIncome(_underlyingAsset));
114 : : }
115 : :
116 : : /// @inheritdoc IAToken
117 : : function RESERVE_TREASURY_ADDRESS() external view override returns (address) {
118 : 43085 : return _treasury;
119 : : }
120 : :
121 : : /// @inheritdoc IAToken
122 : : function UNDERLYING_ASSET_ADDRESS() external view override returns (address) {
123 : 34168 : return _underlyingAsset;
124 : : }
125 : :
126 : : /// @inheritdoc IAToken
127 : : function transferUnderlyingTo(address target, uint256 amount) external virtual override onlyPool {
128 : 15107 : IERC20(_underlyingAsset).safeTransfer(target, amount);
129 : : }
130 : :
131 : : /// @inheritdoc IAToken
132 : : function handleRepayment(
133 : : address user,
134 : : address onBehalfOf,
135 : : uint256 amount
136 : : ) external virtual override onlyPool {
137 : : // Intentionally left blank
138 : : }
139 : :
140 : : /// @inheritdoc IAToken
141 : : function permit(
142 : : address owner,
143 : : address spender,
144 : : uint256 value,
145 : : uint256 deadline,
146 : : uint8 v,
147 : : bytes32 r,
148 : : bytes32 s
149 : : ) external override {
150 : 3015 : require(owner != address(0), Errors.ZERO_ADDRESS_NOT_VALID);
151 : : //solium-disable-next-line
152 : 3014 : require(block.timestamp <= deadline, Errors.INVALID_EXPIRATION);
153 : 3012 : uint256 currentValidNonce = _nonces[owner];
154 : 3012 : bytes32 digest = keccak256(
155 : : abi.encodePacked(
156 : : '\x19\x01',
157 : : DOMAIN_SEPARATOR(),
158 : : keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, currentValidNonce, deadline))
159 : : )
160 : : );
161 : 3012 : require(owner == ecrecover(digest, v, r, s), Errors.INVALID_SIGNATURE);
162 : 1010 : _nonces[owner] = currentValidNonce + 1;
163 : 1010 : _approve(owner, spender, value);
164 : : }
165 : :
166 : : /**
167 : : * @notice Transfers the aTokens between two users. Validates the transfer
168 : : * (ie checks for valid HF after the transfer) if required
169 : : * @param from The source address
170 : : * @param to The destination address
171 : : * @param amount The amount getting transferred
172 : : * @param validate True if the transfer needs to be validated, false otherwise
173 : : */
174 : : function _transfer(address from, address to, uint256 amount, bool validate) internal virtual {
175 : 25055 : address underlyingAsset = _underlyingAsset;
176 : :
177 : 25055 : uint256 index = POOL.getReserveNormalizedIncome(underlyingAsset);
178 : :
179 : 25055 : uint256 fromBalanceBefore = super.balanceOf(from).rayMul(index);
180 : 25055 : uint256 toBalanceBefore = super.balanceOf(to).rayMul(index);
181 : :
182 : 25055 : super._transfer(from, to, amount, index);
183 : :
184 : 25055 : if (validate) {
185 : 17042 : POOL.finalizeTransfer(underlyingAsset, from, to, amount, fromBalanceBefore, toBalanceBefore);
186 : : }
187 : :
188 : 25054 : emit BalanceTransfer(from, to, amount.rayDiv(index), index);
189 : : }
190 : :
191 : : /**
192 : : * @notice Overrides the parent _transfer to force validated transfer() and transferFrom()
193 : : * @param from The source address
194 : : * @param to The destination address
195 : : * @param amount The amount getting transferred
196 : : */
197 : : function _transfer(address from, address to, uint128 amount) internal virtual override {
198 : 17042 : _transfer(from, to, amount, true);
199 : : }
200 : :
201 : : /**
202 : : * @dev Overrides the base function to fully implement IAToken
203 : : * @dev see `EIP712Base.DOMAIN_SEPARATOR()` for more detailed documentation
204 : : */
205 : : function DOMAIN_SEPARATOR() public view override(IAToken, EIP712Base) returns (bytes32) {
206 : 4016 : return super.DOMAIN_SEPARATOR();
207 : : }
208 : :
209 : : /**
210 : : * @dev Overrides the base function to fully implement IAToken
211 : : * @dev see `EIP712Base.nonces()` for more detailed documentation
212 : : */
213 : : function nonces(address owner) public view override(IAToken, EIP712Base) returns (uint256) {
214 : 1008 : return super.nonces(owner);
215 : : }
216 : :
217 : : /// @inheritdoc EIP712Base
218 : : function _EIP712BaseId() internal view override returns (string memory) {
219 : 166698 : return name();
220 : : }
221 : :
222 : : /// @inheritdoc IAToken
223 : : function rescueTokens(address token, address to, uint256 amount) external override onlyPoolAdmin {
224 : 2 : require(token != _underlyingAsset, Errors.UNDERLYING_CANNOT_BE_RESCUED);
225 : 1 : IERC20(token).safeTransfer(to, amount);
226 : : }
227 : : }
|