From afc9612ac4fb2ac19f3002d3c6eb9c208646e459 Mon Sep 17 00:00:00 2001 From: emilio Date: Tue, 11 Aug 2020 12:26:15 +0200 Subject: [PATCH] Updated optimization in aToken and debt tokens --- contracts/tokenization/AToken.sol | 98 ++++++++++++-------- contracts/tokenization/StableDebtToken.sol | 55 ++++++----- contracts/tokenization/VariableDebtToken.sol | 40 ++++---- 3 files changed, 116 insertions(+), 77 deletions(-) diff --git a/contracts/tokenization/AToken.sol b/contracts/tokenization/AToken.sol index 54c327d0..879ef54c 100644 --- a/contracts/tokenization/AToken.sol +++ b/contracts/tokenization/AToken.sol @@ -223,9 +223,10 @@ contract AToken is VersionedInitializable, ERC20 { require(_amount > 0, 'Amount to redeem needs to be > 0'); //cumulates the balance of the user - (, uint256 currentBalance, uint256 balanceIncrease, uint256 index) = cumulateBalanceInternal( + (, uint256 currentBalance, uint256 balanceIncrease) = calculateBalanceIncreaseInternal( msg.sender ); + uint256 amountToRedeem = _amount; //if amount is equal to uint(-1), the user wants to redeem everything @@ -247,13 +248,21 @@ contract AToken is VersionedInitializable, ERC20 { amountToRedeem ); - // burns tokens equivalent to the amount requested - _burn(msg.sender, amountToRedeem); + if(balanceIncrease > amountToRedeem){ + _mint(msg.sender, balanceIncrease.sub(amountToRedeem)); + } + else{ + _burn(msg.sender, amountToRedeem.sub(balanceIncrease)); + } + + uint256 userIndex = 0; - bool userIndexReset = false; //reset the user data if the remaining balance is 0 if (currentBalance.sub(amountToRedeem) == 0) { - userIndexReset = resetDataOnZeroBalanceInternal(msg.sender); + resetDataOnZeroBalanceInternal(msg.sender); + } else { + //updates the user index + userIndex = userIndexes[msg.sender] = pool.getReserveNormalizedIncome(underlyingAssetAddress); } // executes redeem of the underlying asset @@ -264,28 +273,32 @@ contract AToken is VersionedInitializable, ERC20 { currentBalance.sub(amountToRedeem) ); - emit Redeem(msg.sender, amountToRedeem, balanceIncrease, userIndexReset ? 0 : index); + emit Redeem(msg.sender, amountToRedeem, balanceIncrease, userIndex); } /** * @dev mints token in the event of users depositing the underlying asset into the lending pool * only lending pools can call this function - * @param _account the address receiving the minted tokens + * @param _user the address receiving the minted tokens * @param _amount the amount of tokens to mint */ - function mintOnDeposit(address _account, uint256 _amount) external onlyLendingPool { + function mintOnDeposit(address _user, uint256 _amount) external onlyLendingPool { + //cumulates the balance of the user - (, , uint256 balanceIncrease, uint256 index) = cumulateBalanceConditionalInternal(_account,false); + (, , uint256 balanceIncrease) = calculateBalanceIncreaseInternal(_user); + //updates the user index + uint256 index = userIndexes[_user] = pool.getReserveNormalizedIncome(underlyingAssetAddress); + //if the user is redirecting his interest towards someone else, //we update the redirected balance of the redirection address by adding the accrued interest //and the amount deposited - updateRedirectedBalanceOfRedirectionAddressInternal(_account, balanceIncrease.add(_amount), 0); + updateRedirectedBalanceOfRedirectionAddressInternal(_user, balanceIncrease.add(_amount), 0); //mint an equivalent amount of tokens to cover the new deposit - _mint(_account, _amount.add(balanceIncrease)); + _mint(_user, _amount.add(balanceIncrease)); - emit MintOnDeposit(_account, _amount, balanceIncrease, index); + emit MintOnDeposit(_user, _amount, balanceIncrease, index); } /** @@ -437,13 +450,40 @@ contract AToken is VersionedInitializable, ERC20 { return redirectedBalances[_user]; } + /** + * @dev calculates the increase in balance since the last user action + * @param _user the address of the user + * @return the last user principal balance, the current balance and the balance increase + **/ + function calculateBalanceIncreaseInternal(address _user) + internal + returns ( + uint256, + uint256, + uint256 + ) + { + uint256 currentBalance = balanceOf(_user); + uint256 balanceIncrease = 0; + uint256 previousBalance = 0; + + if (currentBalance != 0) { + previousBalance = super.balanceOf(_user); + //calculate the accrued interest since the last accumulation + balanceIncrease = currentBalance.sub(previousBalance); + } + + return (previousBalance, currentBalance, balanceIncrease); + } + + /** * @dev accumulates the accrued interest of the user to the principal balance * @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 * and the new user index **/ - function cumulateBalanceConditionalInternal(address _user, bool _mintBalanceIncrease) + function cumulateBalanceInternal(address _user) internal returns ( uint256, @@ -452,36 +492,16 @@ contract AToken is VersionedInitializable, ERC20 { uint256 ) { - uint256 currBalance = balanceOf(_user); - uint256 balanceIncrease = 0; - uint256 previousBalance = 0; + (uint256 previousBalance, uint256 currentBalance, uint256 balanceIncrease) = calculateBalanceIncreaseInternal(_user); + + _mint(_user, balanceIncrease); - if (currBalance != 0) { - previousBalance = super.balanceOf(_user); - //calculate the accrued interest since the last accumulation - balanceIncrease = currBalance.sub(previousBalance); - //mints an amount of tokens equivalent to the amount accumulated - if(_mintBalanceIncrease) { - _mint(_user, balanceIncrease); - } - } //updates the user index uint256 index = userIndexes[_user] = pool.getReserveNormalizedIncome(underlyingAssetAddress); - return (previousBalance, currBalance, balanceIncrease, index); - } - - function cumulateBalanceInternal(address _user) - internal - returns ( - uint256, - uint256, - uint256, - uint256 - ) - { - return cumulateBalanceConditionalInternal(_user, true); - } + return (previousBalance, currentBalance, balanceIncrease, index); + + } /** * @dev updates the redirected balance of the user. If the user is not redirecting his diff --git a/contracts/tokenization/StableDebtToken.sol b/contracts/tokenization/StableDebtToken.sol index 84803b46..3f740c7f 100644 --- a/contracts/tokenization/StableDebtToken.sol +++ b/contracts/tokenization/StableDebtToken.sol @@ -67,9 +67,11 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase { uint256 _balanceIncrease ); - constructor(address _pool, address _underlyingAsset) DebtTokenBase(_pool, _underlyingAsset) public { + constructor(address _pool, address _underlyingAsset) + public + DebtTokenBase(_pool, _underlyingAsset) + {} - } /** * @dev returns the average stable rate across all the stable rate debt * @return the average stable rate @@ -114,7 +116,8 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase { } struct MintLocalVars { - uint256 newSupply; + uint256 supplyAfterMint; + uint256 supplyBeforeMint; uint256 amountInRay; uint256 newStableRate; } @@ -134,11 +137,14 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase { MintLocalVars memory vars; //cumulates the user debt - (uint256 previousBalance, uint256 currentBalance, uint256 balanceIncrease) = _cumulateBalance( - _user - ); + ( + uint256 previousBalance, + uint256 currentBalance, + uint256 balanceIncrease + ) = _calculateBalanceIncrease(_user); - vars.newSupply = totalSupply.add(_amount); + vars.supplyBeforeMint = totalSupply.add(balanceIncrease); + vars.supplyAfterMint = vars.supplyBeforeMint.add(_amount); vars.amountInRay = _amount.wadToRay(); @@ -156,11 +162,11 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase { //calculates the updated average stable rate avgStableRate = avgStableRate - .rayMul(totalSupply.wadToRay()) + .rayMul(vars.supplyBeforeMint.wadToRay()) .add(_rate.rayMul(vars.amountInRay)) - .rayDiv(vars.newSupply.wadToRay()); + .rayDiv(vars.supplyAfterMint.wadToRay()); - _mint(_user, _amount); + _mint(_user, _amount.add(balanceIncrease)); emit mintDebt( _user, @@ -178,11 +184,16 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase { * @param _amount the amount of debt tokens to mint **/ function burn(address _user, uint256 _amount) public override onlyLendingPool { - (uint256 previousBalance, uint256 currentBalance, uint256 balanceIncrease) = _cumulateBalance( - _user - ); + ( + uint256 previousBalance, + uint256 currentBalance, + uint256 balanceIncrease + ) = _calculateCumulatedBalance(_user); - uint256 newSupply = totalSupply.sub(_amount); + uint256 supplyBeforeBurn = totalSupply.add(balanceIncrease); + uint256 supplyAfterBurn = supplyBeforeBurn.sub(_amount); + + uint256 newSupply = totalSupply.add(balanceIncrease).sub(_amount); uint256 amountInRay = _amount.wadToRay(); @@ -190,9 +201,9 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase { avgStableRate = 0; } else { avgStableRate = avgStableRate - .rayMul(totalSupply.wadToRay()) + .rayMul(supplyBeforeBurn.wadToRay()) .sub(usersData[_user].currentRate.rayMul(amountInRay)) - .rayDiv(newSupply.wadToRay()); + .rayDiv(supplyAfterBurn.wadToRay()); } if (_amount == currentBalance) { @@ -200,17 +211,21 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase { usersData[_user].lastUpdateTimestamp = 0; } - _burn(_user, _amount); + if (balanceIncrease > _amount) { + _mint(_user, balanceIncrease.sub(_amount)); + } else { + _burn(_user, _amount.sub(balanceIncrease)); + } emit burnDebt(_user, _amount, previousBalance, currentBalance, balanceIncrease); } /** - * @dev accumulates the accrued interest of the user to the principal balance + * @dev calculates the increase in balance since the last user action * @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 _cumulateBalance(address _user) + function _calculateBalanceIncrease(address _user) internal returns ( uint256, @@ -226,8 +241,6 @@ 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 - _mint(_user, balanceIncrease); return ( previousPrincipalBalance, diff --git a/contracts/tokenization/VariableDebtToken.sol b/contracts/tokenization/VariableDebtToken.sol index e3d98a43..3e5a3746 100644 --- a/contracts/tokenization/VariableDebtToken.sol +++ b/contracts/tokenization/VariableDebtToken.sol @@ -58,10 +58,11 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { uint256 _index ); - constructor(address _pool, address _underlyingAsset) DebtTokenBase(_pool, _underlyingAsset) public { - - } - + constructor(address _pool, address _underlyingAsset) + public + DebtTokenBase(_pool, _underlyingAsset) + {} + /** * @dev calculates the accumulated debt balance of the user * @return the debt balance of the user @@ -94,11 +95,13 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { * @param _amount the amount of debt being minted **/ function mint(address _user, uint256 _amount) public override onlyLendingPool { - (uint256 previousBalance, uint256 currentBalance, uint256 balanceIncrease) = _cumulateBalance( - _user - ); + ( + uint256 previousBalance, + uint256 currentBalance, + uint256 balanceIncrease + ) = _calculateCumulatedBalance(_user); - _mint(_user, _amount); + _mint(_user, _amount.add(balanceIncrease)); userIndexes[_user] = pool.getReserveNormalizedVariableDebt(underlyingAssetAddress); @@ -118,11 +121,17 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { * @param _amount the amount of debt being burned **/ function burn(address _user, uint256 _amount) public override onlyLendingPool { - (uint256 previousBalance, uint256 currentBalance, uint256 balanceIncrease) = _cumulateBalance( - _user - ); + ( + uint256 previousBalance, + uint256 currentBalance, + uint256 balanceIncrease + ) = _calculateBalanceIncrease(_user); - _burn(_user, _amount); + if (balanceIncrease > _amount) { + _mint(_user, balanceIncrease.sub(_amount)); + } else { + _burn(_user, _amount.sub(balanceIncrease)); + } //if user repaid everything if (currentBalance == _amount) { @@ -142,12 +151,12 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { } /** - * @dev accumulates the accrued interest of the user to the principal balance + * @dev calculates the increase in balance since the last user interaction * @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 * and the new user index **/ - function _cumulateBalance(address _user) + function _calculateBalanceIncrease(address _user) internal returns ( uint256, @@ -164,9 +173,6 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { //calculate the accrued interest since the last accumulation uint256 balanceIncrease = balanceOf(_user).sub(previousPrincipalBalance); - //mints an _amount of tokens equivalent to the _amount accumulated - _mint(_user, balanceIncrease); - return ( previousPrincipalBalance, previousPrincipalBalance.add(balanceIncrease),