// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; pragma experimental ABIEncoderV2; import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol'; import {PoolTokenBase} from './base/PoolTokenBase.sol'; import {IVariableDebtToken} from '../../interfaces/IVariableDebtToken.sol'; import {WadRayMath} from '../../tools/math/WadRayMath.sol'; import {Errors} from '../libraries/helpers/Errors.sol'; import {DebtTokenBase} from './base/DebtTokenBase.sol'; import {PoolTokenConfig} from './interfaces/PoolTokenConfig.sol'; import {VersionedInitializable} from '../../tools/upgradeability/VersionedInitializable.sol'; /** * @title VariableDebtToken * @notice Implements a variable debt token to track the borrowing positions of users * at variable rate mode **/ contract VariableDebtToken is DebtTokenBase, VersionedInitializable, IVariableDebtToken { using WadRayMath for uint256; uint256 private constant DEBT_TOKEN_REVISION = 0x1; function initialize( PoolTokenConfig memory config, string memory name, string memory symbol, uint8 decimals, bytes calldata params ) public override initializerRunAlways(DEBT_TOKEN_REVISION) { _initializeERC20(name, symbol, decimals); _initializePoolToken(config, name, symbol, decimals, 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(IERC20, PoolTokenBase) 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); _mintBalance(onBehalfOf, amountScaled, index); 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); _burnBalance(user, amountScaled, index); emit Transfer(user, address(0), amount); emit Burn(user, amount, index); } /** * @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(IERC20, PoolTokenBase) 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()); } }