Added natspec comments to stable debt token, cleaned up stable debt token code

This commit is contained in:
emilio 2020-07-09 11:23:30 +02:00
parent da6273a951
commit 7813e8cec0
12 changed files with 133 additions and 118 deletions

View File

@ -186,14 +186,14 @@ contract TokenDistributor is ReentrancyGuard, VersionedInitializable {
require(_success, "ERROR_ON_EXCHANGE");
_amountToBurn = abi.decode(_result, (uint256));
}
internalBurn(_amountToBurn);
_burn(_amountToBurn);
}
}
}
/// @notice Internal function to send _amount of tokenToBurn to the 0x0 address
/// @param _amount The amount to burn
function internalBurn(uint256 _amount) internal {
function _burn(uint256 _amount) internal {
require(IERC20(tokenToBurn).transfer(recipientBurn, _amount), "INTERNAL_BURN. Reverted transfer to recipientBurn address");
emit Burn(_amount);
}

View File

@ -211,8 +211,6 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl
}
}
console.log("Balance before liquidation is %s", IERC20(principalReserve.stableDebtTokenAddress).balanceOf(_user));
//TODO Burn debt tokens
if(vars.userVariableDebt >= vars.actualAmountToLiquidate){
IVariableDebtToken(principalReserve.variableDebtTokenAddress).burn(_user, vars.actualAmountToLiquidate);
@ -222,8 +220,6 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl
IStableDebtToken(principalReserve.stableDebtTokenAddress).burn(_user, vars.actualAmountToLiquidate.sub(vars.userVariableDebt));
}
console.log("Balance after liquidation is %s", IERC20(principalReserve.stableDebtTokenAddress).balanceOf(_user));
vars.collateralAtoken = AToken(collateralReserve.aTokenAddress);
//if liquidator reclaims the aToken, he receives the equivalent atoken amount
@ -237,13 +233,10 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl
//otherwise receives the underlying asset
//burn the equivalent amount of atoken
vars.collateralAtoken.burnOnLiquidation(_user, vars.maxCollateralToLiquidate);
console.log("Burned %s collateral tokens, collateral %s",vars.maxCollateralToLiquidate, _collateral);
IERC20(_collateral).universalTransfer(msg.sender, vars.maxCollateralToLiquidate);
}
console.log("Transferring principal, amount %s",vars.actualAmountToLiquidate);
//transfers the principal currency to the pool
IERC20(_reserve).universalTransferFromSenderToThis(vars.actualAmountToLiquidate, true);

View File

@ -238,8 +238,6 @@ library GenericLogic {
uint256 liquidationThreshold
) internal view returns (uint256) {
console.log("Borrow balance ETH is %s", borrowBalanceETH);
if (borrowBalanceETH == 0) return uint256(-1);
return

View File

@ -38,11 +38,8 @@ library UniversalERC20 {
}
if (isETH(token)) {
console.log("transfer of ETH, value %s", amount);
console.log("Balance is %s", address(this).balance);
(bool result, ) = payable(to).call{value: amount, gas: DEFAULT_TRANSFER_GAS}('');
console.log("Transfer done, result %s", result);
require(result, 'ETH_TRANSFER_FAILED');
} else {

View File

@ -1,14 +1,24 @@
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/GSN/Context.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/math/SafeMath.sol';
import '@openzeppelin/contracts/utils/Address.sol';
import {Context} from '@openzeppelin/contracts/GSN/Context.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
import {Address} from '@openzeppelin/contracts/utils/Address.sol';
import {DebtTokenBase} from './base/DebtTokenBase.sol';
import {MathUtils} from '../libraries/MathUtils.sol';
import {WadRayMath} from '../libraries/WadRayMath.sol';
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
*
* @author Aave
*
**/
contract StableDebtToken is IStableDebtToken, DebtTokenBase {
using SafeMath for uint256;
using WadRayMath for uint256;
@ -23,6 +33,15 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
mapping(address => UserData) usersData;
/**
* @dev emitted when new stable debt is minted
* @param _user the address of the user
* @param _amount the amount minted
* @param _previousBalance the previous balance of the user
* @param _currentBalance the current balance of the user
* @param _balanceIncrease the debt increase since the last update
* @param _newRate the rate of the debt after the minting
**/
event mintDebt(
address _user,
uint256 _amount,
@ -31,6 +50,15 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
uint256 _balanceIncrease,
uint256 _newRate
);
/**
* @dev emitted when new stable debt is burned
* @param _user the address of the user
* @param _amount the amount minted
* @param _previousBalance the previous balance of the user
* @param _currentBalance the current balance of the user
* @param _balanceIncrease the debt increase since the last update
**/
event burnDebt(
address _user,
uint256 _amount,
@ -52,9 +80,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
return usersData[_user].currentRate;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public virtual override view returns (uint256) {
if(balances[account] == 0) {
return 0;
@ -69,15 +95,6 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
return balances[account].wadToRay().rayMul(cumulatedInterest).rayToWad();
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements
*
* - `to` cannot be the zero address.
*/
struct MintLocalVars {
uint256 newSupply;
@ -85,45 +102,55 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
uint256 newStableRate;
}
/**
* @dev mints debt token to the target user. The resulting rate is the weighted average
* between the rate of the new debt and the rate of the previous debt
* @param _user the address of the user
* @param _amount the amount of debt tokens to mint
* @param _rate the rate of the debt being minted.
**/
function mint(
address account,
uint256 amount,
uint256 rate
address _user,
uint256 _amount,
uint256 _rate
) public override onlyLendingPool {
MintLocalVars memory vars;
//cumulates the user debt
(
uint256 previousBalance,
uint256 currentBalance,
uint256 balanceIncrease
) = internalCumulateBalance(account);
) = _cumulateBalance(_user);
vars.newSupply = totalSupply.add(_amount);
vars.newSupply = totalSupply.add(amount);
vars.amountInRay = _amount.wadToRay();
vars.amountInRay = amount.wadToRay();
vars.newStableRate = usersData[account]
//calculates the new stable rate for the user
vars.newStableRate = usersData[_user]
.currentRate
.rayMul(currentBalance.wadToRay())
.add(vars.amountInRay.rayMul(rate))
.rayDiv(currentBalance.add(amount).wadToRay());
.add(vars.amountInRay.rayMul(_rate))
.rayDiv(currentBalance.add(_amount).wadToRay());
usersData[account].currentRate = vars.newStableRate;
usersData[_user].currentRate = vars.newStableRate;
usersData[account].lastUpdateTimestamp = uint40(block.timestamp);
//solium-disable-next-line
usersData[_user].lastUpdateTimestamp = uint40(block.timestamp);
//calculates the updated average stable rate
avgStableRate = avgStableRate
.rayMul(totalSupply.wadToRay())
.add(rate.rayMul(vars.amountInRay))
.add(_rate.rayMul(vars.amountInRay))
.rayDiv(vars.newSupply.wadToRay());
internalMint(account, amount);
_mint(_user, _amount);
emit mintDebt(
account,
amount,
_user,
_amount,
previousBalance,
currentBalance,
balanceIncrease,
@ -132,22 +159,16 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function burn(address _account, uint256 _amount) public override onlyLendingPool {
* @dev burns debt of the target user.
* @param _user the address of the user
* @param _amount the amount of debt tokens to mint
**/
function burn(address _user, uint256 _amount) public override onlyLendingPool {
(
uint256 previousBalance,
uint256 currentBalance,
uint256 balanceIncrease
) = internalCumulateBalance(_account);
) = _cumulateBalance(_user);
uint256 newSupply = totalSupply.sub(_amount);
@ -158,18 +179,18 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
} else {
avgStableRate = avgStableRate
.rayMul(totalSupply.wadToRay())
.sub(usersData[_account].currentRate.rayMul(amountInRay))
.sub(usersData[_user].currentRate.rayMul(amountInRay))
.rayDiv(newSupply.wadToRay());
}
if(_amount == currentBalance){
usersData[_account].currentRate = 0;
usersData[_account].lastUpdateTimestamp = 0;
usersData[_user].currentRate = 0;
usersData[_user].lastUpdateTimestamp = 0;
}
internalBurn(_account, _amount);
_burn(_user, _amount);
emit burnDebt(_account, _amount, previousBalance, currentBalance, balanceIncrease);
emit burnDebt(_user, _amount, previousBalance, currentBalance, balanceIncrease);
}
/**
@ -177,7 +198,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
* @param _user the address of the user for which the interest is being accumulated
* @return the previous principal balance, the new principal balance, the balance increase
**/
function internalCumulateBalance(address _user)
function _cumulateBalance(address _user)
internal
returns (
uint256,
@ -194,7 +215,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
//calculate the accrued interest since the last accumulation
uint256 balanceIncrease = balanceOf(_user).sub(previousPrincipalBalance);
//mints an amount of tokens equivalent to the amount accumulated
internalMint(_user, balanceIncrease);
_mint(_user, balanceIncrease);
return (
previousPrincipalBalance,

View File

@ -69,7 +69,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
uint256 balanceIncrease
) = internalCumulateBalance(account);
internalMint(account, amount);
_mint(account, amount);
userIndexes[account] = pool.getReserveNormalizedVariableDebt(underlyingAssetAddress);
@ -94,7 +94,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
uint256 balanceIncrease
) = internalCumulateBalance(account);
internalBurn(account, amount);
_burn(account, amount);
//if user repaid everything
if (currentBalance == amount) {
@ -130,7 +130,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
uint256 balanceIncrease = balanceOf(_user).sub(previousPrincipalBalance);
//mints an amount of tokens equivalent to the amount accumulated
internalMint(_user, balanceIncrease);
_mint(_user, balanceIncrease);
return (
previousPrincipalBalance,

View File

@ -152,12 +152,12 @@ abstract contract DebtTokenBase is IERC20 {
revert('ALLOWANCE_NOT_SUPPORTED');
}
function internalMint(address account, uint256 amount) internal {
function _mint(address account, uint256 amount) internal {
totalSupply = totalSupply.add(amount);
balances[account] = balances[account].add(amount);
}
function internalBurn(address account, uint256 amount) internal {
function _burn(address account, uint256 amount) internal {
totalSupply = totalSupply.sub(amount);
balances[account] = balances[account].sub(amount);
}

View File

@ -1,19 +1,54 @@
pragma solidity ^0.6.0;
/**
* @title interface IStableDebtToken
*
* @notice defines the interface for the stable debt token
*
* @dev it does not inherit from IERC20 to save in code size
*
* @author Aave
*
**/
interface IStableDebtToken {
/**
* @dev mints debt token to the target user. The resulting rate is the weighted average
* between the rate of the new debt and the rate of the previous debt
* @param _user the address of the user
* @param _amount the amount of debt tokens to mint
* @param _rate the rate of the debt being minted.
**/
function mint(
address account,
uint256 amount,
uint256 rate
address _user,
uint256 _amount,
uint256 _rate
) external virtual;
function burn(address _account, uint256 _amount) external virtual;
/**
* @dev burns debt of the target user.
* @param _user the address of the user
* @param _amount the amount of debt tokens to mint
**/
function burn(address _user, uint256 _amount) external virtual;
/**
* @dev returns the average rate of all the stable rate loans.
* @return the average stable rate
**/
function getAverageStableRate() external virtual view returns(uint256);
/**
* @dev returns the stable rate of the user debt
* @return the stable rate of the user
**/
function getUserStableRate(address _user) external virtual view returns(uint256);
/**
* @dev returns the timestamp of the last update of the user
* @return the timestamp
**/
function getUserLastUpdated(address _user) external virtual view returns (uint40);
}

View File

@ -70,7 +70,7 @@
},
"PriceOracle": {
"buidlerevm": {
"address": "0x8731324a6C09a1745bD15009Dc8FcceF11c05F4a",
"address": "0x85bdE212E66e2BAE510E44Ed59116c1eC712795b",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
},
"localhost": {
@ -80,7 +80,7 @@
},
"MockAggregator": {
"buidlerevm": {
"address": "0x474d9b0D5F1Bb1602711F9346743a7a7478d6f52",
"address": "0xAF6BA11790D1942625C0c2dA07da19AB63845cfF",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
},
"localhost": {
@ -90,7 +90,7 @@
},
"ChainlinkProxyPriceProvider": {
"buidlerevm": {
"address": "0xf91aC1098F3b154671Ce83290114aaE45ac0225f",
"address": "0xD83D2773a7873ae2b5f8Fb92097e20a8C64F691E",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
},
"localhost": {
@ -100,7 +100,7 @@
},
"LendingRateOracle": {
"buidlerevm": {
"address": "0xf4830d6b1D70C8595d3BD8A63f9ed9F636DB9ef2",
"address": "0xf91aC1098F3b154671Ce83290114aaE45ac0225f",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
},
"localhost": {
@ -110,7 +110,7 @@
},
"DefaultReserveInterestRateStrategy": {
"buidlerevm": {
"address": "0xC8Df507578fEfb60aA626ABFDDB20B48ee439ad1",
"address": "0x2dD8146Ad2138ac61F93E549f8F917927B47E28a",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
},
"localhost": {
@ -146,7 +146,7 @@
},
"TokenDistributor": {
"buidlerevm": {
"address": "0x24E420B42971372F060a93129846761F354Bc50B"
"address": "0xC5f7aC6895DcB76877E71db756433fB0E0478FEB"
},
"localhost": {
"address": "0xb840b4fe440b5E26e1840cd2D6320FAda1C0ca5d"
@ -154,7 +154,7 @@
},
"InitializableAdminUpgradeabilityProxy": {
"buidlerevm": {
"address": "0x24E420B42971372F060a93129846761F354Bc50B",
"address": "0xC5f7aC6895DcB76877E71db756433fB0E0478FEB",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
},
"localhost": {
@ -164,7 +164,7 @@
},
"MockFlashLoanReceiver": {
"buidlerevm": {
"address": "0x1a432D97211e8b2CD53DF262c8Da0EfeBa6b6b3D"
"address": "0x24E420B42971372F060a93129846761F354Bc50B"
},
"localhost": {
"address": "0x5c98c9202b73d27A618662d34A6805c34AB041B8"
@ -172,7 +172,7 @@
},
"WalletBalanceProvider": {
"buidlerevm": {
"address": "0xC91A0D5B404a66d0d66daF32DA23BB0c434F7F6b",
"address": "0x285671fF5C8172dE63cF5eA264B2e827aDBC6740",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
},
"localhost": {
@ -412,7 +412,7 @@
},
"AaveProtocolTestHelpers": {
"buidlerevm": {
"address": "0x5c98c9202b73d27A618662d34A6805c34AB041B8"
"address": "0xb840b4fe440b5E26e1840cd2D6320FAda1C0ca5d"
},
"localhost": {
"address": "0xBE7fFcC01164C890e59D298FD755FcBE6B7941a9"
@ -420,7 +420,7 @@
},
"StableDebtToken": {
"buidlerevm": {
"address": "0xD325d114a728C2114Bd33Ad47152f790f2a29c5c",
"address": "0xBdFE372Bb5a0db801A1a17796EC5cfF2F30A714C",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
},
"localhost": {
@ -430,7 +430,7 @@
},
"VariableDebtToken": {
"buidlerevm": {
"address": "0x910b6a78b413e47401f20aA2350d264b55ae0189",
"address": "0xD325d114a728C2114Bd33Ad47152f790f2a29c5c",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
},
"localhost": {

View File

@ -449,15 +449,6 @@ export const calcExpectedReserveDataAfterRepay = (
userDataBeforeAction.principalStableDebt
);
console.log(
'Debt accrued: ',
debtAccrued.toFixed(),
' Total liquidity:',
reserveDataBeforeAction.totalLiquidity.toFixed(),
' total borrow stable: ',
reserveDataBeforeAction.totalBorrowsStable.toFixed()
);
expectedReserveData.totalLiquidity = reserveDataBeforeAction.totalLiquidity.plus(debtAccrued);
expectedReserveData.totalBorrowsStable = reserveDataBeforeAction.totalBorrowsStable

View File

@ -178,8 +178,6 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
txTimestamp.plus(2)
);
console.log("debt: ", stableDebtBeforeTx.toFixed(), userReserveDataBefore.currentStableDebt.toFixed(), userReserveDataAfter.currentStableDebt.toString())
expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual(
new BigNumber(stableDebtBeforeTx).minus(amountToLiquidate).toFixed(0),
'Invalid user debt after liquidation'
@ -190,8 +188,6 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
'Invalid principal available liquidity'
);
console.log('eth liquidity: ', daiReserveDataAfter.availableLiquidity.toString());
expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual(
new BigNumber(ethReserveDataBefore.availableLiquidity)
.minus(expectedCollateralLiquidated)
@ -303,14 +299,6 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
'Invalid health factor'
);
console.log(
'Debt: ',
userReserveDataAfter.currentStableDebt.toString(),
new BigNumber(userReserveDataBefore.currentStableDebt.toString())
.minus(amountToLiquidate)
.toFixed(0)
);
expect(userReserveDataAfter.currentStableDebt.toString()).to.be.bignumber.almostEqual(
new BigNumber(userReserveDataBefore.currentStableDebt.toString())
.minus(amountToLiquidate)
@ -323,14 +311,6 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
'Invalid principal available liquidity'
);
console.log(
'Debt: ',
usdcReserveDataAfter.availableLiquidity.toString(),
new BigNumber(usdcReserveDataBefore.availableLiquidity.toString())
.plus(amountToLiquidate)
.toFixed(0)
);
expect(ethReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual(
new BigNumber(ethReserveDataBefore.availableLiquidity)
.minus(expectedCollateralLiquidated)

View File

@ -12,7 +12,7 @@ BigNumber.config({DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN});
const scenarioFolder = './test/helpers/scenarios/';
const selectedScenarios: string[] = ['borrow-repay-variable.json'];
const selectedScenarios: string[] = [];
fs.readdirSync(scenarioFolder).forEach((file) => {
if (selectedScenarios.length > 0 && !selectedScenarios.includes(file)) return;