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

Introduce custom logic into OnRecvPacket in PFM module to charge fee #520

Merged
merged 12 commits into from
Jun 11, 2024

Conversation

RustNinja
Copy link
Collaborator

@RustNinja RustNinja commented May 22, 2024

Introduce custom logic into OnRecvPacket in PFM module to charge fee

this code in custom pfm inside IbcMiddleware OnRecvPacket method introduced by me.
https://github.com/ComposableFi/composable-cosmos/blob/rustninja/pmf-middleware/custom/custompfm/keeper/keeper.go#L185-L216

all other code in method OnRecvPacket is taken from original version of OnRecvPacket.

}
}

func (im IBCMiddleware) OnRecvPacket(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't you need to implement all of the methods?

Copy link
Collaborator Author

@RustNinja RustNinja May 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, all other methods are implemented because i include into mine IbcMidleware type the original IbcMiddleware that bring implementation of others methods as inherited from original
I just override the only one method to inject my custom fee logic

@rjonczy rjonczy self-requested a review May 22, 2024 17:33
Copy link
Contributor

@rjonczy rjonczy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you target develop2 ?

target: main (current mainnet) or testnet (current testnet)

@blasrodri
Copy link
Collaborator

Please include an interchain test here

custom/custompfm/keeper/keeper.go Show resolved Hide resolved
im.keeper1.Logger(ctx).Error("packetForwardMiddleware error marshaling next as JSON",
"error", err,
)
// return errorsmod.Wrapf(sdkerrors.ErrJSONMarshal, err.Error())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we don't return an error here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error will be handled by original pfm in case if memo was incorrect.

custom/custompfm/keeper/keeper.go Show resolved Hide resolved
custom/custompfm/keeper/keeper.go Show resolved Hide resolved
@RustNinja RustNinja changed the base branch from develop2 to testnet May 22, 2024 18:11
@RustNinja
Copy link
Collaborator Author

Why do you target develop2 ?

target: main (current mainnet) or testnet (current testnet)

this is devnet. first devnet. then will merge into testnet. and will go to testnet.

@RustNinja RustNinja changed the base branch from testnet to develop2 May 22, 2024 18:53
@RustNinja RustNinja requested a review from vmarkushin May 23, 2024 13:03
Copy link

@vmarkushin vmarkushin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please highlight the changes to the middleware in the code so it's clear where it's the original middleware and where it's our changes

@RustNinja
Copy link
Collaborator Author

Please highlight the changes to the middleware in the code so it's clear where it's the original middleware and where it's our changes

at the description

i duplicate here too
https://github.com/ComposableFi/composable-cosmos/blob/rustninja/pmf-middleware/custom/custompfm/keeper/keeper.go#L185-L216

retries = im.retriesOnTimeout1
}

// im.ibcfeekeeper.Transfer()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove such commented code everywhere, otherwise leave a comment explaining why it's needed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Receiver sdk.AccAddress
}

func (k Keeper) ChargeFee(ctx sdk.Context, msg *ibctypes.MsgTransfer) (*BridgeFee, error) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why ChargeFee has something to do with timeouts?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will rename function
thanks

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed.

return nil, fmt.Errorf("token not allowed to be transferred in this channel")
}

minFee := coin.MinFee.Amount

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this function takes all the fees or only some specific ones?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

function
calculate fee based on config as percentage fee + min fee for some specific demon

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. this fee is the logic from original pfm.
it is different.

our requirements is to add extra field depends on channel and denom. where each fee contains 3 params
account where to send this fee, percentage from amount + min amount equal to 20$.

Comment on lines +146 to +151
if priority != nil {
p := findPriority(coin.TxPriorityFee, *priority)
if p != nil && coin.MinFee.Denom == p.PriorityFee.Denom {
minFee = minFee.Add(p.PriorityFee.Amount)
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the sender specifies in the memo a priority coin that is not in the TxPriorityFee or with a Denom different from the MinFee one, it will be not charged and no error raised. Is this intentional?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. So FE is responsible to set a proper priority (high, medium, low) depends on config in storage for this denom.

Comment on lines 203 to 205
if result.Fee.Amount.LT(token.Amount) {
token = token.SubAmount(result.Fee.Amount)
} else {
Copy link

@christianvari christianvari May 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

result.Fee is calculated on PacketCoin which is token deducted by the pfm fees.
However since here we deduct token instead of PacketCoin and then pass it to ForwardTransferPacket which applies pfm fees to it, we will get inaccurate calculations for non-fixed fees

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It depends how to specify the order of charging a fee.
charge bridge fee when pfm already was charged or opposite.

But now problem. i will remove extra code where i intentionally first determinate the pfm fee and use new amount to charge extra bridge fee for specific channel and denom.

I got your point. Accepted your request.

Comment on lines 202 to 206
if result != nil {
if result.Fee.Amount.LT(token.Amount) {
token = token.SubAmount(result.Fee.Amount)
} else {
send_err := im.bank.SendCoins(ctx, result.Sender, result.Receiver, sdk.NewCoins(result.Fee))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case result.Fee.Amount.LT(token.Amount) we are deducting the Fee from token, however, fees are not sent to the feeAddress and will remain in the receiver account

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is really good point.
Thanks.
Updated the logic.

Comment on lines 204 to 211
token = token.SubAmount(result.Fee.Amount)
} else {
send_err := im.bank.SendCoins(ctx, result.Sender, result.Receiver, sdk.NewCoins(result.Fee))
if send_err != nil {
logger.Error("packetForwardMiddleware OnRecvPacket error sending fee", "error", send_err)
return newErrorAcknowledgement(fmt.Errorf("error charging fee: %w", send_err))
}
ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)})

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if the SendCoins here would work correctly. Funds at this point have already been received by the overrideReceiver so they should be transferred from this account probably.

overrideReceiver, err := getReceiver(packet.DestinationChannel, data.Sender)
if err != nil {
logger.Error("packetForwardMiddleware OnRecvPacket failed to construct override receiver", "error", err)
return newErrorAcknowledgement(fmt.Errorf("failed to construct override receiver: %w", err))
}
// if this packet has been handled by another middleware in the stack there may be no need to call into the
// underlying app, otherwise the transfer module's OnRecvPacket callback could be invoked more than once
// which would mint/burn vouchers more than once
if !processed {
if err := im.receiveFunds(ctx, packet, data, overrideReceiver, relayer); err != nil {
logger.Error("packetForwardMiddleware OnRecvPacket error receiving packet", "error", err)
return newErrorAcknowledgement(fmt.Errorf("error receiving packet: %w", err))
}
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@christianvari
thank you a lot for warning.

you are correct. assets already sent to override receiver address. so fee should be sent from that account.
And this is exactly what our custom logic is doing.

Look.

tr := transfertypes.NewMsgTransfer(
		metadata.Port,
		metadata.Channel,
		token,
		overrideReceiver,
		metadata.Receiver,
		clienttypes.Height{
			RevisionNumber: 0,
			RevisionHeight: 0,
		},
		uint64(ctx.BlockTime().UnixNano())+uint64(timeout.Nanoseconds()),
		memo,
	)

	result, err := im.ibcfeekeeper.GetBridgeFeeBasedOnConfigForChannelAndDenom(ctx, tr)

I created tr variable passing the exact overrideReceiver as a sender
So the result from GetBridgeFeeBasedOnConfigForChannelAndDenom contains a field sender that equal to overrideReceiver.
So all good.
Thank for pointing and double check.

- remove calculation of pfm fee before request calculation of extra
birdge fee for channel and denom if exists
- fix a bug when send to fee account only one case when fee is less then
token amount. so it was a bug. fixed. now send coin always when fee is
less then token amount or equal.
hoank101 and others added 3 commits June 11, 2024 14:26
Co-authored-by: dzmitry-lahoda <dzmitry@lahoda.pro>
Co-authored-by: kienn6034 <kien@notional.ventures>
Co-authored-by: rustdev <placex.com@gmail.com>
Co-authored-by: rust.dev <102041955+RustNinja@users.noreply.github.com>
Co-authored-by: kkast <kkastsevich@gmail.com>
Co-authored-by: Kanstantsin Kastsevich <kkast@users.noreply.github.com>
Co-authored-by: rjonczy <robert.jonczy@gmail.com>
Co-authored-by: tungle <anhletung@notional.ventures>
…-cosmos into rustninja/pmf-middleware

# Conflicts:
#	app/keepers/keepers.go
#	x/ibctransfermiddleware/keeper/keeper.go
@RustNinja RustNinja merged commit 8fce893 into develop2 Jun 11, 2024
16 of 17 checks passed
@RustNinja RustNinja deleted the rustninja/pmf-middleware branch June 11, 2024 21:53
RustNinja added a commit that referenced this pull request Jun 21, 2024
This pr is the same as
[this](#520) but
into `testnet` branch instead of `develop2`.
Test failed in testnet branch bz of prefix migration.
tests are fixed in develop2, so once develop2 will be merged to testnet.
tests related to prefix will be fixed as well in `testnet` branch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants