Skip to content

Commit 9ca9872

Browse files
committed
fix(igp): allow IGP zero fee
1 parent 7310d9d commit 9ca9872

3 files changed

Lines changed: 127 additions & 1 deletion

File tree

x/core/02_post_dispatch/keeper/hook_igp.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ func (i InterchainGasPaymasterHookHandler) PayForGasWithoutQuote(ctx context.Con
6969
}
7070

7171
if amount.IsZero() {
72-
return fmt.Errorf("amount must be greater than zero")
72+
// Nothing to charge
73+
return nil
7374
}
7475

7576
senderAcc, err := sdk.AccAddressFromBech32(sender)
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package keeper_test
2+
3+
import (
4+
"cosmossdk.io/math"
5+
6+
i "github.com/bcp-innovations/hyperlane-cosmos/tests/integration"
7+
"github.com/bcp-innovations/hyperlane-cosmos/util"
8+
"github.com/bcp-innovations/hyperlane-cosmos/x/core/02_post_dispatch/types"
9+
sdk "github.com/cosmos/cosmos-sdk/types"
10+
"github.com/cosmos/gogoproto/proto"
11+
. "github.com/onsi/ginkgo/v2"
12+
. "github.com/onsi/gomega"
13+
)
14+
15+
var _ = Describe("hook_igp_test.go", Ordered, func() {
16+
var s *i.KeeperTestSuite
17+
var creator i.TestValidatorAddress
18+
19+
var mailboxId util.HexAddress
20+
var hookId util.HexAddress
21+
22+
const igpDenom = "uatom"
23+
const actualDenom = "uosmo"
24+
25+
BeforeEach(func() {
26+
s = i.NewCleanChain()
27+
creator = i.GenerateTestValidatorAddress("Creator")
28+
29+
err := s.MintBaseCoins(creator.Address, 1_000_000)
30+
Expect(err).To(BeNil())
31+
32+
mailboxId, err = createDummyMailbox(s, creator.Address)
33+
Expect(err).To(BeNil())
34+
35+
hookId, err = createDummyIgp(s, creator.Address, igpDenom)
36+
Expect(err).To(BeNil())
37+
38+
_, err = s.RunTx(&types.MsgSetDestinationGasConfig{
39+
Owner: creator.Address,
40+
IgpId: hookId,
41+
DestinationGasConfig: &types.DestinationGasConfig{
42+
RemoteDomain: 2,
43+
GasOracle: &types.GasOracle{
44+
TokenExchangeRate: math.NewInt(1e10),
45+
GasPrice: math.NewInt(1e9),
46+
},
47+
GasOverhead: math.NewInt(100000),
48+
},
49+
})
50+
Expect(err).To(BeNil())
51+
})
52+
53+
It("IGP PayForGas should not fail on free IGP", func() {
54+
// Set gas config to be gas-free
55+
_, err := s.RunTx(&types.MsgSetDestinationGasConfig{
56+
Owner: creator.Address,
57+
IgpId: hookId,
58+
DestinationGasConfig: &types.DestinationGasConfig{
59+
RemoteDomain: 2,
60+
GasOracle: &types.GasOracle{
61+
TokenExchangeRate: math.NewInt(1e10),
62+
GasPrice: math.ZeroInt(), // NO GAS PAYMENT NEEDED
63+
},
64+
GasOverhead: math.NewInt(100000),
65+
},
66+
})
67+
Expect(err).To(BeNil())
68+
69+
recipient, err := util.DecodeHexAddress("0x00000000000000000000000000000000000000000000000000000000deadbeef")
70+
Expect(err).To(BeNil())
71+
72+
sender, err := util.DecodeHexAddress("0x0000000000000000000000007fa9385be102ac3eac297483dd6233d62b3e1496")
73+
Expect(err).To(BeNil())
74+
75+
message := util.HyperlaneMessage{
76+
Version: 1,
77+
Nonce: 0,
78+
Origin: 1,
79+
Sender: sender,
80+
Destination: 2,
81+
Recipient: recipient,
82+
Body: []byte("test"),
83+
}
84+
85+
metadata := util.StandardHookMetadata{
86+
Address: creator.AccAddress,
87+
GasLimit: math.NewInt(100000),
88+
CustomHookMetadata: nil,
89+
}
90+
91+
// Try PostDispatch with different maxFee denom
92+
93+
// igpDenom != actualDenom
94+
maxFee := sdk.NewCoins(sdk.NewCoin(igpDenom, math.NewInt(50)))
95+
_, err = s.App().HyperlaneKeeper.PostDispatch(s.Ctx(), mailboxId, hookId, metadata, message, maxFee)
96+
Expect(err).To(BeNil())
97+
98+
// igpDenom == actualDenom
99+
maxFee = sdk.NewCoins(sdk.NewCoin(actualDenom, math.NewInt(50)))
100+
_, err = s.App().HyperlaneKeeper.PostDispatch(s.Ctx(), mailboxId, hookId, metadata, message, maxFee)
101+
Expect(err).To(BeNil())
102+
})
103+
})
104+
105+
func createDummyIgp(s *i.KeeperTestSuite, creator string, denom string) (util.HexAddress, error) {
106+
res, err := s.RunTx(&types.MsgCreateIgp{
107+
Owner: creator,
108+
Denom: denom,
109+
})
110+
if err != nil {
111+
return [32]byte{}, err
112+
}
113+
114+
var response types.MsgCreateIgpResponse
115+
err = proto.Unmarshal(res.MsgResponses[0].Value, &response)
116+
if err != nil {
117+
return [32]byte{}, err
118+
}
119+
120+
return response.Id, nil
121+
}

x/core/02_post_dispatch/keeper/msg_igp.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ func (ms msgServer) SetIgpOwner(ctx context.Context, req *types.MsgSetIgpOwner)
8989

9090
// PayForGas executes an InterchainGasPayment without for the specified payment amount.
9191
func (ms msgServer) PayForGas(ctx context.Context, req *types.MsgPayForGas) (*types.MsgPayForGasResponse, error) {
92+
if req.Amount.IsZero() {
93+
return nil, fmt.Errorf("amount must be greater than zero")
94+
}
95+
9296
handler := InterchainGasPaymasterHookHandler{*ms.k}
9397

9498
return &types.MsgPayForGasResponse{}, handler.PayForGasWithoutQuote(ctx, req.IgpId, req.Sender, req.MessageId, req.DestinationDomain, req.GasLimit, sdk.NewCoins(req.Amount))

0 commit comments

Comments
 (0)