Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make CDP debt index always update as long as there is a global index update #694

Merged
merged 4 commits into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 68 additions & 44 deletions packages/contracts/contracts/CdpManagerStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -302,20 +302,19 @@ contract CdpManagerStorage is EbtcBase, ReentrancyGuard, ICdpManagerData, AuthNo
*/
function _getPendingRedistributedDebt(
bytes32 _cdpId
) internal view returns (uint256 pendingEBTCDebtReward) {
) internal view returns (uint256 pendingEBTCDebtReward, uint256 _debtIndexDiff) {
Cdp storage cdp = Cdps[_cdpId];

if (cdp.status != Status.active) {
return 0;
return (0, 0);
}

uint256 rewardPerUnitStaked = systemDebtRedistributionIndex -
cdpDebtRedistributionIndex[_cdpId];
_debtIndexDiff = systemDebtRedistributionIndex - cdpDebtRedistributionIndex[_cdpId];

if (rewardPerUnitStaked > 0) {
pendingEBTCDebtReward = (cdp.stake * rewardPerUnitStaked) / DECIMAL_PRECISION;
if (_debtIndexDiff > 0) {
pendingEBTCDebtReward = (cdp.stake * _debtIndexDiff) / DECIMAL_PRECISION;
} else {
return 0;
return (0, 0);
}
}

Expand All @@ -342,33 +341,45 @@ contract CdpManagerStorage is EbtcBase, ReentrancyGuard, ICdpManagerData, AuthNo

// Add the borrowers's coll and debt rewards earned from redistributions, to their Cdp
function _syncAccounting(bytes32 _cdpId) internal {
(, uint _newDebt, , uint _pendingDebt) = _applyAccumulatedFeeSplit(_cdpId);

// Update pending debts
if (_pendingDebt > 0) {
Cdp storage _cdp = Cdps[_cdpId];
uint256 prevDebt = _cdp.debt;
uint256 prevColl = _cdp.coll;

// Apply pending rewards to cdp's state
_cdp.debt = _newDebt;
(, uint _newDebt, , uint _pendingDebt, uint256 _debtIndexDelta) = _applyAccumulatedFeeSplit(
_cdpId
);

// Update if there is a debt redistribution index delta
if (_debtIndexDelta > 0) {
_updateRedistributedDebtSnapshot(_cdpId);

emit CdpUpdated(
_cdpId,
ISortedCdps(sortedCdps).getOwnerAddress(_cdpId),
msg.sender,
prevDebt,
prevColl,
_newDebt,
prevColl,
Cdps[_cdpId].stake,
CdpOperation.syncAccounting
);
Cdp storage _cdp = Cdps[_cdpId];
uint256 prevDebt = _cdp.debt;
if (prevDebt != _newDebt) {
{
// Apply pending debt redistribution to this CDP
_cdp.debt = _newDebt;
_emitCdpUpdatedEventForSyncAccounting(_cdpId, _cdp, _newDebt, _cdp.coll);
Comment on lines +357 to +358
Copy link

@dmitriia dmitriia Oct 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like it is always _cdp.debt == _newDebt, _cdp.coll == _newColl for the event:

    function _emitCdpUpdatedEventForSyncAccounting(
        bytes32 _cdpId,
        Cdp storage _cdp,
        uint256 _newDebt,
        uint256 _newColl
    ) internal {
        emit CdpUpdated(
            _cdpId,
            ISortedCdps(sortedCdps).getOwnerAddress(_cdpId),
            msg.sender,
>           _cdp.debt,
>           _cdp.coll,
>           _newDebt,
>           _newColl,
            _cdp.stake,
            CdpOperation.syncAccounting
        );
    }

For collateral part it is needed to have old one returned or it can be just said that CdpFeeSplitApplied is enough for reporting.

For debt the order can be changed:

https://github.com/Badger-Finance/ebtc/blob/c8b1f4b6d390983b37e0d52a3ea8e44efb07acd6/packages/contracts/contracts/CdpManagerStorage.sol#L354-L360

            if (prevDebt != _newDebt) {
                {
                    // Apply pending debt redistribution to this CDP
-                   _cdp.debt = _newDebt;
                    _emitCdpUpdatedEventForSyncAccounting(_cdpId, _cdp, _newDebt, _cdp.coll);
+                   _cdp.debt = _newDebt;
                }
            }

}
}
}
}

function _emitCdpUpdatedEventForSyncAccounting(
bytes32 _cdpId,
Cdp storage _cdp,
uint256 _newDebt,
uint256 _newColl
) internal {
emit CdpUpdated(
_cdpId,
ISortedCdps(sortedCdps).getOwnerAddress(_cdpId),
msg.sender,
_cdp.debt,
_cdp.coll,
_newDebt,
_newColl,
_cdp.stake,
CdpOperation.syncAccounting
);
}

// Remove borrower's stake from the totalStakes sum, and set their stake to 0
function _removeStake(bytes32 _cdpId) internal {
uint256 _newTotalStakes = totalStakes - Cdps[_cdpId].stake;
Expand Down Expand Up @@ -550,7 +561,7 @@ contract CdpManagerStorage is EbtcBase, ReentrancyGuard, ICdpManagerData, AuthNo
// and update its accumulator tracker accordingly
function _applyAccumulatedFeeSplit(
bytes32 _cdpId
) internal returns (uint256, uint256, uint256, uint256) {
) internal returns (uint256, uint256, uint256, uint256, uint256) {
// TODO Ensure global states like systemStEthFeePerUnitIndex get timely updated
// whenever there is a CDP modification operation,
// such as opening, closing, adding collateral, repaying debt, or liquidating
Expand All @@ -564,7 +575,8 @@ contract CdpManagerStorage is EbtcBase, ReentrancyGuard, ICdpManagerData, AuthNo
uint256 _newColl,
uint256 _newDebt,
uint256 _feeSplitDistributed,
uint _pendingDebt
uint _pendingDebt,
uint256 _debtIndexDelta
) = _calcSyncedAccounting(_cdpId, _oldPerUnitCdp, _systemStEthFeePerUnitIndex);

// apply split fee to given CDP
Expand All @@ -585,7 +597,7 @@ contract CdpManagerStorage is EbtcBase, ReentrancyGuard, ICdpManagerData, AuthNo
cdpStEthFeePerUnitIndex[_cdpId] = _systemStEthFeePerUnitIndex;
}

return (_newColl, _newDebt, _feeSplitDistributed, _pendingDebt);
return (_newColl, _newDebt, _feeSplitDistributed, _pendingDebt, _debtIndexDelta);
}

// return the applied split fee(scaled by 1e18) and the resulting CDP collateral amount after applied
Expand Down Expand Up @@ -655,7 +667,7 @@ contract CdpManagerStorage is EbtcBase, ReentrancyGuard, ICdpManagerData, AuthNo
function getSyncedNominalICR(bytes32 _cdpId) external view returns (uint256) {
(uint256 _oldIndex, uint256 _newIndex) = _readStEthIndex();
(, uint256 _newGlobalSplitIdx, ) = _calcSyncedGlobalAccounting(_newIndex, _oldIndex);
(uint256 _newColl, uint256 _newDebt, , uint256 _pendingDebt) = _calcSyncedAccounting(
(uint256 _newColl, uint256 _newDebt, , uint256 _pendingDebt, ) = _calcSyncedAccounting(
_cdpId,
cdpStEthFeePerUnitIndex[_cdpId],
_newGlobalSplitIdx /// NOTE: This is latest index
Expand Down Expand Up @@ -688,7 +700,8 @@ contract CdpManagerStorage is EbtcBase, ReentrancyGuard, ICdpManagerData, AuthNo
function getPendingRedistributedDebt(
bytes32 _cdpId
) public view returns (uint256 pendingEBTCDebtReward) {
return _getPendingRedistributedDebt(_cdpId);
(uint256 _pendingDebt, ) = _getPendingRedistributedDebt(_cdpId);
return _pendingDebt;
}

function hasPendingRedistributedDebt(bytes32 _cdpId) public view returns (bool) {
Expand All @@ -708,7 +721,7 @@ contract CdpManagerStorage is EbtcBase, ReentrancyGuard, ICdpManagerData, AuthNo
function getSyncedDebtAndCollShares(
bytes32 _cdpId
) public view returns (uint256 debt, uint256 coll) {
(uint256 _newColl, uint256 _newDebt, , ) = _calcSyncedAccounting(
(uint256 _newColl, uint256 _newDebt, , , ) = _calcSyncedAccounting(
_cdpId,
cdpStEthFeePerUnitIndex[_cdpId],
systemStEthFeePerUnitIndex
Expand Down Expand Up @@ -746,11 +759,12 @@ contract CdpManagerStorage is EbtcBase, ReentrancyGuard, ICdpManagerData, AuthNo
/// @return new CDP debt after pending change applied
/// @return split fee applied to given CDP
/// @return redistributed debt applied to given CDP
/// @return delta between debt redistribution index of given CDP and global tracking index
function _calcSyncedAccounting(
bytes32 _cdpId,
uint256 _cdpPerUnitIdx,
uint256 _systemStEthFeePerUnitIndex
) internal view returns (uint256, uint256, uint256, uint256) {
) internal view returns (uint256, uint256, uint256, uint256, uint256) {
uint256 _feeSplitApplied;
uint256 _newCollShare = Cdps[_cdpId].coll;

Expand All @@ -765,36 +779,46 @@ contract CdpManagerStorage is EbtcBase, ReentrancyGuard, ICdpManagerData, AuthNo
}

// processing redistributed debt to be applied
(uint256 _newDebt, uint256 pendingDebtRedistributed) = _getSyncedCdpDebtAndRedistribution(
_cdpId
(
uint256 _newDebt,
uint256 pendingDebtRedistributed,
uint256 _debtIndexDelta
) = _getSyncedCdpDebtAndRedistribution(_cdpId);

return (
_newCollShare,
_newDebt,
_feeSplitApplied,
pendingDebtRedistributed,
_debtIndexDelta
);

return (_newCollShare, _newDebt, _feeSplitApplied, pendingDebtRedistributed);
}

/// @return CDP debt and pending redistribution from liquidation applied
function _getSyncedCdpDebtAndRedistribution(
bytes32 _cdpId
) internal view returns (uint256, uint256) {
uint256 pendingDebtRedistributed = _getPendingRedistributedDebt(_cdpId);
) internal view returns (uint256, uint256, uint256) {
(uint256 pendingDebtRedistributed, uint256 _debtIndexDelta) = _getPendingRedistributedDebt(
_cdpId
);
uint256 _newDebt = Cdps[_cdpId].debt;
if (pendingDebtRedistributed > 0) {
_newDebt = _newDebt + pendingDebtRedistributed;
}
return (_newDebt, pendingDebtRedistributed);
return (_newDebt, pendingDebtRedistributed, _debtIndexDelta);
}

/// @return CDP debt with pending redistribution from liquidation applied
function getSyncedCdpDebt(bytes32 _cdpId) public view returns (uint256) {
(uint256 _newDebt, ) = _getSyncedCdpDebtAndRedistribution(_cdpId);
(uint256 _newDebt, , ) = _getSyncedCdpDebtAndRedistribution(_cdpId);
return _newDebt;
}

/// @return CDP collateral with pending split fee applied
function getSyncedCdpCollShares(bytes32 _cdpId) public view returns (uint256) {
(uint256 _oldIndex, uint256 _newIndex) = _readStEthIndex();
(, uint256 _newGlobalSplitIdx, ) = _calcSyncedGlobalAccounting(_newIndex, _oldIndex);
(uint256 _newColl, , , ) = _calcSyncedAccounting(
(uint256 _newColl, , , , ) = _calcSyncedAccounting(
_cdpId,
cdpStEthFeePerUnitIndex[_cdpId],
_newGlobalSplitIdx
Expand Down
2 changes: 0 additions & 2 deletions packages/contracts/contracts/LiquidationLibrary.sol
Original file line number Diff line number Diff line change
Expand Up @@ -451,8 +451,6 @@ contract LiquidationLibrary is CdpManagerStorage {
_cdp.coll = _coll - _partialColl;
_cdp.debt = _debt - _partialDebt;
_updateStakeAndTotalStakes(_cdpId);

_updateRedistributedDebtSnapshot(_cdpId);
}

// Re-Insertion into SortedCdp list after partial liquidation
Expand Down
Loading