---
# System prepended metadata

title: Margin spec meeting preparation

---

# 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
