Merge branch 'fix/150' into 'master'

Resolve "Fix calculation on burning of stableDebt"

Closes #150

See merge request aave-tech/protocol-v2!161
This commit is contained in:
Ernesto Boado 2020-11-11 14:58:07 +00:00
commit 9fdd9f11da
2 changed files with 19 additions and 11 deletions

View File

@ -18,7 +18,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
uint256 internal _avgStableRate; uint256 internal _avgStableRate;
mapping(address => uint40) internal _timestamps; mapping(address => uint40) internal _timestamps;
mapping(address => uint256) internal _usersData; mapping(address => uint256) internal _usersStableRate;
uint40 internal _totalSupplyTimestamp; uint40 internal _totalSupplyTimestamp;
constructor( constructor(
@ -59,7 +59,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
* @return the stable rate of user * @return the stable rate of user
**/ **/
function getUserStableRate(address user) external virtual override view returns (uint256) { function getUserStableRate(address user) external virtual override view returns (uint256) {
return _usersData[user]; return _usersStableRate[user];
} }
/** /**
@ -68,7 +68,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
**/ **/
function balanceOf(address account) public virtual override view returns (uint256) { function balanceOf(address account) public virtual override view returns (uint256) {
uint256 accountBalance = super.balanceOf(account); uint256 accountBalance = super.balanceOf(account);
uint256 stableRate = _usersData[account]; uint256 stableRate = _usersStableRate[account];
if (accountBalance == 0) { if (accountBalance == 0) {
return 0; return 0;
} }
@ -117,13 +117,13 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
vars.amountInRay = amount.wadToRay(); vars.amountInRay = amount.wadToRay();
//calculates the new stable rate for the user //calculates the new stable rate for the user
vars.newStableRate = _usersData[onBehalfOf] vars.newStableRate = _usersStableRate[onBehalfOf]
.rayMul(currentBalance.wadToRay()) .rayMul(currentBalance.wadToRay())
.add(vars.amountInRay.rayMul(rate)) .add(vars.amountInRay.rayMul(rate))
.rayDiv(currentBalance.add(amount).wadToRay()); .rayDiv(currentBalance.add(amount).wadToRay());
require(vars.newStableRate < (1 << 128), 'Debt token: stable rate overflow'); require(vars.newStableRate < (1 << 128), 'Debt token: stable rate overflow');
_usersData[onBehalfOf] = vars.newStableRate; _usersStableRate[onBehalfOf] = vars.newStableRate;
//updating the user and supply timestamp //updating the user and supply timestamp
//solium-disable-next-line //solium-disable-next-line
@ -166,6 +166,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
uint256 previousSupply = totalSupply(); uint256 previousSupply = totalSupply();
uint256 newStableRate = 0; uint256 newStableRate = 0;
uint256 nextSupply = 0; uint256 nextSupply = 0;
uint256 userStableRate = _usersStableRate[user];
//since the total supply and each single user debt accrue separately, //since the total supply and each single user debt accrue separately,
//there might be accumulation errors so that the last borrower repaying //there might be accumulation errors so that the last borrower repaying
@ -176,14 +177,21 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
_totalSupply = 0; _totalSupply = 0;
} else { } else {
nextSupply = _totalSupply = previousSupply.sub(amount); nextSupply = _totalSupply = previousSupply.sub(amount);
newStableRate = _avgStableRate = _avgStableRate uint256 firstTerm = _avgStableRate.rayMul(previousSupply.wadToRay());
.rayMul(previousSupply.wadToRay()) uint256 secondTerm = userStableRate.rayMul(amount.wadToRay());
.sub(_usersData[user].rayMul(amount.wadToRay()))
.rayDiv(nextSupply.wadToRay()); //for the same reason described above, when the last user is repaying it might
//happen that user rate * user balance > avg rate * total supply. In that case,
//we simply set the avg rate to 0
if (secondTerm >= firstTerm) {
newStableRate = _avgStableRate = _totalSupply = 0;
} else {
newStableRate = _avgStableRate = firstTerm.sub(secondTerm).rayDiv(nextSupply.wadToRay());
}
} }
if (amount == currentBalance) { if (amount == currentBalance) {
_usersData[user] = 0; _usersStableRate[user] = 0;
_timestamps[user] = 0; _timestamps[user] = 0;
} else { } else {
//solium-disable-next-line //solium-disable-next-line