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

Auto-swap non-osmo tx fees to osmo #1145

Merged
merged 84 commits into from
Apr 22, 2022
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
98eed0b
migrate deductfeesdecorator to txfees module & set up second module a…
AlpinYukseloglu Mar 24, 2022
bb1857c
add second module account to supported module accounts in app
AlpinYukseloglu Mar 25, 2022
88b4401
set up txFeesKeeper with new keeper interface in app
AlpinYukseloglu Mar 25, 2022
2b7f32f
add hook receiver to epoch hooks for txfees module
AlpinYukseloglu Mar 25, 2022
0becf2a
set up AfterEpochEnd hook to swap all non-OSMO fees to OSMO
AlpinYukseloglu Mar 25, 2022
ad8bd35
clean up feedecorator comments
AlpinYukseloglu Mar 25, 2022
c2c848e
add relevant keepers to TxFeeKeeper struct
AlpinYukseloglu Mar 25, 2022
6467af6
revert accidental file changes due to branch mixup
AlpinYukseloglu Mar 25, 2022
e5d46e1
revert accidental file changes due to branch mixup
AlpinYukseloglu Mar 25, 2022
cfae2f0
add rudimentary swapping logic
AlpinYukseloglu Mar 25, 2022
528edfd
clean up comments and spacing
AlpinYukseloglu Mar 25, 2022
9db3006
add gammkeeper and move swap calls under it
AlpinYukseloglu Mar 25, 2022
8850485
comments for intended feedecorator tests
AlpinYukseloglu Mar 25, 2022
26c3316
fix swap parameters to get correct pool id and minimum output
AlpinYukseloglu Mar 25, 2022
3f40623
set up feegrantkeeper in suite app for testing
AlpinYukseloglu Mar 25, 2022
2d1ceb2
Update x/txfees/keeper/feedecorator.go
AlpinYukseloglu Mar 27, 2022
081d9a7
Update x/txfees/keeper/feedecorator.go
AlpinYukseloglu Mar 27, 2022
aa5775e
Update x/txfees/keeper/feedecorator.go
AlpinYukseloglu Mar 27, 2022
184b939
Update x/txfees/keeper/feedecorator.go
AlpinYukseloglu Mar 27, 2022
4bce525
Update x/txfees/keeper/feedecorator.go
AlpinYukseloglu Mar 27, 2022
5032ca1
Apply suggestions from code review
AlpinYukseloglu Mar 27, 2022
9719f75
Merge branch 'auto-fee-swaps' of https://github.com/osmosis-labs/osmo…
AlpinYukseloglu Mar 27, 2022
b9026d1
update comments
AlpinYukseloglu Mar 27, 2022
349bc70
attempt to migrate test from legacytx to txbuilder
AlpinYukseloglu Mar 28, 2022
d8fbd81
updates
alexanderbez Mar 28, 2022
8002532
update txbuilder setup
AlpinYukseloglu Mar 28, 2022
5371229
update feedecorator test for sanity check on dfd
AlpinYukseloglu Mar 28, 2022
4f1fded
working second module acc tx tests
AlpinYukseloglu Mar 29, 2022
b1b02cf
clean up debugging and comments
AlpinYukseloglu Mar 29, 2022
2ddddd2
remove superfluous comments
AlpinYukseloglu Mar 29, 2022
634c2b8
add tests for hooks.go
AlpinYukseloglu Mar 29, 2022
573f48c
complete fee swap and distribution tests
AlpinYukseloglu Mar 29, 2022
a611c28
clean up comments
AlpinYukseloglu Mar 29, 2022
5ffcf27
remove import comments app/keepers.go
AlpinYukseloglu Mar 29, 2022
38a9609
Apply suggestions from code review
AlpinYukseloglu Mar 30, 2022
f03ca7e
change name for second module account to AltFeeCollector
AlpinYukseloglu Mar 30, 2022
5cda003
go docs for CalcOutGivenIn function
AlpinYukseloglu Mar 30, 2022
dccb1dd
updates
alexanderbez Mar 30, 2022
7355d76
updates
alexanderbez Mar 30, 2022
495be0a
updates
alexanderbez Mar 30, 2022
7a41952
Apply suggestions from code review
AlpinYukseloglu Apr 4, 2022
d483612
Apply suggestions from code review
AlpinYukseloglu Apr 6, 2022
82454dd
update second module name
AlpinYukseloglu Apr 6, 2022
0c001f4
add error check for swaps
AlpinYukseloglu Apr 6, 2022
5c8ec96
Apply comment suggestions from code review
AlpinYukseloglu Apr 6, 2022
3cb4fc7
add minTokenOut comments
AlpinYukseloglu Apr 6, 2022
d33ae10
update swap error checking logic
AlpinYukseloglu Apr 6, 2022
213d32e
set up changes for hook tests
AlpinYukseloglu Apr 7, 2022
d9609d5
resolve merge conflicts
AlpinYukseloglu Apr 7, 2022
e415a51
merge related fixes
AlpinYukseloglu Apr 7, 2022
3fe3b63
merge related updates
AlpinYukseloglu Apr 7, 2022
637b75c
gofmt updates
AlpinYukseloglu Apr 7, 2022
f803faa
Fix feekeeper test setup
ValarDragon Apr 7, 2022
273fc3b
switch tests to cleaner approach for resetting
AlpinYukseloglu Apr 9, 2022
d710ad0
refactor tx building into test suite
AlpinYukseloglu Apr 9, 2022
b6da360
add error checks and run linters
AlpinYukseloglu Apr 9, 2022
8bdea1f
formatting
AlpinYukseloglu Apr 9, 2022
903b2a2
fix linting related issues
AlpinYukseloglu Apr 9, 2022
691dce4
Apply suggestions from code review
AlpinYukseloglu Apr 13, 2022
6eec713
apply suggestions from review
AlpinYukseloglu Apr 13, 2022
68d2ad2
Merge branch 'main' into auto-fee-swaps
AlpinYukseloglu Apr 13, 2022
193f832
run linter
AlpinYukseloglu Apr 13, 2022
5b5749d
run linter
AlpinYukseloglu Apr 13, 2022
87bd397
fix import-related issues
AlpinYukseloglu Apr 13, 2022
342761c
fix merge conflicts
AlpinYukseloglu Apr 13, 2022
c1228c3
Delete math.go
AlpinYukseloglu Apr 14, 2022
02056ae
Merge branch 'main' into auto-fee-swaps
AlpinYukseloglu Apr 14, 2022
1e43f4e
Fix build error
ValarDragon Apr 15, 2022
b60e0a0
Merge branch 'main' into auto-fee-swaps
ValarDragon Apr 15, 2022
709bceb
Fix formatting
ValarDragon Apr 15, 2022
05b3fbc
Not sure why make format didn't catch this
ValarDragon Apr 15, 2022
3d8e7dc
import fixes
AlpinYukseloglu Apr 15, 2022
2b8140d
Delete fee grant keeper
ValarDragon Apr 15, 2022
dbc7cb1
Merge branch 'auto-fee-swaps' of https://github.com/osmosis-labs/osmo…
AlpinYukseloglu Apr 16, 2022
c152510
gerge branch 'auto-fee-swaps' of https://github.com/osmosis-labs/osmo…
AlpinYukseloglu Apr 18, 2022
faf48a5
fix tests to accommodate removal of fee grant keeper
AlpinYukseloglu Apr 18, 2022
ab34ca3
remove panic errors at epoch end and remove potential for unbounded d…
AlpinYukseloglu Apr 18, 2022
366da35
Apply suggestions from code review
AlpinYukseloglu Apr 18, 2022
84ab533
Update epoch code + DRY some of the test
ValarDragon Apr 18, 2022
08c4a8f
Merge branch 'main' into auto-fee-swaps
ValarDragon Apr 21, 2022
f3c0eee
formatting
AlpinYukseloglu Apr 21, 2022
85d215b
formatting
AlpinYukseloglu Apr 21, 2022
2c22499
Fix build & keeper import
ValarDragon Apr 22, 2022
f341152
Apply suggestions from code review
ValarDragon Apr 22, 2022
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
3 changes: 2 additions & 1 deletion app/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func NewAnteHandler(
) sdk.AnteHandler {
mempoolFeeOptions := txfeestypes.NewMempoolFeeOptions(appOpts)
mempoolFeeDecorator := txfeeskeeper.NewMempoolFeeDecorator(*txFeesKeeper, mempoolFeeOptions)
deductFeeDecorator := txfeeskeeper.NewDeductFeeDecorator(*txFeesKeeper, ak, bankKeeper, nil)
AlpinYukseloglu marked this conversation as resolved.
Show resolved Hide resolved
return sdk.ChainAnteDecorators(
ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
wasmkeeper.NewLimitSimulationGasDecorator(wasmConfig.SimulationGasLimit),
Expand All @@ -43,7 +44,7 @@ func NewAnteHandler(
ante.TxTimeoutHeightDecorator{},
ante.NewValidateMemoDecorator(ak),
ante.NewConsumeGasForTxSizeDecorator(ak),
ante.NewDeductFeeDecorator(ak, bankKeeper, nil),
deductFeeDecorator,
ante.NewSetPubKeyDecorator(ak), // SetPubKeyDecorator must be called before all signature verification decorators
ante.NewValidateSigCountDecorator(ak),
ante.NewSigGasConsumeDecorator(ak, sigGasConsumer),
Expand Down
20 changes: 18 additions & 2 deletions app/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ import (
// Staking: Allows the Tendermint validator set to be chosen based on bonded stake.
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"

// Upgrade: Software upgrades handling and coordination.
feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper"
"github.com/cosmos/cosmos-sdk/x/upgrade"
upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
Expand Down Expand Up @@ -158,6 +157,7 @@ type appKeepers struct {
MintKeeper *mintkeeper.Keeper
PoolIncentivesKeeper *poolincentiveskeeper.Keeper
TxFeesKeeper *txfeeskeeper.Keeper
FeeGrantKeeper *feegrantkeeper.Keeper
AlpinYukseloglu marked this conversation as resolved.
Show resolved Hide resolved
SuperfluidKeeper *superfluidkeeper.Keeper
GovKeeper *govkeeper.Keeper
WasmKeeper *wasm.Keeper
Expand Down Expand Up @@ -358,13 +358,28 @@ func (app *OsmosisApp) InitNormalKeepers(
)
app.PoolIncentivesKeeper = &poolIncentivesKeeper

// Note: gammKeeper is expected to satisfy the SpotPriceCalculator interface parameter
txFeesKeeper := txfeeskeeper.NewKeeper(
appCodec,
app.AccountKeeper,
app.BankKeeper,
app.EpochsKeeper,
keys[txfeestypes.StoreKey],
app.GAMMKeeper,
app.GAMMKeeper,
AlpinYukseloglu marked this conversation as resolved.
Show resolved Hide resolved
txfeestypes.FeeCollectorName,
txfeestypes.FooCollectorName,
)
app.TxFeesKeeper = &txFeesKeeper

// Note: gammKeeper is expected to satisfy the SpotPriceCalculator interface parameter
AlpinYukseloglu marked this conversation as resolved.
Show resolved Hide resolved
feeGrantKeeper := feegrantkeeper.NewKeeper(
appCodec,
keys[txfeestypes.StoreKey],
app.AccountKeeper,
)
app.FeeGrantKeeper = &feeGrantKeeper

// The last arguments can contain custom message handlers, and custom query handlers,
// if we want to allow any custom callbacks
supportedFeatures := "iterator,staking,stargate"
Expand Down Expand Up @@ -465,6 +480,7 @@ func (app *OsmosisApp) SetupHooks() {
app.EpochsKeeper.SetHooks(
epochstypes.NewMultiEpochHooks(
// insert epoch hooks receivers here
app.TxFeesKeeper.Hooks(),
app.SuperfluidKeeper.Hooks(),
app.IncentivesKeeper.Hooks(),
app.MintKeeper.Hooks(),
Expand Down
1 change: 1 addition & 0 deletions app/modules.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ var moduleAaccountPermissions = map[string][]string{
poolincentivestypes.ModuleName: nil,
superfluidtypes.ModuleName: {authtypes.Minter, authtypes.Burner},
txfeestypes.ModuleName: nil,
txfeestypes.FooCollectorName: nil,
wasm.ModuleName: {authtypes.Burner},
}

Expand Down
16 changes: 16 additions & 0 deletions x/gamm/keeper/math.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,22 @@ func calcOutGivenIn(
return tokenAmountOut
}

// exported version
AlpinYukseloglu marked this conversation as resolved.
Show resolved Hide resolved
func CalcOutGivenIn(
AlpinYukseloglu marked this conversation as resolved.
Show resolved Hide resolved
tokenBalanceIn,
tokenWeightIn,
tokenBalanceOut,
tokenWeightOut,
tokenAmountIn,
swapFee sdk.Dec,
) sdk.Dec {
// deduct swapfee on the in asset
tokenAmountInAfterFee := tokenAmountIn.Mul(sdk.OneDec().Sub(swapFee))
// delta balanceOut is positive(tokens inside the pool decreases)
tokenAmountOut := solveConstantFunctionInvariant(tokenBalanceIn, tokenBalanceIn.Add(tokenAmountInAfterFee), tokenWeightIn, tokenBalanceOut, tokenWeightOut)
AlpinYukseloglu marked this conversation as resolved.
Show resolved Hide resolved
return tokenAmountOut
}

AlpinYukseloglu marked this conversation as resolved.
Show resolved Hide resolved
// calcInGivenOut calculates token to be provided, fee added,
// given the swapped out amount, using solveConstantFunctionInvariant
func calcInGivenOut(
Expand Down
118 changes: 118 additions & 0 deletions x/txfees/keeper/feedecorator.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package keeper

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

"github.com/osmosis-labs/osmosis/v7/x/txfees/keeper/txfee_filters"
"github.com/osmosis-labs/osmosis/v7/x/txfees/types"

authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
)

// MempoolFeeDecorator will check if the transaction's fee is at least as large
Expand Down Expand Up @@ -119,3 +123,117 @@ func (mfd MempoolFeeDecorator) GetMinBaseGasPriceForTx(ctx sdk.Context, baseDeno
}
return cfgMinGasPrice
}

// DeductFeeDecorator deducts fees from the first signer of the tx.
// If the first signer does not have the funds to pay for the fees, we return an InsufficientFunds error.
// We call next AnteHandler if fees successfully deducted.
//
// CONTRACT: Tx must implement FeeTx interface to use DeductFeeDecorator
type DeductFeeDecorator struct {
ak types.AccountKeeper
bankKeeper types.BankKeeper
feegrantKeeper types.FeegrantKeeper
txFeesKeeper Keeper
}

func NewDeductFeeDecorator(tk Keeper, ak types.AccountKeeper, bk types.BankKeeper, fk types.FeegrantKeeper) DeductFeeDecorator {
return DeductFeeDecorator{
ak: ak,
bankKeeper: bk,
feegrantKeeper: fk,
txFeesKeeper: tk,
}
}

func (dfd DeductFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {

AlpinYukseloglu marked this conversation as resolved.
Show resolved Hide resolved
feeTx, ok := tx.(sdk.FeeTx)
if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
}

// checks to make sure the module account has been set to collect fees in OSMO
ValarDragon marked this conversation as resolved.
Show resolved Hide resolved
if addr := dfd.ak.GetModuleAddress(types.FeeCollectorName); addr == nil {
return ctx, fmt.Errorf("Fee collector module account (%s) has not been set", types.FeeCollectorName)
}

// checks to make sure a separate module account has been set to collect fees not in OSMO
ValarDragon marked this conversation as resolved.
Show resolved Hide resolved
if addrFoo := dfd.ak.GetModuleAddress(types.FooCollectorName); addrFoo == nil {
AlpinYukseloglu marked this conversation as resolved.
Show resolved Hide resolved
return ctx, fmt.Errorf("Foo collector module account (%s) has not been set", types.FooCollectorName)
}

// fee can be in any denom (checked for validity later)
fee := feeTx.GetFee()
feePayer := feeTx.FeePayer()
feeGranter := feeTx.FeeGranter()

// set the fee payer as the default address to deduct fees from
deductFeesFrom := feePayer

// If a fee granter was set, deduct fee from the fee granter's account.
if feeGranter != nil {
if dfd.feegrantKeeper == nil {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "fee grants is not enabled")
} else if !feeGranter.Equals(feePayer) {
err := dfd.feegrantKeeper.UseGrantedFees(ctx, feeGranter, feePayer, fee, tx.GetMsgs())

if err != nil {
return ctx, sdkerrors.Wrapf(err, "%s not allowed to pay fees from %s", feeGranter, feePayer)
}
}

// if no errors, change the account that is charged for fees to the fee granter
deductFeesFrom = feeGranter
}

deductFeesFromAcc := dfd.ak.GetAccount(ctx, deductFeesFrom)
if deductFeesFromAcc == nil {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "fee payer address: %s does not exist", deductFeesFrom)
}

// deducts the fees and transfer them to the module account
if !feeTx.GetFee().IsZero() {
err = DeductFees(dfd.txFeesKeeper, dfd.bankKeeper, ctx, deductFeesFromAcc, feeTx.GetFee())
if err != nil {
return ctx, err
}
}

AlpinYukseloglu marked this conversation as resolved.
Show resolved Hide resolved
ctx.EventManager().EmitEvents(sdk.Events{sdk.NewEvent(sdk.EventTypeTx,
sdk.NewAttribute(sdk.AttributeKeyFee, feeTx.GetFee().String()),
)})

return next(ctx, tx, simulate)
}

// DeductFees deducts fees from the given account and transfers them to the set module account.
func DeductFees(txFeesKeeper types.TxFeesKeeper, bankKeeper types.BankKeeper, ctx sdk.Context, acc authtypes.AccountI, fees sdk.Coins) error {

AlpinYukseloglu marked this conversation as resolved.
Show resolved Hide resolved
// Checks the validity of the fee tokens (sorted, have positive amount, valid and unique denomination)
if !fees.IsValid() {
return sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "invalid fee amount: %s", fees)
}

// pulls base denom from TxFeesKeeper (should be uOSMO)
baseDenom, err := txFeesKeeper.GetBaseDenom(ctx)
if err != nil {
return err
}

// checks if input fee is uOSMO (assumes only one fee token exists in the fees array (as per the check in mempoolFeeDecorator))
if fees[0].Denom == baseDenom {
AlpinYukseloglu marked this conversation as resolved.
Show resolved Hide resolved
// sends to FeeCollectorName module account
err := bankKeeper.SendCoinsFromAccountToModule(ctx, acc.GetAddress(), types.FeeCollectorName, fees)
if err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, err.Error())
}
} else {
// sends to FooCollectorName module account
err := bankKeeper.SendCoinsFromAccountToModule(ctx, acc.GetAddress(), types.FooCollectorName, fees)
if err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, err.Error())
}
}

return nil
}
Loading