@@ -501,24 +501,29 @@ contract OUSD is Initializable, InitializableERC20Detailed, Governable {
501501 function rebaseOptIn () public nonReentrant {
502502 require (_isNonRebasingAccount (msg .sender ), "Account has not opted out " );
503503
504+ // Precalculate new credits, so that we avoid internal calls when
505+ // atomicly updating account.
504506 // Convert balance into the same amount at the current exchange rate
505507 uint256 newCreditBalance = _creditBalances[msg .sender ]
506508 .mul (_rebasingCreditsPerToken)
507509 .div (_creditsPerToken (msg .sender ));
508510
509- // Decreasing non rebasing supply
510- nonRebasingSupply = nonRebasingSupply.sub (balanceOf (msg .sender ));
511-
511+ // Atomicly update this account:
512+ // Important that no internal calls happen during this.
513+ // Remove pinned fixed credits per token
514+ delete nonRebasingCreditsPerToken[msg .sender ];
515+ // New credits
512516 _creditBalances[msg .sender ] = newCreditBalance;
517+ // Mark explicitly opted out of rebasing
518+ rebaseState[msg .sender ] = RebaseOptions.OptIn;
519+
513520
521+ // Update global totals:
522+ // Decrease non rebasing supply
523+ nonRebasingSupply = nonRebasingSupply.sub (balanceOf (msg .sender ));
514524 // Increase rebasing credits, totalSupply remains unchanged so no
515525 // adjustment necessary
516526 _rebasingCredits = _rebasingCredits.add (_creditBalances[msg .sender ]);
517-
518- rebaseState[msg .sender ] = RebaseOptions.OptIn;
519-
520- // Delete any fixed credits per token
521- delete nonRebasingCreditsPerToken[msg .sender ];
522527 }
523528
524529 /**
@@ -527,17 +532,19 @@ contract OUSD is Initializable, InitializableERC20Detailed, Governable {
527532 function rebaseOptOut () public nonReentrant {
528533 require (! _isNonRebasingAccount (msg .sender ), "Account has not opted in " );
529534
530- // Increase non rebasing supply
531- nonRebasingSupply = nonRebasingSupply. add ( balanceOf ( msg . sender ));
535+ // Atomicly update this account
536+ // Important that no internal calls happen during this.
532537 // Set fixed credits per token
533538 nonRebasingCreditsPerToken[msg .sender ] = _rebasingCreditsPerToken;
539+ // Mark explicitly opted out of rebasing
540+ rebaseState[msg .sender ] = RebaseOptions.OptOut;
534541
542+ // Update global totals:
543+ // Increase non rebasing supply
544+ nonRebasingSupply = nonRebasingSupply.add (balanceOf (msg .sender ));
535545 // Decrease rebasing credits, total supply remains unchanged so no
536546 // adjustment necessary
537547 _rebasingCredits = _rebasingCredits.sub (_creditBalances[msg .sender ]);
538-
539- // Mark explicitly opted out of rebasing
540- rebaseState[msg .sender ] = RebaseOptions.OptOut;
541548 }
542549
543550 /**
0 commit comments