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

R4R: CDP types and methods #275

Merged
merged 22 commits into from
Jan 12, 2020
Merged

R4R: CDP types and methods #275

merged 22 commits into from
Jan 12, 2020

Conversation

karzak
Copy link
Member

@karzak karzak commented Dec 9, 2019

TODO

  • msgs
  • rebase and re-integrate tests using new testing pattern

@karzak karzak added the WIP PR is a work in progress and not ready for review label Dec 9, 2019
@karzak karzak added R4R When a PR is ready for review and removed WIP PR is a work in progress and not ready for review labels Dec 26, 2019
@karzak karzak changed the title WIP: CDP types and methods R4R: CDP types and methods Dec 26, 2019
@denalimarsh denalimarsh self-requested a review January 7, 2020 14:49
Copy link
Contributor

@denalimarsh denalimarsh left a comment

Choose a reason for hiding this comment

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

Looks good! Review comments are mostly focused on general cleaning and limiting code duplication. Are there any specific Golang styles we're using? I'm pretty sure Cosmos has been using Uber's Go style guide.

Comment on lines 21 to 27
// deposits blocked if cdp is in liquidation, have to check all deposits
deposits := k.GetDeposits(ctx, cdp.ID)
for _, d := range deposits {
if d.InLiquidation {
return types.ErrCdpNotAvailable(k.codespace, cdp.ID)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Duplicated below on lines 73-79 and in draw.go on lines 17-22 and 95-100. Could be potentially cleaned up by moving this block into a new method such as func (k Keeper) ValidateAvailableCDP().

if !found {
return types.ErrCdpNotFound(k.codespace, owner, collateral[0].Denom)
}
// withdrawals blocked if cdp is in liquidation
Copy link
Contributor

@denalimarsh denalimarsh Jan 7, 2020

Choose a reason for hiding this comment

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

See above comment

Copy link
Member Author

@karzak karzak Jan 7, 2020

Choose a reason for hiding this comment

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

Not clear we reduce duplication here, as the GetCdpByOwnerAndDenom call is necessary, so to replace it was a ValidateCdpFound() method wouldn't do much.

Copy link
Contributor

Choose a reason for hiding this comment

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

Was referring to lines 73-79. It appears that my single line selection during reviews is buggy and automatically selects a 4 line block with the single selected line at the bottom, noticed it over in #276 as well. That seems to be the source of the confusion here.

Comment on lines +93 to +100
collateralizationRatio, err := k.CalculateCollateralizationRatio(ctx, cdp.Collateral.Sub(collateral), cdp.Principal, cdp.AccumulatedFees.Add(fees))
if err != nil {
return err
}
liquidationRatio := k.getLiquidationRatio(ctx, collateral[0].Denom)
if collateralizationRatio.LT(liquidationRatio) {
return types.ErrInvalidCollateralRatio(k.codespace, collateral[0].Denom, collateralizationRatio, liquidationRatio)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar to draw.go lines 32-40 and cdp.go lines 27-34. Can we move this to a ValidateCollateralizationRatio() helper function which checks for ErrInvalidCollateralRatio?

}

// fee calculation
periods := sdk.NewInt(ctx.BlockTime().Unix() - cdp.FeesUpdated.Unix())
Copy link
Contributor

Choose a reason for hiding this comment

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

Update to use ...Sub(sdk.NewInt(cdp.FeesUpdated.Unix())), as done in deposit.go lines 49 and 91.

}

// calculate fees
periods := sdk.NewInt(ctx.BlockTime().Unix() - cdp.FeesUpdated.Unix())
Copy link
Contributor

Choose a reason for hiding this comment

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

See above comment

Comment on lines 84 to 86
if deposit.InLiquidation {
return types.ErrDepositNotAvailable(k.codespace, cdp.ID, depositor)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Due to the liquidation status check on line 76, will this condition ever be true?

Comment on lines 27 to 34
collateralRatio, err := k.CalculateCollateralizationRatio(ctx, collateral, principal, sdk.NewCoins())
if err != nil {
return err
}
liquidationRatio := k.getLiquidationRatio(ctx, collateral[0].Denom)
if collateralRatio.LT(liquidationRatio) {
return types.ErrInvalidCollateralRatio(k.codespace, collateral[0].Denom, collateralRatio, liquidationRatio)
}
Copy link
Contributor

@denalimarsh denalimarsh Jan 7, 2020

Choose a reason for hiding this comment

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

Comment on lines +338 to +340
if dc.Amount.LT(dp.DebtFloor) {
return types.ErrBelowDebtFloor(k.codespace, sdk.NewCoins(dc), dp.DebtFloor)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Should a DebtFloor check also be added somewhere in DepositCollateral()/ValidatePrincipalDraw() to prevent dust with additional principal coin types? May allow us to combine this function with ValidatePrincipalDraw(), but I'm not sure I fully understand all the potential implications of such an addition.

// - 0x07<denom>:feeRate
// - 0x08:previousBlockTime
// - 0x20 - 0xff are reserved for collaterals
Copy link
Member

Choose a reason for hiding this comment

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

Remove this comment? Correct me if I'm wrong but collateral types are assigned byte ids, which as used in store keys, but their namespace doesn't conflict with the other store keys. So they can start at 0x00.

Comment on lines +285 to +296
func (k Keeper) IndexCdpByCollateralRatio(ctx sdk.Context, denom string, id uint64, collateralRatio sdk.Dec) {
store := prefix.NewStore(ctx.KVStore(k.key), types.CollateralRatioIndexPrefix)
db, _ := k.GetDenomPrefix(ctx, denom)
store.Set(types.CollateralRatioKey(db, id, collateralRatio), types.GetCdpIDBytes(id))
}

// RemoveCdpCollateralRatioIndex deletes the cdp id from the store's index of cdps by collateral type and collateral to debt ratio
func (k Keeper) RemoveCdpCollateralRatioIndex(ctx sdk.Context, denom string, id uint64, collateralRatio sdk.Dec) {
store := prefix.NewStore(ctx.KVStore(k.key), types.CollateralRatioIndexPrefix)
db, _ := k.GetDenomPrefix(ctx, denom)
store.Delete(types.CollateralRatioKey(db, id, collateralRatio))
}
Copy link
Member

Choose a reason for hiding this comment

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

In the staking module, any index updates are written into the Get/Set methods. I kind of like that approach - reduces code repitition in higher level keeper methods, and avoids the posibility that indexes are not updated when they should be.
Do you think it's worth doing for CDP indexes?

Copy link
Member Author

Choose a reason for hiding this comment

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

Not quite sure what the suggestion is here. Looking through staking, the Set methods are pretty small and there are separate methods for indexes (ie SetValidatorByPowerIndex). The main difference appears to be that there is only one key prefix, which I'm not sure I can accomplish. I thought about the various indexes and iterators that were desirable for CDPs and couldn't come up with an approach that had fewer keys.

Copy link
Member

Choose a reason for hiding this comment

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

ah yeah looking at staking again it's only the SetUnbondingDelegations and SetRedelegations methods that update their indexes. Didn't see validator indexes are not updated in SetValidator.

The idea was that I couldn't think of any reason you would want to set a CDP in the store, but not update the CDP indexes. Having this happen by accident could be bad. Therefore it seems safer to combine SetCDP and IndexCdpByCollateralRatio into one function.

Comment on lines 120 to 121
deposit.Amount = deposit.Amount.Sub(collateral)
k.SetDeposit(ctx, deposit)
Copy link
Member

Choose a reason for hiding this comment

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

ifdeposit.Amount is reduced down to zero, the deposit is never removed from state. Think this could be exploited to add arbitrary numbers of zero size deposits.

// - 0x01<collateralDenomPrefix>:<cdpID_Bytes>: CDP
// - cdps are prefix by denom prefix so we can iterate over cdps of one type
// - uses : as separator, otherwise the cdp with ID 11 would be selected when iterating over denom with prefix 1
Copy link
Member

Choose a reason for hiding this comment

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

Pretty sure separators aren't needed. If each part of a key is a known fixed length so there's no need to rely on a special : byte to seprate them. The collateralDenomPrefix is fixed at one byte right?
Maybe just update comment, can't see any harm in leaving separators in.

@denalimarsh denalimarsh mentioned this pull request Jan 8, 2020
11 tasks
Copy link
Contributor

@denalimarsh denalimarsh left a comment

Choose a reason for hiding this comment

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

Review changes look good. Willing to merge this into develop now, as branch kd-update-liquidator will be adding more functionality into the CDP module given the restructuring.

@karzak karzak merged commit d849d69 into develop Jan 12, 2020
@karzak karzak deleted the kd-propose-cdp branch January 15, 2020 10:40
denalimarsh pushed a commit that referenced this pull request Apr 3, 2020
* wip: tpyes and keeper methods

* wip: iterators

* wip: types and keeper methods

* wip: add msgs

* wip: client methods

* wip: rebase develop

* wip: types tests

* wip: keeper tests, small fixes

* wip: add cdp tests

* wip: deposit tests

* wip: keeper tests

* wip: tests and module methods

* feat: error when fetching expired price

* feat: conversion factor for external assets

* feat: debt floor for new cdps

* feat: save deposits on export genesis

* feat: ensure messages implement msg

* feat: index deposits by status

* fix: stray comment

* wip: address review comments

* address review comments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
R4R When a PR is ready for review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants