diff --git a/contracts/erc20.go b/contracts/erc20.go index 66ad0037..a0b667ab 100644 --- a/contracts/erc20.go +++ b/contracts/erc20.go @@ -7,6 +7,10 @@ import ( "github.com/irisnet/irismod/types" ) +const ( + EventSwapToNative = "SwapToNative" +) + var ( //go:embed compiled_contracts/Token.json ERC20JSON []byte //nolint: golint diff --git a/contracts/erc20_test.go b/contracts/erc20_test.go new file mode 100644 index 00000000..dc222137 --- /dev/null +++ b/contracts/erc20_test.go @@ -0,0 +1,14 @@ +package contracts_test + +import ( + "testing" + + "github.com/irisnet/irismod/contracts" +) + + +func TestERC20(t *testing.T) { + for k,v := range contracts.ERC20TokenContract.ABI.Events { + t.Logf("event:%s ,id: %s", k,v.ID) + } +} \ No newline at end of file diff --git a/modules/token/keeper/evm_hook.go b/modules/token/keeper/evm_hook.go index a2674c28..716e20c2 100644 --- a/modules/token/keeper/evm_hook.go +++ b/modules/token/keeper/evm_hook.go @@ -1,14 +1,83 @@ package keeper import ( + "math/big" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/core" ethtypes "github.com/ethereum/go-ethereum/core/types" + + "github.com/irisnet/irismod/contracts" ) -// PostTxProcessing processes the transaction in the given context with the message and receipt. -// Parameters: ctx sdk.Context, msg core.Message, receipt *ethtypes.Receipt -// Returns: error -func(k Keeper) PostTxProcessing(ctx sdk.Context, msg core.Message, receipt *ethtypes.Receipt) error { +// PostTxProcessing processes the transaction receipt for ERC20 token swap to native. +// +// Parameters: +// ctx: the context in which the function is executed. +// msg: the core message associated with the transaction. +// receipt: the Ethereum receipt containing the transaction logs. +// Return type: error +func (k Keeper) PostTxProcessing(ctx sdk.Context, msg core.Message, receipt *ethtypes.Receipt) error { + erc20 := contracts.ERC20TokenContract.ABI + for _, log := range receipt.Logs { + // Note: the `SwapToNative` event contains 1 topics + if len(log.Topics) != 1 { + continue + } + + // Check if event is included in ERC20 + eventID := log.Topics[0] + event, err := erc20.EventByID(eventID) + if err != nil { + continue + } + + // Check if event is a `SwapToNative` event. + if event.Name != contracts.EventSwapToNative { + k.Logger(ctx).Info("emitted event", "name", event.Name, "signature", event.Sig) + continue + } + + eventArgs, err := erc20.Unpack(event.Name, log.Data) + if err != nil { + k.Logger(ctx).Error("failed to unpack SwapToNative event", "error", err.Error()) + continue + } + + if len(eventArgs) != 3 { + k.Logger(ctx).Error("invalid SwapToNative event args") + continue + } + + sender := sdk.AccAddress(msg.From().Bytes()) + to, ok := eventArgs[0].(string) + if !ok || len(to) == 0 { + k.Logger(ctx).Error("invalid SwapToNative event args `to`") + continue + } + toAddr, err := sdk.AccAddressFromBech32(to) + if err != nil { + k.Logger(ctx).Error("invalid SwapToNative event args `to`", "error", err.Error()) + continue + } + + amount, ok := eventArgs[1].(*big.Int) + if !ok || amount.Cmp(big.NewInt(0)) == 0 { + k.Logger(ctx).Error("invalid SwapToNative event args `amount`") + continue + } + + isERIS, ok := eventArgs[2].(bool) + if !ok { + k.Logger(ctx).Error("invalid SwapToNative event args `isERIS`") + continue + } + + paid := sdk.NewCoin(k.evmKeeper.FeeDenom(), sdk.NewIntFromBigInt(amount)) + if isERIS { + _, _, err := k.SwapFeeToken(ctx, paid, sender, toAddr) + return err + } + } return nil -} \ No newline at end of file +} diff --git a/modules/token/types/expected_keepers.go b/modules/token/types/expected_keepers.go index f0b37a9d..92ac5c41 100644 --- a/modules/token/types/expected_keepers.go +++ b/modules/token/types/expected_keepers.go @@ -55,6 +55,7 @@ type AccountKeeper interface { } type EVMKeeper interface { + FeeDenom() string ChainID() *big.Int EstimateGas(ctx context.Context, req *types.EthCallRequest) (uint64, error) ApplyMessage(ctx sdk.Context, msg core.Message, tracer vm.EVMLogger, commit bool) (*types.Result, error)