# Margin spec meeting preparation
## Questions
```go
type MTP struct {
Address string
CollateralAssets []string
CollateralAmounts []sdk.Int
Liabilities sdk.Int
InterestPaidCollaterals []sdk.Int
InterestPaidCustodys []sdk.Int
InterestUnpaidCollaterals []sdk.Int
CustodyAssets []string
CustodyAmounts []sdk.Int
Leverages []sdk.Dec
MtpHealth sdk.Dec
Position Position
Id uint64
AmmPoolId uint64
ConsolidateLeverage sdk.Dec
SumCollateral sdk.Int
}
type PoolAsset struct {
Liabilities sdk.Int
Custody sdk.Int
AssetBalance sdk.Int
UnsettledLiabilities sdk.Int
BlockInterest sdk.Int
AssetDenom string
}
type Pool struct {
AmmPoolId uint64
Health sdk.Dec
Enabled bool
Closed bool
InterestRate sdk.Dec
PoolAssets []PoolAsset
}
```
- Definition of Custody (Custody is an external pool for a specific pool to store margin users' borrowed amounts?) - NativeCustody & ExternalCustody (Why splitting into two?)
- Collateral amount is put on the amm pool, margin pool or put on the margin custody? (If collateral asset is non-pool asset, how is it managed?)
- On MTP struct, InterestUnpaidCollateral exists, why InterestPaidCustodys exists, What about InterestUnpaidCustodys? Interest not only paid in Collaterals?
- MTP struct has array items, is it because users can open multiple positions at different leverage? (CollateralAssets array could have duplicated items?)
- How LP removal on amm and margin position close interact with each other? On which codebase?
## Findings to be fixed
- A lot of TODOs on margin module codebase, I think those are important features, and not sure when it's going to be implemented
```go
// compute interest
// TODO: missing fields
// interestPayment := k.CalcMTPInterestLiabilities(ctx, *mtp, pool.InterestRate, 0, 0, ammPool, mtp.CollateralAssets[0])
// finalInterestPayment := k.HandleInterestPayment(ctx, mtp.CollateralAssets[0],mtp.CustodyAssets[0], interestPayment, mtp, &pool, ammPool)
// nativeAsset := types.GetSettlementAsset()
// if types.StringCompare(mtp.CollateralAsset, nativeAsset) { // custody is external, payment is custody
// pool.BlockInterestExternal = pool.BlockInterestExternal.Add(finalInterestPayment)
// } else { // custody is native, payment is custody
// pool.BlockInterestNative = pool.BlockInterestNative.Add(finalInterestPayment)
// }
_ = k.SetMTP(ctx, mtp)
// TODO: missing function
// repayAmount, err := k.ForceCloseLong(ctx, *mtp, pool, false, true)
if err == nil {
// TODO: missing function
// Emit event if position was closed
// k.EmitForceClose(ctx, mtp, repayAmount, "")
} else if err != types.ErrMTPUnhealthy {
ctx.Logger().Error(errors.Wrap(err, "error executing force close").Error())
}
```
- On MTP close, only one field is `sdk.NewAttribute("leverage", closedMtp.Leverages[0].String())` logged - not all
- Lots of sdkerrors.Wrap calls with invalid meanings - recommend to check all the error return lines and fix
```go
pool, found := k.OpenLongChecker.GetPool(ctx, poolId)
if !found {
return nil, sdkerrors.Wrap(types.ErrPoolDoesNotExist, tradingAsset)
}
```
- This function does not require tradingAsset
```go
func (k Keeper) GetAmmPool(ctx sdk.Context, poolId uint64, tradingAsset string) (ammtypes.Pool, error) {
ammPool, found := k.amm.GetPool(ctx, poolId)
if !found {
return ammPool, sdkerrors.Wrap(types.ErrPoolDoesNotExist, tradingAsset)
}
return ammPool, nil
}
```
- GetFirstValidPool will need to be removed I guess which seems not correct, and the usage of tradingAsset will need to be deleted everywhere I think
```go
func (k Keeper) PreparePools(ctx sdk.Context, tradingAsset string) (poolId uint64, ammPool ammtypes.Pool, pool types.Pool, err error) {
poolId, err = k.GetFirstValidPool(ctx, tradingAsset)
if err != nil {
return
}
ammPool, err = k.GetAmmPool(ctx, poolId, tradingAsset)
if err != nil {
return
}
pool, found := k.GetPool(ctx, poolId)
if !found {
pool = types.NewPool(poolId)
pool.InitiatePool(ctx, &ammPool)
k.SetPool(ctx, pool)
}
return
}
```
- TakeFundPayment's SendCoinsFromModuleToAccount will need to be updated to SendCoins and will need to write proper unit test for this.
```go
func (k Keeper) TakeFundPayment(ctx sdk.Context, returnAmount sdk.Int, returnAsset string, takePercentage sdk.Dec, fundAddr sdk.AccAddress, ammPool *ammtypes.Pool) (sdk.Int, error) {
returnAmountDec := sdk.NewDecFromBigInt(returnAmount.BigInt())
takeAmount := sdk.NewIntFromBigInt(takePercentage.Mul(returnAmountDec).TruncateInt().BigInt())
if !takeAmount.IsZero() {
takeCoins := sdk.NewCoins(sdk.NewCoin(returnAsset, sdk.NewIntFromBigInt(takeAmount.BigInt())))
err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, ammPool.Address, fundAddr, takeCoins)
if err != nil {
return sdk.ZeroInt(), err
}
}
return takeAmount, nil
}
```
- On the call, it's discussed to remove `InterestUnpaidCollaterals []sdk.Int` on MTP struct