mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
283 lines
8.6 KiB
Solidity
283 lines
8.6 KiB
Solidity
// SPDX-License-Identifier: agpl-3.0
|
|
pragma solidity 0.6.12;
|
|
|
|
import {IVariableDebtToken} from '../../interfaces/IVariableDebtToken.sol';
|
|
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
|
|
import {Errors} from '../libraries/helpers/Errors.sol';
|
|
import {DebtTokenBase} from './base/DebtTokenBase.sol';
|
|
import {ILendingPool} from '../../interfaces/ILendingPool.sol';
|
|
import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol';
|
|
|
|
/**
|
|
* @title VariableDebtToken
|
|
* @notice Implements a variable debt token to track the borrowing positions of users
|
|
* at variable rate mode
|
|
* @author Aave
|
|
**/
|
|
contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
|
|
using WadRayMath for uint256;
|
|
|
|
bytes public constant EIP712_REVISION = bytes('1');
|
|
bytes32 internal constant EIP712_DOMAIN =
|
|
keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)');
|
|
bytes32 public constant PERMIT_DELEGATION_TYPEHASH =
|
|
keccak256(
|
|
'PermitDelegation(address delegator,address delegatee,uint256 value,uint256 nonce,uint256 deadline)'
|
|
);
|
|
|
|
uint256 public constant DEBT_TOKEN_REVISION = 0x2;
|
|
|
|
ILendingPool internal _pool;
|
|
address internal _underlyingAsset;
|
|
IAaveIncentivesController internal _incentivesController;
|
|
|
|
mapping(address => uint256) public _nonces;
|
|
bytes32 public DOMAIN_SEPARATOR;
|
|
|
|
/**
|
|
* @dev Initializes the debt token.
|
|
* @param pool The address of the lending pool where this aToken will be used
|
|
* @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH)
|
|
* @param incentivesController The smart contract managing potential incentives distribution
|
|
* @param debtTokenDecimals The decimals of the debtToken, same as the underlying asset's
|
|
* @param debtTokenName The name of the token
|
|
* @param debtTokenSymbol The symbol of the token
|
|
*/
|
|
function initialize(
|
|
ILendingPool pool,
|
|
address underlyingAsset,
|
|
IAaveIncentivesController incentivesController,
|
|
uint8 debtTokenDecimals,
|
|
string memory debtTokenName,
|
|
string memory debtTokenSymbol,
|
|
bytes calldata params
|
|
) public override initializer {
|
|
uint256 chainId;
|
|
|
|
//solium-disable-next-line
|
|
assembly {
|
|
chainId := chainid()
|
|
}
|
|
|
|
_setName(debtTokenName);
|
|
_setSymbol(debtTokenSymbol);
|
|
_setDecimals(debtTokenDecimals);
|
|
|
|
_pool = pool;
|
|
_underlyingAsset = underlyingAsset;
|
|
_incentivesController = incentivesController;
|
|
|
|
DOMAIN_SEPARATOR = keccak256(
|
|
abi.encode(
|
|
EIP712_DOMAIN,
|
|
keccak256(bytes(debtTokenName)),
|
|
keccak256(EIP712_REVISION),
|
|
chainId,
|
|
address(this)
|
|
)
|
|
);
|
|
|
|
emit Initialized(
|
|
underlyingAsset,
|
|
address(pool),
|
|
address(incentivesController),
|
|
debtTokenDecimals,
|
|
debtTokenName,
|
|
debtTokenSymbol,
|
|
params
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @dev Gets the revision of the stable debt token implementation
|
|
* @return The debt token implementation revision
|
|
**/
|
|
function getRevision() internal pure virtual override returns (uint256) {
|
|
return DEBT_TOKEN_REVISION;
|
|
}
|
|
|
|
/**
|
|
* @dev Calculates the accumulated debt balance of the user
|
|
* @return The debt balance of the user
|
|
**/
|
|
function balanceOf(address user) public view virtual override returns (uint256) {
|
|
uint256 scaledBalance = super.balanceOf(user);
|
|
|
|
if (scaledBalance == 0) {
|
|
return 0;
|
|
}
|
|
|
|
return scaledBalance.rayMul(_pool.getReserveNormalizedVariableDebt(_underlyingAsset));
|
|
}
|
|
|
|
/**
|
|
* @dev Mints debt token to the `onBehalfOf` address
|
|
* - Only callable by the LendingPool
|
|
* @param user The address receiving the borrowed underlying, being the delegatee in case
|
|
* of credit delegate, or same as `onBehalfOf` otherwise
|
|
* @param onBehalfOf The address receiving the debt tokens
|
|
* @param amount The amount of debt being minted
|
|
* @param index The variable debt index of the reserve
|
|
* @return `true` if the the previous balance of the user is 0
|
|
**/
|
|
function mint(
|
|
address user,
|
|
address onBehalfOf,
|
|
uint256 amount,
|
|
uint256 index
|
|
) external override onlyLendingPool returns (bool) {
|
|
if (user != onBehalfOf) {
|
|
_decreaseBorrowAllowance(onBehalfOf, user, amount);
|
|
}
|
|
|
|
uint256 previousBalance = super.balanceOf(onBehalfOf);
|
|
uint256 amountScaled = amount.rayDiv(index);
|
|
require(amountScaled != 0, Errors.CT_INVALID_MINT_AMOUNT);
|
|
|
|
_mint(onBehalfOf, amountScaled);
|
|
|
|
emit Transfer(address(0), onBehalfOf, amount);
|
|
emit Mint(user, onBehalfOf, amount, index);
|
|
|
|
return previousBalance == 0;
|
|
}
|
|
|
|
/**
|
|
* @dev Burns user variable debt
|
|
* - Only callable by the LendingPool
|
|
* @param user The user whose debt is getting burned
|
|
* @param amount The amount getting burned
|
|
* @param index The variable debt index of the reserve
|
|
**/
|
|
function burn(
|
|
address user,
|
|
uint256 amount,
|
|
uint256 index
|
|
) external override onlyLendingPool {
|
|
uint256 amountScaled = amount.rayDiv(index);
|
|
require(amountScaled != 0, Errors.CT_INVALID_BURN_AMOUNT);
|
|
|
|
_burn(user, amountScaled);
|
|
|
|
emit Transfer(user, address(0), amount);
|
|
emit Burn(user, amount, index);
|
|
}
|
|
|
|
/**
|
|
* @dev implements the credit delegation with ERC712 signature
|
|
* @param delegator The delegator of the credit
|
|
* @param delegatee The delegatee that can use the credit
|
|
* @param value The amount to be delegated
|
|
* @param deadline The deadline timestamp, type(uint256).max for max deadline
|
|
* @param v Signature param
|
|
* @param s Signature param
|
|
* @param r Signature param
|
|
*/
|
|
function permitDelegation(
|
|
address delegator,
|
|
address delegatee,
|
|
uint256 value,
|
|
uint256 deadline,
|
|
uint8 v,
|
|
bytes32 r,
|
|
bytes32 s
|
|
) external override {
|
|
require(delegator != address(0), 'INVALID_DELEGATOR');
|
|
//solium-disable-next-line
|
|
require(block.timestamp <= deadline, 'INVALID_EXPIRATION');
|
|
uint256 currentValidNonce = _nonces[delegator];
|
|
bytes32 digest =
|
|
keccak256(
|
|
abi.encodePacked(
|
|
'\x19\x01',
|
|
DOMAIN_SEPARATOR,
|
|
keccak256(
|
|
abi.encode(
|
|
PERMIT_DELEGATION_TYPEHASH,
|
|
delegator,
|
|
delegatee,
|
|
value,
|
|
currentValidNonce,
|
|
deadline
|
|
)
|
|
)
|
|
)
|
|
);
|
|
require(delegator == ecrecover(digest, v, r, s), 'INVALID_SIGNATURE');
|
|
_nonces[delegator] = currentValidNonce.add(1);
|
|
_approveDelegation(delegator, delegatee, value);
|
|
}
|
|
|
|
/**
|
|
* @dev Returns the principal debt balance of the user from
|
|
* @return The debt balance of the user since the last burn/mint action
|
|
**/
|
|
function scaledBalanceOf(address user) public view virtual override returns (uint256) {
|
|
return super.balanceOf(user);
|
|
}
|
|
|
|
/**
|
|
* @dev Returns the total supply of the variable debt token. Represents the total debt accrued by the users
|
|
* @return The total supply
|
|
**/
|
|
function totalSupply() public view virtual override returns (uint256) {
|
|
return super.totalSupply().rayMul(_pool.getReserveNormalizedVariableDebt(_underlyingAsset));
|
|
}
|
|
|
|
/**
|
|
* @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index)
|
|
* @return the scaled total supply
|
|
**/
|
|
function scaledTotalSupply() public view virtual override returns (uint256) {
|
|
return super.totalSupply();
|
|
}
|
|
|
|
/**
|
|
* @dev Returns the principal balance of the user and principal total supply.
|
|
* @param user The address of the user
|
|
* @return The principal balance of the user
|
|
* @return The principal total supply
|
|
**/
|
|
function getScaledUserBalanceAndSupply(address user)
|
|
external
|
|
view
|
|
override
|
|
returns (uint256, uint256)
|
|
{
|
|
return (super.balanceOf(user), super.totalSupply());
|
|
}
|
|
|
|
/**
|
|
* @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH)
|
|
**/
|
|
function UNDERLYING_ASSET_ADDRESS() public view returns (address) {
|
|
return _underlyingAsset;
|
|
}
|
|
|
|
/**
|
|
* @dev Returns the address of the incentives controller contract
|
|
**/
|
|
function getIncentivesController() external view override returns (IAaveIncentivesController) {
|
|
return _getIncentivesController();
|
|
}
|
|
|
|
/**
|
|
* @dev Returns the address of the lending pool where this aToken is used
|
|
**/
|
|
function POOL() public view returns (ILendingPool) {
|
|
return _pool;
|
|
}
|
|
|
|
function _getIncentivesController() internal view override returns (IAaveIncentivesController) {
|
|
return _incentivesController;
|
|
}
|
|
|
|
function _getUnderlyingAssetAddress() internal view override returns (address) {
|
|
return _underlyingAsset;
|
|
}
|
|
|
|
function _getLendingPool() internal view override returns (ILendingPool) {
|
|
return _pool;
|
|
}
|
|
}
|