Skip to content
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
6 changes: 3 additions & 3 deletions proto/reserve/psm/v1/psm.proto
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@ message StablecoinInfo {
(gogoproto.nullable) = false,
(amino.dont_omitempty) = true
];
// stablecoin to nom exchange fee, fee_in when 1 stablecoin = 1nomUSD
// stablecoin to fxUSD exchange fee, fee_in when 1 stablecoin = 1fxUSD
string fee_in = 3 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];
// nom to stablecoin exchange fee, fee_out when 1 stablecoin = 1nomUSD
// fxUSD to stablecoin exchange fee, fee_out when 1 stablecoin = 1fxUSD
string fee_out = 4 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];
// amount of stablecoins locked in exchange for nomUSD
// amount of stablecoins locked in exchange for fxUSD
string total_stablecoin_lock = 5 [
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "cosmossdk.io/math.Int",
Expand Down
4 changes: 2 additions & 2 deletions script/proposal-vault-1.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"max_debt":"1000000000000000000000000000",
"collateral_oracle_script": "44",
"mint_oracle_script":44,
"mint_denom": "nomUSD",
"mint_denom": "fxUSD",
"mint_symbol":"USD",
"stability_fee": "0.1"
},
Expand All @@ -23,7 +23,7 @@
"max_debt":"1000000000000000000000000000",
"collateral_oracle_script": "44",
"mint_oracle_script":44,
"mint_denom": "nomUSD",
"mint_denom": "fxUSD",
"mint_symbol":"USD",
"stability_fee": "0.1"
}],
Expand Down
10 changes: 5 additions & 5 deletions script/psm-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,14 @@ sleep 15
# # reserved q psm all-stablecoin
reserved q bank balances $(reserved keys show validator1 -a --keyring-backend test --home /Users/donglieu/.reserved/validator1)

# # # tx swap usdt to nomUSD
# # # tx swap usdt to fxUSD
# # echo "========swap==========="
reserved tx psm swap 100000000000000000000000usdt nomUSD --from validator1 --keyring-backend test --home ~/.reserved/validator1 --chain-id testing-1 -y --fees 20stake
reserved tx psm swap 100000000000000000000000usdt fxUSD --from validator1 --keyring-backend test --home ~/.reserved/validator1 --chain-id testing-1 -y --fees 20stake

sleep 7

reserved tx psm swap 1000000000usdc nomUSD --from validator1 --keyring-backend test --home ~/.reserved/validator1 --chain-id testing-1 -y --fees 20stake
reserved tx psm swap 1000000000usdc fxUSD --from validator1 --keyring-backend test --home ~/.reserved/validator1 --chain-id testing-1 -y --fees 20stake
sleep 7
reserved tx psm swap 1000nomUSD usdc --from validator1 --keyring-backend test --home ~/.reserved/validator1 --chain-id testing-1 -y --fees 20stake
reserved tx psm swap 1000fxUSD usdc --from validator1 --keyring-backend test --home ~/.reserved/validator1 --chain-id testing-1 -y --fees 20stake
sleep 7
reserved tx psm swap 1000nomUSD usdt --from validator1 --keyring-backend test --home ~/.reserved/validator1 --chain-id testing-1 -y --fees 20stake
reserved tx psm swap 1000fxUSD usdt --from validator1 --keyring-backend test --home ~/.reserved/validator1 --chain-id testing-1 -y --fees 20stake
4 changes: 2 additions & 2 deletions script/vaults-gov-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ reserved tx oracle set-price atom 8 --home=$HOME/.reserved/validator2 --from v

sleep 7

reserved tx vaults create-vault 1250000000usdt 50000000nomUSD --home=$HOME/.reserved/validator1 --from validator1 --keyring-backend test --fees 20stake --chain-id testing-1 -y
reserved tx vaults create-vault 1250000000atom 50000000nomUSD --home=$HOME/.reserved/validator2 --from validator2 --keyring-backend test --fees 20stake --chain-id testing-1 -y
reserved tx vaults create-vault 1250000000usdt 50000000fxUSD --home=$HOME/.reserved/validator1 --from validator1 --keyring-backend test --fees 20stake --chain-id testing-1 -y
reserved tx vaults create-vault 1250000000atom 50000000fxUSD --home=$HOME/.reserved/validator2 --from validator2 --keyring-backend test --fees 20stake --chain-id testing-1 -y
# killall reserved || true


Expand Down
2 changes: 1 addition & 1 deletion x/auction/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func NewBidCmd() *cobra.Command {
Long: `create new bid.

Example:
$ onomyd tx bid 0 1000nomUSD 0.95 --from mykey
$ onomyd tx bid 0 1000fxUSD 0.95 --from mykey
`,
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
Expand Down
2 changes: 1 addition & 1 deletion x/auction/spec/msg.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ onomyd tx auction bid [auction-id] [amount] [recive_rate] [flags]
Example:

```shell
onomyd tx bid 0 1000nomUSD 0.8 --from mykey
onomyd tx bid 0 1000fxUSD 0.8 --from mykey
```

#### Cancel bid
Expand Down
2 changes: 1 addition & 1 deletion x/oracle/oracle/data_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def get_price_mecx(symbols):
result = []
# Set request parameters
PARAMETERS = {
"symbol": "NOMUSDT",
"symbol": "FXUSDT",
}


Expand Down
50 changes: 25 additions & 25 deletions x/psm/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# PSM Module

The PSM module is a stabilization mechanism for the nomUSD stablecoin, allowing users to swap approved stablecoins for nomUSD at a 1-1 ratio.
The PSM module is a stabilization mechanism for the fxUSD stablecoin, allowing users to swap approved stablecoins for fxUSD at a 1-1 ratio.

## Contents
- [Concept](#concept)
Expand All @@ -14,28 +14,28 @@ The PSM module is a stabilization mechanism for the nomUSD stablecoin, allowing

## Concept

PSM issues nomUSD in exchange for approved stablecoins, with a maximum issuance limit set by governance. It also allows users to swap nomUSD for stablecoins at a 1-1 ratio.nomUSD is issued from PSM which is backed by stablecoins within it. Parameters such as limit per stablecoin, swap-in fees and swap-out fees are governed and can change based on economic conditions. PSM is an effective support module for Vaults module in case users need nomUSD to repay off debts and close vault (redeem collateral).
PSM issues fxUSD in exchange for approved stablecoins, with a maximum issuance limit set by governance. It also allows users to swap fxUSD for stablecoins at a 1-1 ratio.fxUSD is issued from PSM which is backed by stablecoins within it. Parameters such as limit per stablecoin, swap-in fees and swap-out fees are governed and can change based on economic conditions. PSM is an effective support module for Vaults module in case users need fxUSD to repay off debts and close vault (redeem collateral).

### Key Features

Key Features

- **Swap to nomUSD**: Users can convert from stablecoin to nomUSD provided that the stablecoin has been added to the list of accepted stablecoins.
- **Swap to Stablecoin**: Users can convert from nomUSD to stablecoin provided that the stablecoin has been added to the list of accepted stablecoins.
- **Swap to fxUSD**: Users can convert from stablecoin to fxUSD provided that the stablecoin has been added to the list of accepted stablecoins.
- **Swap to Stablecoin**: Users can convert from fxUSD to stablecoin provided that the stablecoin has been added to the list of accepted stablecoins.

## State

### Params

Params contains:

- `LimitTotal`: Maximum amount of nomUSD that can be provided.
- `AcceptablePriceRatio`: The spread price between nomUSD and the stablecoins is at an acceptable level where the fees will remain the same.
- `LimitTotal`: Maximum amount of fxUSD that can be provided.
- `AcceptablePriceRatio`: The spread price between fxUSD and the stablecoins is at an acceptable level where the fees will remain the same.
- `AdjustmentFee`: "AdjustmentFee" is a parameter used to adjust the amount of change in swap fees based on the deviation of the stablecoin from the target price. AdjustmentFee determines the number of iterations that one of the fees (entry fee or exit fee) will be adjusted according to the current ratio between the target price and the actual price. The larger the AdjustmentFee, the more severe the fee adjustment will be. Specifically, it affects how the feeOut or feeIn is calculated by multiplying (or dividing) it by the price ratio.

```protobuf
message Params {
// total $nomUSD can mint
// total $fxUSD can mint
bytes limit_total = 1 [
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "cosmossdk.io/math.Int",
Expand Down Expand Up @@ -64,9 +64,9 @@ Params config for each stablecoin type:

- `Denom`: stablecoin name
- `LimitTotal`: limit total stablecoin
- `FeeIn`: stablecoin to nomUSD exchange fee, fee_in when 1 stablecoin = 1nomUSD
- `FeeOut`: nomUSD to stablecoin exchange fee, fee_out when 1 stablecoin = 1nomUSD
- `TotalStablecoinLock`: amount of stablecoins locked in exchange for nomUSD, default start at 0
- `FeeIn`: stablecoin to fxUSD exchange fee, fee_in when 1 stablecoin = 1fxUSD
- `FeeOut`: fxUSD to stablecoin exchange fee, fee_out when 1 stablecoin = 1fxUSD
- `TotalStablecoinLock`: amount of stablecoins locked in exchange for fxUSD, default start at 0
- `FeeMaxStablecoin`: maximum fee for when either fee = 0, default at fee_in+fee_out

```protobuf
Expand All @@ -80,19 +80,19 @@ message Stablecoin {
(gogoproto.nullable) = false,
(amino.dont_omitempty) = true
];
// stablecoin to nomUSD exchange fee, fee_in when 1 stablecoin = 1nomUSD
// stablecoin to fxUSD exchange fee, fee_in when 1 stablecoin = 1fxUSD
bytes fee_in = 3 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];
// nomUSD to stablecoin exchange fee, fee_out when 1 stablecoin = 1nomUSD
// fxUSD to stablecoin exchange fee, fee_out when 1 stablecoin = 1fxUSD
bytes fee_out = 4 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];
// amount of stablecoins locked in exchange for nomUSD
// amount of stablecoins locked in exchange for fxUSD
bytes total_stablecoin_lock = 5 [
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "cosmossdk.io/math.Int",
Expand All @@ -112,8 +112,8 @@ message Stablecoin {

## Messages

### MsgStableSwap (swap to nomUSD)
Allows users to swap accepted stablecoins for nomUSD. `Address` is the sender's address, `OfferCoin` is the amount of stablecoin the user sent. `ExpectedDenom` is the type of denom expected to be received.
### MsgStableSwap (swap to fxUSD)
Allows users to swap accepted stablecoins for fxUSD. `Address` is the sender's address, `OfferCoin` is the amount of stablecoin the user sent. `ExpectedDenom` is the type of denom expected to be received.

```{.go}
type MsgStableSwap struct {
Expand All @@ -131,10 +131,10 @@ type MsgStableSwap struct {
- Check balance user and calculate amount of coins received and fee in

- Transfer stablecoin from user to psm module.
- Mint nomUSD and send for user
- Mint fxUSD and send for user

### MsgStableSwap (swap to stablecoin)
Allows users to swap accepted nomUSD for stablecoins. `Address` is the sender's address, `ExpectedDenom` is the stablecoin name to receive ,`OfferCoin` is the amount of nomUSD the user sent
Allows users to swap accepted fxUSD for stablecoins. `Address` is the sender's address, `ExpectedDenom` is the stablecoin name to receive ,`OfferCoin` is the amount of fxUSD the user sent

```{.go}
type MsgStableSwap struct {
Expand All @@ -151,34 +151,34 @@ type MsgStableSwap struct {
- Check total stablecoin lock enough to swap
- Check balance user and calculate amount of coins received and fee out

- Transfer nomUSD from user to psm module and burn.
- Transfer fxUSD from user to psm module and burn.
- Transfer stablecoin to user

## Events

The PSM module emits events for various operations:
- **AddStablecoin**: Emitted when a new stablecoin is added.
- **UpdateStablecoin**: Emitted when a stablecoin is updates
- **Swap**: Emitted when exchanging nomUSD for stablecoin. Emitted when exchanging stablecoin for nomUSD
- **Swap**: Emitted when exchanging fxUSD for stablecoin. Emitted when exchanging stablecoin for fxUSD


## ABCI

### Fee recalculate
To maintain the peg of 1 nomUSD = 1 USD, the swap fees need to be adjusted whenever the price of stablecoins fluctuates. This adjustment ensures that deviations from the target price of 1 USD per nomUSD are counterbalanced by the fees.
To maintain the peg of 1 fxUSD = 1 USD, the swap fees need to be adjusted whenever the price of stablecoins fluctuates. This adjustment ensures that deviations from the target price of 1 USD per fxUSD are counterbalanced by the fees.

Adjustment Logic:
- If the stablecoin price is above 1, fee_out (the fee for converting from nomUSD to the stablecoin) will be higher, and fee_in (the fee for converting from the stablecoin to nomUSD) will be lower. This setup discourages swaps that would increase the stablecoin holdings when its value is above 1, helping to bring the price back down.
- If the stablecoin price is below 1, fee_out will be lower, and fee_in will be higher. This makes it cheaper to convert nomUSD to the stablecoin and more costly to convert the stablecoin to nomUSD, which encourages activity that pushes the price back up toward the target.
- If the stablecoin price is above 1, fee_out (the fee for converting from fxUSD to the stablecoin) will be higher, and fee_in (the fee for converting from the stablecoin to fxUSD) will be lower. This setup discourages swaps that would increase the stablecoin holdings when its value is above 1, helping to bring the price back down.
- If the stablecoin price is below 1, fee_out will be lower, and fee_in will be higher. This makes it cheaper to convert fxUSD to the stablecoin and more costly to convert the stablecoin to fxUSD, which encourages activity that pushes the price back up toward the target.


#### How to calculate fee:
The fee adjustments are scaled using the `AdjustmentFee` parameter (k), which controls the responsiveness of the fee to price deviations.

Suppose:
- `newPrice`: new market price of stablecoin relative to nomUSD.
- `feeIn`: inbound fee (to exchange stablecoin to nomUSD).
- `feeOut`: outbound fee (to exchange nomUSD to stablecoin).
- `newPrice`: new market price of stablecoin relative to fxUSD.
- `feeIn`: inbound fee (to exchange stablecoin to fxUSD).
- `feeOut`: outbound fee (to exchange fxUSD to stablecoin).
- `maxFee`: maximum total fee for both directions (usually feeIn + feeOut).
- `k`: adjustment factor (`AdjustmentFee`) that controls the sensitivity of the fee to price changes.

Expand Down
2 changes: 1 addition & 1 deletion x/psm/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func NewSwapToNomCmd() *cobra.Command {
Long: `swap between stable coins.

Example:
$ onomyd tx psm swap 100000000000000000000000nomUSD ibc/xxxxx --from validator1 --keyring-backend test --home ~/.reserved/validator1 --chain-id testing-1 -y --fees 20stake
$ onomyd tx psm swap 100000000000000000000000fxUSD ibc/xxxxx --from validator1 --keyring-backend test --home ~/.reserved/validator1 --chain-id testing-1 -y --fees 20stake

`,

Expand Down
10 changes: 5 additions & 5 deletions x/psm/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func (k Keeper) UpdatesStablecoinEpoch(ctx context.Context) error {
}) //k.IterateStablecoin(ctx, updatePrice)
}

// price is $nomUSD amount to exchange for 1 $stabalecoin
// price is $fxUSD amount to exchange for 1 $stabalecoin
// price taget = 1
// ex:
// oldPrice:1
Expand All @@ -41,20 +41,20 @@ func (k Keeper) UpdatesStablecoinEpoch(ctx context.Context) error {
// k = AdjustmentFeeIn = 40
// ----------------------------------------------------------------------------------------
// case 1:
// newPrice: 1.01 (1.01$nomUSD = 1USDT)
// newPrice: 1.01 (1.01$fxUSD = 1USDT)
// rate = 1/1.01 = 0.990099
// newfeeOut = 0.01/(0.990099)**k = 0.01 * (1.01**40)= 0.014888637335882209
// newfeeIn = 0.02 - 0.014888637335882209 = 0.005111362664117791

// So $USDT swap to $nomUSD will be cheaper than $nomUSD swap to $USDT
// So $USDT swap to $fxUSD will be cheaper than $fxUSD swap to $USDT
// ----------------------------------------------------------------------------------------
// case 2:
// newPrice: 0.99 (0.98$nomUSD = 1USDT)
// newPrice: 0.99 (0.98$fxUSD = 1USDT)
// rate = 1/0.99 = 1.0101010101
// deltaP < 0
// newfeeIn = 0.01 * (1.0101010101)**40 = 0.014948314143157351
// newfeeOut = 0.02 - 0.014948314143157351 = 0.005051685856842649
// So $nomUSD swap to $USDT will be cheaper than $USDT swap to $nomUSD
// So $fxUSD swap to $USDT will be cheaper than $USDT swap to $fxUSD

func (k Keeper) stablecoinUpdate(ctx context.Context, newPrice math.LegacyDec, stablecoin types.StablecoinInfo) types.StablecoinInfo {
params, err := k.GetParams(ctx)
Expand Down
18 changes: 9 additions & 9 deletions x/psm/keeper/swap.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func (k Keeper) SwapToOtherStablecoin(ctx context.Context, addr sdk.AccAddress,
return fmt.Errorf("amount %s locked lesser than amount desired", expectedDenom)
}

// burn nomUSD
// burn fxUSD
coinsBurn := sdk.NewCoins(offerCoin)
err = k.BankKeeper.SendCoinsFromAccountToModule(ctx, addr, types.ModuleName, coinsBurn)
if err != nil {
Expand Down Expand Up @@ -93,7 +93,7 @@ func (k Keeper) SwapToOnomyStableToken(ctx context.Context, accAddress sdk.AccAd
}

// check balance user and calculate amount of coins received
receiveAmountnomUSD, fee_in, err := k.calculateSwapToOnomyStableToken(ctx, offerCoin, stablecoin.Symbol)
receiveAmountfxUSD, fee_in, err := k.calculateSwapToOnomyStableToken(ctx, offerCoin, stablecoin.Symbol)
if err != nil {
return err
}
Expand All @@ -110,8 +110,8 @@ func (k Keeper) SwapToOnomyStableToken(ctx context.Context, accAddress sdk.AccAd
return err
}

// mint nomUSD
coinsMint := sdk.NewCoins(sdk.NewCoin(types.ReserveStableCoinDenom, receiveAmountnomUSD))
// mint fxUSD
coinsMint := sdk.NewCoins(sdk.NewCoin(types.ReserveStableCoinDenom, receiveAmountfxUSD))
err = k.BankKeeper.MintCoins(ctx, types.ModuleName, coinsMint)
if err != nil {
return err
Expand All @@ -126,7 +126,7 @@ func (k Keeper) SwapToOnomyStableToken(ctx context.Context, accAddress sdk.AccAd
sdkCtx := sdk.UnwrapSDKContext(ctx)
sdkCtx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventSwapTonomUSD,
types.EventSwapTofxUSD,
sdk.NewAttribute(types.AttributeAmount, offerCoin.String()),
sdk.NewAttribute(types.AttributeReceive, coinsMint.String()),
sdk.NewAttribute(types.AttributeFeeIn, fee_in.String()),
Expand Down Expand Up @@ -177,13 +177,13 @@ func (k Keeper) calculateSwapToOnomyStableToken(ctx context.Context, stablecoin
return math.Int{}, sdk.DecCoin{}, err
}

amountnomUSD := multiplier.Mul(stablecoin.Amount.ToLegacyDec())
amountfxUSD := multiplier.Mul(stablecoin.Amount.ToLegacyDec())

fee, err := k.PayFeesIn(ctx, amountnomUSD.RoundInt(), stablecoin.Denom)
fee, err := k.PayFeesIn(ctx, amountfxUSD.RoundInt(), stablecoin.Denom)
if err != nil {
return math.Int{}, sdk.DecCoin{}, err
}

receiveAmountnomUSD := amountnomUSD.Sub(fee)
return receiveAmountnomUSD.RoundInt(), sdk.NewDecCoinFromDec(types.ReserveStableCoinDenom, fee), nil
receiveAmountfxUSD := amountfxUSD.Sub(fee)
return receiveAmountfxUSD.RoundInt(), sdk.NewDecCoinFromDec(types.ReserveStableCoinDenom, fee), nil
}
Loading
Loading