mirror of
				https://github.com/Instadapp/aave-protocol-v2.git
				synced 2024-07-29 21:47:30 +00:00 
			
		
		
		
	Optimized debt tokens
This commit is contained in:
		
							parent
							
								
									4d054dd56d
								
							
						
					
					
						commit
						5b7a2f2a55
					
				| 
						 | 
				
			
			@ -11,27 +11,17 @@ import {IStableDebtToken} from './interfaces/IStableDebtToken.sol';
 | 
			
		|||
 | 
			
		||||
/**
 | 
			
		||||
 * @title contract StableDebtToken
 | 
			
		||||
 *
 | 
			
		||||
 * @notice defines the interface for the stable debt token
 | 
			
		||||
 *
 | 
			
		||||
 * @dev it does not inherit from IERC20 to save in code size
 | 
			
		||||
 *
 | 
			
		||||
 * @notice Implements a stable debt token to track the user positions
 | 
			
		||||
 * @author Aave
 | 
			
		||||
 *
 | 
			
		||||
 **/
 | 
			
		||||
contract StableDebtToken is IStableDebtToken, DebtTokenBase {
 | 
			
		||||
  using SafeMath for uint256;
 | 
			
		||||
  using WadRayMath for uint256;
 | 
			
		||||
 | 
			
		||||
  uint256 public constant DEBT_TOKEN_REVISION = 0x1;
 | 
			
		||||
  struct UserData {
 | 
			
		||||
    uint256 currentRate;
 | 
			
		||||
    uint40 lastUpdateTimestamp;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  uint256 private avgStableRate;
 | 
			
		||||
 | 
			
		||||
  mapping(address => UserData) private _usersData;
 | 
			
		||||
  uint256 private _avgStableRate;
 | 
			
		||||
  mapping(address => uint40) _timestamps;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    address pool,
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +43,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
 | 
			
		|||
   * @return the average stable rate
 | 
			
		||||
   **/
 | 
			
		||||
  function getAverageStableRate() external virtual override view returns (uint256) {
 | 
			
		||||
    return avgStableRate;
 | 
			
		||||
    return _avgStableRate;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +51,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
 | 
			
		|||
   * @return the last update timestamp
 | 
			
		||||
   **/
 | 
			
		||||
  function getUserLastUpdated(address user) external virtual override view returns (uint40) {
 | 
			
		||||
    return _usersData[user].lastUpdateTimestamp;
 | 
			
		||||
    return _timestamps[user];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +60,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
 | 
			
		|||
   * @return the stable rate of user
 | 
			
		||||
   **/
 | 
			
		||||
  function getUserStableRate(address user) external virtual override view returns (uint256) {
 | 
			
		||||
    return _usersData[user].currentRate;
 | 
			
		||||
    return _usersData[user].dataField;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			@ -78,16 +68,14 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
 | 
			
		|||
   * @return the accumulated debt of the user
 | 
			
		||||
   **/
 | 
			
		||||
  function balanceOf(address account) public virtual override view returns (uint256) {
 | 
			
		||||
    uint256 accountBalance = _balances[account];
 | 
			
		||||
    uint256 accountBalance = _usersData[account].balance;
 | 
			
		||||
    uint256 stableRate = _usersData[account].dataField;
 | 
			
		||||
    if (accountBalance == 0) {
 | 
			
		||||
      return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UserData storage userData = _usersData[account];
 | 
			
		||||
 | 
			
		||||
    uint256 cumulatedInterest = MathUtils.calculateCompoundedInterest(
 | 
			
		||||
      userData.currentRate,
 | 
			
		||||
      userData.lastUpdateTimestamp
 | 
			
		||||
      stableRate,
 | 
			
		||||
      _timestamps[account]
 | 
			
		||||
    );
 | 
			
		||||
    return accountBalance.wadToRay().rayMul(cumulatedInterest).rayToWad();
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -126,19 +114,20 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
 | 
			
		|||
    vars.amountInRay = amount.wadToRay();
 | 
			
		||||
 | 
			
		||||
    //calculates the new stable rate for the user
 | 
			
		||||
    vars.newStableRate = _usersData[user]
 | 
			
		||||
      .currentRate
 | 
			
		||||
    vars.newStableRate = uint256(_usersData[user]
 | 
			
		||||
      .dataField)
 | 
			
		||||
      .rayMul(currentBalance.wadToRay())
 | 
			
		||||
      .add(vars.amountInRay.rayMul(rate))
 | 
			
		||||
      .rayDiv(currentBalance.add(amount).wadToRay());
 | 
			
		||||
 | 
			
		||||
    _usersData[user].currentRate = vars.newStableRate;
 | 
			
		||||
    require(vars.newStableRate < (1 << 128), "Debt token: stable rate overflow");
 | 
			
		||||
    _usersData[user].dataField = uint128(vars.newStableRate);
 | 
			
		||||
 | 
			
		||||
    //solium-disable-next-line
 | 
			
		||||
    _usersData[user].lastUpdateTimestamp = uint40(block.timestamp);
 | 
			
		||||
    _timestamps[user] = uint40(block.timestamp);
 | 
			
		||||
 | 
			
		||||
    //calculates the updated average stable rate
 | 
			
		||||
    avgStableRate = avgStableRate
 | 
			
		||||
    _avgStableRate = _avgStableRate
 | 
			
		||||
      .rayMul(vars.supplyBeforeMint.wadToRay())
 | 
			
		||||
      .add(rate.rayMul(vars.amountInRay))
 | 
			
		||||
      .rayDiv(vars.supplyAfterMint.wadToRay());
 | 
			
		||||
| 
						 | 
				
			
			@ -171,20 +160,20 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
 | 
			
		|||
    uint256 supplyAfterBurn = supplyBeforeBurn.sub(amount);
 | 
			
		||||
 | 
			
		||||
    if (supplyAfterBurn == 0) {
 | 
			
		||||
      avgStableRate = 0;
 | 
			
		||||
      _avgStableRate = 0;
 | 
			
		||||
    } else {
 | 
			
		||||
      avgStableRate = avgStableRate
 | 
			
		||||
      _avgStableRate = _avgStableRate
 | 
			
		||||
        .rayMul(supplyBeforeBurn.wadToRay())
 | 
			
		||||
        .sub(_usersData[user].currentRate.rayMul(amount.wadToRay()))
 | 
			
		||||
        .sub(uint256(_usersData[user].dataField).rayMul(amount.wadToRay()))
 | 
			
		||||
        .rayDiv(supplyAfterBurn.wadToRay());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (amount == currentBalance) {
 | 
			
		||||
      _usersData[user].currentRate = 0;
 | 
			
		||||
      _usersData[user].lastUpdateTimestamp = 0;
 | 
			
		||||
      _usersData[user].dataField = 0;
 | 
			
		||||
      _timestamps[user] = 0;
 | 
			
		||||
    } else {
 | 
			
		||||
      //solium-disable-next-line
 | 
			
		||||
      _usersData[user].lastUpdateTimestamp = uint40(block.timestamp);
 | 
			
		||||
      _timestamps[user] = uint40(block.timestamp);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (balanceIncrease > amount) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,10 +9,9 @@ import {WadRayMath} from '../libraries/math/WadRayMath.sol';
 | 
			
		|||
import {IVariableDebtToken} from './interfaces/IVariableDebtToken.sol';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @title interface IVariableDebtToken
 | 
			
		||||
 * @title contract VariableDebtToken
 | 
			
		||||
 * @notice Implements a variable debt token to track the user positions
 | 
			
		||||
 * @author Aave
 | 
			
		||||
 * @notice defines the basic interface for a variable debt token.
 | 
			
		||||
 * @dev does not inherit from IERC20 to save in contract size
 | 
			
		||||
 **/
 | 
			
		||||
contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
 | 
			
		||||
  using SafeMath for uint256;
 | 
			
		||||
| 
						 | 
				
			
			@ -20,8 +19,6 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
 | 
			
		|||
 | 
			
		||||
  uint256 public constant DEBT_TOKEN_REVISION = 0x1;
 | 
			
		||||
 | 
			
		||||
  mapping(address => uint256) private _userIndexes;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    address pool,
 | 
			
		||||
    address underlyingAsset,
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +39,8 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
 | 
			
		|||
   * @return the debt balance of the user
 | 
			
		||||
   **/
 | 
			
		||||
  function balanceOf(address user) public virtual override view returns (uint256) {
 | 
			
		||||
    uint256 userBalance = _balances[user];
 | 
			
		||||
    uint256 userBalance = _usersData[user].balance;
 | 
			
		||||
    uint256 index = _usersData[user].dataField;
 | 
			
		||||
    if (userBalance == 0) {
 | 
			
		||||
      return 0;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +49,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
 | 
			
		|||
      userBalance
 | 
			
		||||
        .wadToRay()
 | 
			
		||||
        .rayMul(_pool.getReserveNormalizedVariableDebt(_underlyingAssetAddress))
 | 
			
		||||
        .rayDiv(_userIndexes[user])
 | 
			
		||||
        .rayDiv(index)
 | 
			
		||||
        .rayToWad();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +59,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
 | 
			
		|||
   **/
 | 
			
		||||
 | 
			
		||||
  function getUserIndex(address user) external virtual override view returns (uint256) {
 | 
			
		||||
    return _userIndexes[user];
 | 
			
		||||
    return _usersData[user].dataField;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			@ -79,7 +77,8 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
 | 
			
		|||
    _mint(user, amount.add(balanceIncrease));
 | 
			
		||||
 | 
			
		||||
    uint256 newUserIndex = _pool.getReserveNormalizedVariableDebt(_underlyingAssetAddress);
 | 
			
		||||
    _userIndexes[user] = newUserIndex;
 | 
			
		||||
    require(newUserIndex < (1 << 128), "Debt token: Index overflow");
 | 
			
		||||
    _usersData[user].dataField = uint128(newUserIndex);
 | 
			
		||||
 | 
			
		||||
    emit MintDebt(user, amount, previousBalance, currentBalance, balanceIncrease, newUserIndex);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -106,8 +105,9 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
 | 
			
		|||
    //if user not repaid everything
 | 
			
		||||
    if (currentBalance != amount) {
 | 
			
		||||
      newUserIndex = _pool.getReserveNormalizedVariableDebt(_underlyingAssetAddress);
 | 
			
		||||
      require(newUserIndex < (1 << 128), "Debt token: Index overflow");
 | 
			
		||||
    }
 | 
			
		||||
    _userIndexes[user] = newUserIndex;
 | 
			
		||||
    _usersData[user].dataField = uint128(newUserIndex);
 | 
			
		||||
 | 
			
		||||
    emit BurnDebt(user, amount, previousBalance, currentBalance, balanceIncrease, newUserIndex);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,7 +27,14 @@ abstract contract DebtTokenBase is IERC20Detailed, VersionedInitializable {
 | 
			
		|||
  address internal immutable _underlyingAssetAddress;
 | 
			
		||||
 | 
			
		||||
  ILendingPool internal immutable _pool;
 | 
			
		||||
  mapping(address => uint256) internal _balances;
 | 
			
		||||
 | 
			
		||||
  struct UserData{
 | 
			
		||||
    uint128 balance;
 | 
			
		||||
    //this field will store the user index for the variable debt token, and the user stable rate for the stable debt token
 | 
			
		||||
    uint128 dataField; 
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  mapping(address => UserData) internal _usersData;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @dev only lending pool can call functions marked by this modifier
 | 
			
		||||
| 
						 | 
				
			
			@ -96,7 +103,7 @@ abstract contract DebtTokenBase is IERC20Detailed, VersionedInitializable {
 | 
			
		|||
   * @return the debt balance of the user since the last burn/mint action
 | 
			
		||||
   **/
 | 
			
		||||
  function principalBalanceOf(address user) public view returns (uint256) {
 | 
			
		||||
    return _balances[user];
 | 
			
		||||
    return _usersData[user].balance;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			@ -106,7 +113,9 @@ abstract contract DebtTokenBase is IERC20Detailed, VersionedInitializable {
 | 
			
		|||
   **/
 | 
			
		||||
  function _mint(address user, uint256 amount) internal {
 | 
			
		||||
    _totalSupply = _totalSupply.add(amount);
 | 
			
		||||
    _balances[user] = _balances[user].add(amount);
 | 
			
		||||
    uint256 result = amount.add(_usersData[user].balance);
 | 
			
		||||
    require(result < (1 << 128), "Debt token: balance overflow");
 | 
			
		||||
    _usersData[user].balance = uint128(result);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			@ -116,7 +125,9 @@ abstract contract DebtTokenBase is IERC20Detailed, VersionedInitializable {
 | 
			
		|||
   **/
 | 
			
		||||
  function _burn(address user, uint256 amount) internal {
 | 
			
		||||
    _totalSupply = _totalSupply.sub(amount);
 | 
			
		||||
    _balances[user] = _balances[user].sub(amount);
 | 
			
		||||
    uint256 result = uint256(_usersData[user].balance).sub(amount);
 | 
			
		||||
    require(result < (1 << 128), "Debt token: balance overflow");
 | 
			
		||||
    _usersData[user].balance = uint128(result);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			@ -176,7 +187,7 @@ abstract contract DebtTokenBase is IERC20Detailed, VersionedInitializable {
 | 
			
		|||
      uint256
 | 
			
		||||
    )
 | 
			
		||||
  {
 | 
			
		||||
    uint256 previousPrincipalBalance = _balances[user];
 | 
			
		||||
    uint256 previousPrincipalBalance = _usersData[user].balance;
 | 
			
		||||
 | 
			
		||||
    if (previousPrincipalBalance == 0) {
 | 
			
		||||
      return (0, 0, 0);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user