diff --git a/x/crosschain/keeper/bridge_call_out.go b/x/crosschain/keeper/bridge_call_out.go index 7143dc0e..e7cac714 100644 --- a/x/crosschain/keeper/bridge_call_out.go +++ b/x/crosschain/keeper/bridge_call_out.go @@ -7,6 +7,8 @@ import ( "strconv" "time" + "cosmossdk.io/collections" + "cosmossdk.io/errors" sdkmath "cosmossdk.io/math" storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/telemetry" @@ -19,6 +21,7 @@ import ( "github.com/hashicorp/go-metrics" fxtelemetry "github.com/functionx/fx-core/v8/telemetry" + fxtypes "github.com/functionx/fx-core/v8/types" "github.com/functionx/fx-core/v8/x/crosschain/types" ) @@ -138,8 +141,22 @@ func (k Keeper) RefundOutgoingBridgeCall(ctx sdk.Context, data *types.OutgoingBr sdk.NewAttribute(types.AttributeKeyRefund, refund.String()), )) + originAmount, err := k.erc20Keeper.GetCache(ctx, types.NewOriginTokenKey(k.moduleName, data.Nonce)) + if err != nil && !errors.IsOf(err, collections.ErrNotFound) { + return err + } + if errors.IsOf(err, collections.ErrNotFound) { + originAmount = sdkmath.ZeroInt() + } + + originCoin := sdk.NewCoin(fxtypes.DefaultDenom, originAmount) + if !baseCoins.IsAllGTE(sdk.NewCoins(originCoin)) { + return types.ErrInvalid.Wrapf("bridge call coin less than origin amount") + } + baseCoins = baseCoins.Sub(originCoin) + for _, coin := range baseCoins { - _, err := k.erc20Keeper.BaseCoinToEvm(ctx, common.BytesToAddress(refund.Bytes()), coin) + _, err = k.erc20Keeper.BaseCoinToEvm(ctx, common.BytesToAddress(refund.Bytes()), coin) if err != nil { return err } diff --git a/x/crosschain/keeper/many_to_one.go b/x/crosschain/keeper/many_to_one.go index abc56f10..ba13553c 100644 --- a/x/crosschain/keeper/many_to_one.go +++ b/x/crosschain/keeper/many_to_one.go @@ -148,14 +148,11 @@ func (k Keeper) IBCCoinRefund(ctx sdk.Context, holder sdk.AccAddress, ibcCoin sd if err != nil { return err } - if !found { - return nil + if found { + return k.erc20Keeper.DeleteCache(ctx, ibcTransferKey) } _, err = k.erc20Keeper.BaseCoinToEvm(ctx, common.BytesToAddress(holder.Bytes()), sdk.NewCoin(baseDenom, ibcCoin.Amount)) - if err != nil { - return err - } - return k.erc20Keeper.DeleteCache(ctx, ibcTransferKey) + return err } func (k Keeper) AfterIBCAckSuccess(ctx sdk.Context, ibcChannel string, ibcSequence uint64) error { diff --git a/x/crosschain/mock/expected_keepers_mocks.go b/x/crosschain/mock/expected_keepers_mocks.go index 2019ebbf..3cb7f25f 100644 --- a/x/crosschain/mock/expected_keepers_mocks.go +++ b/x/crosschain/mock/expected_keepers_mocks.go @@ -418,6 +418,21 @@ func (mr *MockErc20KeeperMockRecorder) GetBridgeTokens(ctx, chainName any) *gomo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBridgeTokens", reflect.TypeOf((*MockErc20Keeper)(nil).GetBridgeTokens), ctx, chainName) } +// GetCache mocks base method. +func (m *MockErc20Keeper) GetCache(ctx context.Context, key string) (math.Int, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCache", ctx, key) + ret0, _ := ret[0].(math.Int) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCache indicates an expected call of GetCache. +func (mr *MockErc20KeeperMockRecorder) GetCache(ctx, key any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCache", reflect.TypeOf((*MockErc20Keeper)(nil).GetCache), ctx, key) +} + // GetERC20Token mocks base method. func (m *MockErc20Keeper) GetERC20Token(ctx context.Context, baseDenom string) (types4.ERC20Token, error) { m.ctrl.T.Helper() diff --git a/x/crosschain/types/expected_keepers.go b/x/crosschain/types/expected_keepers.go index 6520db1e..abe9d2ff 100644 --- a/x/crosschain/types/expected_keepers.go +++ b/x/crosschain/types/expected_keepers.go @@ -49,6 +49,7 @@ type Erc20Keeper interface { HasCache(ctx context.Context, key string) (bool, error) SetCache(ctx context.Context, key string, amount sdkmath.Int) error DeleteCache(ctx context.Context, key string) error + GetCache(ctx context.Context, key string) (sdkmath.Int, error) HasToken(ctx context.Context, token string) (bool, error) GetBaseDenom(ctx context.Context, token string) (string, error) diff --git a/x/erc20/keeper/cache.go b/x/erc20/keeper/cache.go index 2e7d0a3b..3f077004 100644 --- a/x/erc20/keeper/cache.go +++ b/x/erc20/keeper/cache.go @@ -17,3 +17,7 @@ func (k Keeper) SetCache(ctx context.Context, key string, amount sdkmath.Int) er func (k Keeper) DeleteCache(ctx context.Context, key string) error { return k.Cache.Remove(ctx, key) } + +func (k Keeper) GetCache(ctx context.Context, key string) (sdkmath.Int, error) { + return k.Cache.Get(ctx, key) +} diff --git a/x/ibc/middleware/keeper/relay_test.go b/x/ibc/middleware/keeper/relay_test.go index 48b3add6..1506bb12 100644 --- a/x/ibc/middleware/keeper/relay_test.go +++ b/x/ibc/middleware/keeper/relay_test.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/functionx/fx-core/v8/testutil/helpers" + crosschaintypes "github.com/functionx/fx-core/v8/x/crosschain/types" ) func (suite *KeeperTestSuite) TestOnRecvPacket() { @@ -80,6 +81,7 @@ func (suite *KeeperTestSuite) TestOnAcknowledgementPacket() { escrowAddress := transfertypes.GetEscrowAddress(packet.SourcePort, packet.SourceChannel) suite.mintCoin(escrowAddress, coin) + suite.Require().NoError(suite.App.Erc20Keeper.SetCache(suite.Ctx, crosschaintypes.NewIBCTransferKey(packet.SourceChannel, 1), coin.Amount)) }, true, "",