@@ -473,6 +473,44 @@ contract OUSD is Initializable, InitializableERC20Detailed, Governable {
473473 return nonRebasingCreditsPerToken[_account] > 0 ;
474474 }
475475
476+ /**
477+ * @dev Ensures internal account for rebasing and non-rebasing credits and
478+ * supply is updated following deployment of frozen yield change.
479+ */
480+ function _ensureMigrationToRebasing (address _account ) internal {
481+ if (nonRebasingCreditsPerToken[_account] == 0 ) {
482+ return ; // Account already is rebasing
483+ }
484+ // Precalculate old balance so that no partial
485+ // account changes will affect it
486+ uint256 oldBalance = balanceOf (msg .sender );
487+
488+ // Precalculate new credits, so that we avoid internal calls when
489+ // atomically updating account.
490+ // Convert balance into the same amount at the current exchange rate
491+ uint256 newCreditBalance = _creditBalances[msg .sender ]
492+ .mul (_rebasingCreditsPerToken)
493+ .div (_creditsPerToken (msg .sender ));
494+
495+ // Atomicly update this account:
496+ // Important that no internal calls happen during this.
497+ // Remove pinned fixed credits per token
498+ delete nonRebasingCreditsPerToken[msg .sender ];
499+ // New credits
500+ _creditBalances[msg .sender ] = newCreditBalance;
501+
502+ // Update global totals:
503+ // Decrease non rebasing supply. We use the old balance, since that
504+ // would have been the value that was originally used to adjust the
505+ // nonRebasingSupply.
506+ nonRebasingSupply = nonRebasingSupply.sub (oldBalance);
507+ // Increase rebasing credits, totalSupply remains unchanged so no
508+ // adjustment necessary
509+ _rebasingCredits = _rebasingCredits.add (_creditBalances[msg .sender ]);
510+
511+ emit RebasingEnabled (msg .sender , oldBalance, _rebasingCreditsPerToken);
512+ }
513+
476514 /**
477515 * @dev Ensures internal account for rebasing and non-rebasing credits and
478516 * supply is updated following deployment of frozen yield change.
@@ -529,36 +567,9 @@ contract OUSD is Initializable, InitializableERC20Detailed, Governable {
529567 function rebaseOptIn () public nonReentrant {
530568 require (_isNonRebasingAccount (msg .sender ), "Account has not opted out " );
531569
532- // Precalculate old balance so that no partial
533- // account changes will affect it
534- uint256 oldBalance = balanceOf (msg .sender );
535-
536- // Precalculate new credits, so that we avoid internal calls when
537- // atomically updating account.
538- // Convert balance into the same amount at the current exchange rate
539- uint256 newCreditBalance = _creditBalances[msg .sender ]
540- .mul (_rebasingCreditsPerToken)
541- .div (_creditsPerToken (msg .sender ));
570+ _ensureMigrationToRebasing (msg .sender );
542571
543- // Atomicly update this account:
544- // Important that no internal calls happen during this.
545- // Remove pinned fixed credits per token
546- delete nonRebasingCreditsPerToken[msg .sender ];
547- // New credits
548- _creditBalances[msg .sender ] = newCreditBalance;
549- // Mark explicitly opted in to rebasing
550572 rebaseState[msg .sender ] = RebaseOptions.OptIn;
551-
552- // Update global totals:
553- // Decrease non rebasing supply. We use the old balance, since that
554- // would have been the value that was originally used to adjust the
555- // nonRebasingSupply.
556- nonRebasingSupply = nonRebasingSupply.sub (oldBalance);
557- // Increase rebasing credits, totalSupply remains unchanged so no
558- // adjustment necessary
559- _rebasingCredits = _rebasingCredits.add (_creditBalances[msg .sender ]);
560-
561- emit RebasingEnabled (msg .sender , oldBalance, _rebasingCreditsPerToken);
562573 }
563574
564575 /**
@@ -572,6 +583,22 @@ contract OUSD is Initializable, InitializableERC20Detailed, Governable {
572583 rebaseState[msg .sender ] = RebaseOptions.OptOut;
573584 }
574585
586+ /**
587+ * @dev Governance action to allow a contract that does not support
588+ * opting in to earn yield
589+ */
590+ function rebaseOptInByGovernance (address _account )
591+ external
592+ onlyGovernor
593+ nonReentrant
594+ {
595+ require (_isNonRebasingAccount (_account), "Account has not opted out " );
596+
597+ _ensureMigrationToRebasing (_account);
598+
599+ rebaseState[_account] = RebaseOptions.OptIn;
600+ }
601+
575602 /**
576603 * @dev Modify the supply without minting new tokens. This uses a change in
577604 * the exchange rate between "credits" and OUSD tokens to change balances.
0 commit comments