Skip to content

Commit

Permalink
Fee Middleware: Escrow logic (#465)
Browse files Browse the repository at this point in the history
* fix: adding second endpoint for async pay fee + renaming types

* feat: adding escrow logic

* feat: updating proto types & escrow logic

* fix: stub fn & proto comment

* feat: adding PayFee & PayFeeTimeout & escrow_test

* test: adding happy path for EscrowPacketFee

* fix: comments, error handling

* fix: comments & grammar

* test: adding unhappy path for escrow

* tests(escrow): adding hasBalance check for module acc

* test(PayFee): adding happy path for PayFee tests

* tests(PayFee, PayFeeTimeout): adding tests

* fix: adding relayers back to IdentifiedPacket

* fix: removing refund acc from key

* fix: storing IdentifiedPacketFee in state instead of Fee

* feat: adding msg_server test for registerCPAddr, wiring for codec + stubs for sdk.Msg interface

* test: adding msg_server test for PayPacketFee

* test: adding PayPacketFeeAsync msg_server test

* chore: updating PayFee -> DistributeFee & minor nits

* nit: removing unnecessary nil check

* refactor: add portId to store key & use packetId as param

* fix: add DeleteFeeInEscrow & remove fee on successful distribution

* tests: adding validation & signer tests for PayFee/Async & updating proto to use Signer sdk standard

* chore: adding NewIdentifiedPacketFee fn

* fix: getter/setter for counterparty address + fix NewIdentifiedPacketFee

* fix: updating EscrowPacketFee with correct usage of coins api

* test: adding balance check for refund acc after escrow

* fix: remove unncessary errors

* test: updating escrow tests + miscellaneous fixes

* nit: updating var names

* docs: godoc

* refactor: IdentifiedPacketFee & Fee no longer pointers

* fixes: small fixes

* Update modules/apps/29-fee/keeper/escrow.go

Co-authored-by: Aditya <[email protected]>

* Update modules/apps/29-fee/keeper/escrow.go

Co-authored-by: Aditya <[email protected]>

* Update modules/apps/29-fee/keeper/keeper.go

Co-authored-by: Aditya <[email protected]>

* Update modules/apps/29-fee/keeper/msg_server.go

Co-authored-by: Aditya <[email protected]>

* Update modules/apps/29-fee/keeper/msg_server.go

Co-authored-by: Aditya <[email protected]>

* Update modules/apps/29-fee/types/msgs.go

Co-authored-by: Aditya <[email protected]>

* nit: proto doc & error fix

* fix: escrow test

* test: updating distribute fee tests

* test: adding validation check for fee and updating tests

* test: allow counterparty address to be arbitrary string

* fix: message validation should pass if one fee is valid

* Update modules/apps/29-fee/keeper/escrow.go

Co-authored-by: colin axnér <[email protected]>

* Update modules/apps/29-fee/keeper/escrow.go

Co-authored-by: colin axnér <[email protected]>

* fix: nits

* Update modules/apps/29-fee/keeper/escrow.go

Co-authored-by: colin axnér <[email protected]>

* test: adding isZero check for msgs

Co-authored-by: Aditya <[email protected]>
Co-authored-by: colin axnér <[email protected]>
  • Loading branch information
3 people authored Nov 5, 2021
1 parent dd4f8c7 commit 67bd594
Show file tree
Hide file tree
Showing 21 changed files with 2,111 additions and 447 deletions.
68 changes: 49 additions & 19 deletions docs/ibc/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@
- [Query](#ibc.applications.fee.v1.Query)

- [ibc/applications/fee/v1/tx.proto](#ibc/applications/fee/v1/tx.proto)
- [MsgEscrowPacketFee](#ibc.applications.fee.v1.MsgEscrowPacketFee)
- [MsgEscrowPacketFeeResponse](#ibc.applications.fee.v1.MsgEscrowPacketFeeResponse)
- [MsgPayPacketFee](#ibc.applications.fee.v1.MsgPayPacketFee)
- [MsgPayPacketFeeAsync](#ibc.applications.fee.v1.MsgPayPacketFeeAsync)
- [MsgPayPacketFeeAsyncResponse](#ibc.applications.fee.v1.MsgPayPacketFeeAsyncResponse)
- [MsgPayPacketFeeResponse](#ibc.applications.fee.v1.MsgPayPacketFeeResponse)
- [MsgRegisterCounterpartyAddress](#ibc.applications.fee.v1.MsgRegisterCounterpartyAddress)
- [MsgRegisterCounterpartyAddressResponse](#ibc.applications.fee.v1.MsgRegisterCounterpartyAddressResponse)

Expand Down Expand Up @@ -628,7 +630,9 @@ https://github.com/cosmos/ibc/tree/master/spec/app/ics-029-fee-payment#fee-middl

| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | |
| `receive_fee` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | |
| `ack_fee` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | |
| `timeout_fee` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | |



Expand All @@ -644,9 +648,7 @@ Fee associated with a packet_id
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `packet_id` | [ibc.core.channel.v1.PacketId](#ibc.core.channel.v1.PacketId) | | |
| `receive_fee` | [Fee](#ibc.applications.fee.v1.Fee) | | |
| `ack_fee` | [Fee](#ibc.applications.fee.v1.Fee) | | |
| `timeout_fee` | [Fee](#ibc.applications.fee.v1.Fee) | | |
| `fee` | [Fee](#ibc.applications.fee.v1.Fee) | | |
| `relayers` | [string](#string) | repeated | |


Expand Down Expand Up @@ -676,11 +678,6 @@ Fee associated with a packet_id
GenesisState defines the fee middleware genesis state


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `packets_fees` | [IdentifiedPacketFee](#ibc.applications.fee.v1.IdentifiedPacketFee) | repeated | A mapping of packets -> escrowed fees |





Expand Down Expand Up @@ -889,26 +886,58 @@ Query provides defines the gRPC querier service.



<a name="ibc.applications.fee.v1.MsgEscrowPacketFee"></a>
<a name="ibc.applications.fee.v1.MsgPayPacketFee"></a>

### MsgEscrowPacketFee
MsgEscrowPacketFee defines the request type EscrowPacketFee RPC
### MsgPayPacketFee
MsgPayPacketFee defines the request type PayPacketFee RPC
This Msg can be used to pay for a packet at the next sequence send & should be combined with the Msg that will be
paid for


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `incentivized_packet` | [IdentifiedPacketFee](#ibc.applications.fee.v1.IdentifiedPacketFee) | | |
| `fee` | [Fee](#ibc.applications.fee.v1.Fee) | | |
| `source_port_id` | [string](#string) | | source channel port identifier |
| `source_channel_id` | [string](#string) | | source channel unique identifier |
| `signer` | [string](#string) | | account address to refund fee if necessary |
| `relayers` | [string](#string) | repeated | |






<a name="ibc.applications.fee.v1.MsgEscrowPacketFeeResponse"></a>
<a name="ibc.applications.fee.v1.MsgPayPacketFeeAsync"></a>

### MsgPayPacketFeeAsync
MsgPayPacketFeeAsync defines the request type PayPacketFeeAsync RPC
This Msg can be used to pay for a packet at a specified sequence (instead of the next sequence send)


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `identified_packet_fee` | [IdentifiedPacketFee](#ibc.applications.fee.v1.IdentifiedPacketFee) | | packet to pay fee for |
| `signer` | [string](#string) | | account address to refund fee if necessary |






<a name="ibc.applications.fee.v1.MsgPayPacketFeeAsyncResponse"></a>

### MsgPayPacketFeeAsyncResponse
MsgPayPacketFeeAsyncResponse defines the response type for Msg/PayPacketFeeAsync






<a name="ibc.applications.fee.v1.MsgPayPacketFeeResponse"></a>

### MsgEscrowPacketFeeResponse
MsgEscrowPacketFeeResponse defines the response type for Msg/EscrowPacketFee
### MsgPayPacketFeeResponse
MsgPayPacketFeeResponse defines the response type for Msg/PayPacketFee



Expand Down Expand Up @@ -955,7 +984,8 @@ Msg defines the ibc/fee Msg service.
| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint |
| ----------- | ------------ | ------------- | ------------| ------- | -------- |
| `RegisterCounterpartyAddress` | [MsgRegisterCounterpartyAddress](#ibc.applications.fee.v1.MsgRegisterCounterpartyAddress) | [MsgRegisterCounterpartyAddressResponse](#ibc.applications.fee.v1.MsgRegisterCounterpartyAddressResponse) | RegisterCounterpartyAddress defines a rpc handler method for MsgRegisterCounterpartyAddress RegisterCounterpartyAddress is called by the relayer on each channelEnd and allows them to specify their counterparty address before relaying. This ensures they will be properly compensated for forward relaying since destination chain must send back relayer's source address (counterparty address) in acknowledgement. This function may be called more than once by a relayer, in which case, latest counterparty address is always used. | |
| `EscrowPacketFee` | [MsgEscrowPacketFee](#ibc.applications.fee.v1.MsgEscrowPacketFee) | [MsgEscrowPacketFeeResponse](#ibc.applications.fee.v1.MsgEscrowPacketFeeResponse) | EscrowPacketFee defines a rpc handler method for MsgEscrowPacketFee EscrowPacketFee is an open callback that may be called by any module/user that wishes to escrow funds in order to incentivize the relaying of the given packet. | |
| `PayPacketFee` | [MsgPayPacketFee](#ibc.applications.fee.v1.MsgPayPacketFee) | [MsgPayPacketFeeResponse](#ibc.applications.fee.v1.MsgPayPacketFeeResponse) | PayPacketFee defines a rpc handler method for MsgPayPacketFee PayPacketFee is an open callback that may be called by any module/user that wishes to escrow funds in order to incentivize the relaying of the packet at the next sequence | |
| `PayPacketFeeAsync` | [MsgPayPacketFeeAsync](#ibc.applications.fee.v1.MsgPayPacketFeeAsync) | [MsgPayPacketFeeAsyncResponse](#ibc.applications.fee.v1.MsgPayPacketFeeAsyncResponse) | PayPacketFeeAsync defines a rpc handler method for MsgPayPacketFeeAsync PayPacketFeeAsync is an open callback that may be called by any module/user that wishes to escrow funds in order to incentivize the relaying of a known packet | |

<!-- end services -->

Expand Down
106 changes: 106 additions & 0 deletions modules/apps/29-fee/keeper/escrow.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package keeper

import (
"fmt"

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

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

"github.com/cosmos/ibc-go/modules/apps/29-fee/types"
channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types"
)

// EscrowPacketFee sends the packet fee to the 29-fee module account to hold in escrow
func (k Keeper) EscrowPacketFee(ctx sdk.Context, refundAcc sdk.AccAddress, identifiedFee *types.IdentifiedPacketFee) error {
// check if the refund account exists
hasRefundAcc := k.authKeeper.GetAccount(ctx, refundAcc)
if hasRefundAcc == nil {
return sdkerrors.Wrap(types.ErrRefundAccNotFound, fmt.Sprintf("Account with address: %s not found", refundAcc))
}

coins := identifiedFee.Fee.ReceiveFee
coins = coins.Add(identifiedFee.Fee.AckFee...)
coins = coins.Add(identifiedFee.Fee.TimeoutFee...)

if err := k.bankKeeper.SendCoinsFromAccountToModule(
ctx, refundAcc, types.ModuleName, coins,
); err != nil {
return err
}

// Store fee in state for reference later
// feeInEscrow/<port-id>/<channel-id>/packet/<sequence-id>/ -> Fee (timeout, ack, onrecv)
k.SetFeeInEscrow(ctx, identifiedFee)
return nil
}

// DistributeFee pays the acknowledgement fee & receive fee for a given packetId while refunding the timeout fee to the refund account associated with the Fee
func (k Keeper) DistributeFee(ctx sdk.Context, refundAcc, forwardRelayer, reverseRelayer sdk.AccAddress, packetID *channeltypes.PacketId) error {
// check if there is a Fee in escrow for the given packetId
feeInEscrow, found := k.GetFeeInEscrow(ctx, packetID)
if !found {
return sdkerrors.Wrapf(types.ErrFeeNotFound, "with channelID %s, sequence %d", packetID.ChannelId, packetID.Sequence)
}

// get module accAddr
feeModuleAccAddr := k.authKeeper.GetModuleAddress(types.ModuleName)

// send receive fee to forward relayer
err := k.bankKeeper.SendCoins(ctx, feeModuleAccAddr, forwardRelayer, feeInEscrow.Fee.ReceiveFee)
if err != nil {
return sdkerrors.Wrap(err, "failed to send fee to forward relayer")
}

// send ack fee to reverse relayer
err = k.bankKeeper.SendCoins(ctx, feeModuleAccAddr, reverseRelayer, feeInEscrow.Fee.AckFee)
if err != nil {
return sdkerrors.Wrap(err, "error sending fee to reverse relayer")
}

// refund timeout fee to refundAddr
err = k.bankKeeper.SendCoins(ctx, feeModuleAccAddr, refundAcc, feeInEscrow.Fee.TimeoutFee)
if err != nil {
return sdkerrors.Wrap(err, "error refunding timeout fee")
}

// removes the fee from the store as fee is now paid
k.DeleteFeeInEscrow(ctx, packetID)

return nil
}

// DistributeFeeTimeout pays the timeout fee for a given packetId while refunding the acknowledgement fee & receive fee to the refund account associated with the Fee
func (k Keeper) DistributeFeeTimeout(ctx sdk.Context, refundAcc, timeoutRelayer sdk.AccAddress, packetID *channeltypes.PacketId) error {
// check if there is a Fee in escrow for the given packetId
feeInEscrow, found := k.GetFeeInEscrow(ctx, packetID)
if !found {
return sdkerrors.Wrap(types.ErrFeeNotFound, refundAcc.String())
}

// get module accAddr
feeModuleAccAddr := k.authKeeper.GetModuleAddress(types.ModuleName)

// refund the receive fee
err := k.bankKeeper.SendCoins(ctx, feeModuleAccAddr, refundAcc, feeInEscrow.Fee.ReceiveFee)
if err != nil {
return sdkerrors.Wrap(err, "error refunding receive fee")
}

// refund the ack fee
err = k.bankKeeper.SendCoins(ctx, feeModuleAccAddr, refundAcc, feeInEscrow.Fee.AckFee)
if err != nil {
return sdkerrors.Wrap(err, "error refunding ack fee")
}

// pay the timeout fee to the reverse relayer
err = k.bankKeeper.SendCoins(ctx, feeModuleAccAddr, timeoutRelayer, feeInEscrow.Fee.TimeoutFee)
if err != nil {
return sdkerrors.Wrap(err, "error sending fee to timeout relayer")
}

// removes the fee from the store as fee is now paid
k.DeleteFeeInEscrow(ctx, packetID)

return nil
}
Loading

0 comments on commit 67bd594

Please sign in to comment.