# 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