diff --git a/contracts/contracts/token/OUSD.sol b/contracts/contracts/token/OUSD.sol index b00a76facb..643dfc2c99 100644 --- a/contracts/contracts/token/OUSD.sol +++ b/contracts/contracts/token/OUSD.sol @@ -38,7 +38,6 @@ contract OUSD is Governable { YieldDelegationTarget } - uint256[154] private _gap; // Slots to align with deployed contract uint256 private constant MAX_SUPPLY = type(uint128).max; uint256 public totalSupply; @@ -267,7 +266,7 @@ contract OUSD is Governable { if (state == RebaseOptions.YieldDelegationSource) { address target = yieldTo[_account]; uint256 targetOldBalance = balanceOf(target); - uint256 targetNewCredits = _balanceToRebasingCredits( + (uint256 targetNewCredits, ) = _balanceToRebasingCredits( targetOldBalance + newBalance ); rebasingCreditsDiff = @@ -277,7 +276,7 @@ contract OUSD is Governable { creditBalances[_account] = newBalance; creditBalances[target] = targetNewCredits; } else if (state == RebaseOptions.YieldDelegationTarget) { - uint256 newCredits = _balanceToRebasingCredits( + (uint256 newCredits, ) = _balanceToRebasingCredits( newBalance + creditBalances[yieldFrom[_account]] ); rebasingCreditsDiff = @@ -291,7 +290,7 @@ contract OUSD is Governable { alternativeCreditsPerToken[_account] = 1e18; creditBalances[_account] = newBalance; } else { - uint256 newCredits = _balanceToRebasingCredits(newBalance); + (uint256 newCredits, ) = _balanceToRebasingCredits(newBalance); rebasingCreditsDiff = newCredits.toInt256() - creditBalances[_account].toInt256(); @@ -315,7 +314,7 @@ contract OUSD is Governable { } /** - * @notice Function to check the amount of tokens that _owner has allowed + * @notice Function to check the amount of tokens that _owner has allowed * to `_spender`. * @param _owner The address which owns the funds. * @param _spender The address which will spend the funds. @@ -342,7 +341,7 @@ contract OUSD is Governable { } /** - * @notice Creates `_amount` tokens and assigns them to `_account`, + * @notice Creates `_amount` tokens and assigns them to `_account`, * increasing the total supply. */ function mint(address _account, uint256 _amount) external onlyVault { @@ -419,16 +418,27 @@ contract OUSD is Governable { } } + /** + * @dev Calculates credits from contract's global rebasingCreditsPerToken_, and + * also balance that corresponds to those credits. The latter is important + * when adjusting the contract's global nonRebasingSupply to circumvent any + * possible rounding errors. + * + * @param _balance Address of the account. + */ function _balanceToRebasingCredits(uint256 _balance) internal view - returns (uint256) + returns (uint256 rebasingCredits, uint256 balance) { // Rounds up, because we need to ensure that accounts always have // at least the balance that they should have. // Note this should always be used on an absolute account value, // not on a possibly negative diff, because then the rounding would be wrong. - return ((_balance) * rebasingCreditsPerToken_ + 1e18 - 1) / 1e18; + rebasingCredits = + ((_balance) * rebasingCreditsPerToken_ + 1e18 - 1) / + 1e18; + balance = (rebasingCredits * 1e18) / rebasingCreditsPerToken_; } /** @@ -448,7 +458,7 @@ contract OUSD is Governable { function _rebaseOptIn(address _account) internal { uint256 balance = balanceOf(_account); - + // prettier-ignore require( alternativeCreditsPerToken[_account] > 0 || @@ -469,9 +479,15 @@ contract OUSD is Governable { // Account rebaseState[_account] = RebaseOptions.StdRebasing; alternativeCreditsPerToken[_account] = 0; - creditBalances[_account] = _balanceToRebasingCredits(balance); + (uint256 newCredits, uint256 newBalance) = _balanceToRebasingCredits( + balance + ); + creditBalances[_account] = newCredits; // Globals - _adjustGlobals(creditBalances[_account].toInt256(), -balance.toInt256()); + _adjustGlobals( + newCredits.toInt256(), + -newBalance.toInt256() + ); emit AccountRebasingEnabled(_account); } @@ -593,9 +609,15 @@ contract OUSD is Governable { // Local creditBalances[_from] = fromBalance; alternativeCreditsPerToken[_from] = 1e18; - creditBalances[_to] = _balanceToRebasingCredits(fromBalance + toBalance); + (creditBalances[_to], ) = _balanceToRebasingCredits( + fromBalance + toBalance + ); // Global - _adjustGlobals(_balanceToRebasingCredits(fromBalance).toInt256(), -fromBalance.toInt256()); + ( + uint256 fromCredits, + uint256 fromBalanceAccurate + ) = _balanceToRebasingCredits(fromBalance); + _adjustGlobals(fromCredits.toInt256(), -fromBalanceAccurate.toInt256()); emit YieldDelegated(_from, _to); } @@ -620,9 +642,16 @@ contract OUSD is Governable { // alternativeCreditsPerToken[from] already 1e18 from `delegateYield()` creditBalances[_from] = fromBalance; // alternativeCreditsPerToken[to] already 0 from `delegateYield()` - creditBalances[to] = _balanceToRebasingCredits(toBalance); + (creditBalances[to], ) = _balanceToRebasingCredits(toBalance); // Global - _adjustGlobals(-(_balanceToRebasingCredits(fromBalance).toInt256()), fromBalance.toInt256()); + ( + uint256 fromCredits, + uint256 fromBalanceAccurate + ) = _balanceToRebasingCredits(fromBalance); + _adjustGlobals( + -(fromCredits.toInt256()), + fromBalanceAccurate.toInt256() + ); emit YieldUndelegated(_from, to); } }