diff --git a/action/grantreward.go b/action/grantreward.go index 8f98f15f2c..b0a9065458 100644 --- a/action/grantreward.go +++ b/action/grantreward.go @@ -7,20 +7,61 @@ package action import ( "math/big" + "strings" "google.golang.org/protobuf/proto" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/core/types" "github.com/iotexproject/iotex-core/pkg/util/byteutil" "github.com/iotexproject/iotex-proto/golang/iotextypes" ) +var ( + _grantRewardMethod abi.Method + _ EthCompatibleAction = (*GrantReward)(nil) +) + const ( // BlockReward indicates that the action is to grant block reward BlockReward = iota // EpochReward indicates that the action is to grant epoch reward EpochReward + + _grantrewardInterfaceABI = `[ + { + "inputs": [ + { + "internalType": "int8", + "name": "rewardType", + "type": "int8" + }, + { + "internalType": "uint64", + "name": "height", + "type": "uint64" + } + ], + "name": "grantReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ]` ) +func init() { + grantRewardInterface, err := abi.JSON(strings.NewReader(_grantrewardInterfaceABI)) + if err != nil { + panic(err) + } + var ok bool + _grantRewardMethod, ok = grantRewardInterface.Methods["grantReward"] + if !ok { + panic("fail to load the method") + } +} + // GrantReward is the action to grant either block or epoch reward type GrantReward struct { AbstractAction @@ -78,6 +119,38 @@ func (*GrantReward) Cost() (*big.Int, error) { return big.NewInt(0), nil } +// EncodeABIBinary encodes data in abi encoding +func (g *GrantReward) EncodeABIBinary() ([]byte, error) { + return g.encodeABIBinary() +} + +func (g *GrantReward) encodeABIBinary() ([]byte, error) { + data, err := _grantRewardMethod.Inputs.Pack( + int8(g.rewardType), + g.height, + ) + if err != nil { + return nil, err + } + return append(_grantRewardMethod.ID, data...), nil +} + +// ToEthTx converts a grant reward action to an ethereum transaction +func (g *GrantReward) ToEthTx(_ uint32) (*types.Transaction, error) { + data, err := g.encodeABIBinary() + if err != nil { + return nil, err + } + return types.NewTx(&types.LegacyTx{ + Nonce: g.Nonce(), + GasPrice: g.GasPrice(), + Gas: g.GasLimit(), + To: &_rewardingProtocolEthAddr, + Data: data, + Value: big.NewInt(0), + }), nil +} + // GrantRewardBuilder is the struct to build GrantReward type GrantRewardBuilder struct { Builder diff --git a/action/grantreward_test.go b/action/grantreward_test.go new file mode 100644 index 0000000000..f6b162744a --- /dev/null +++ b/action/grantreward_test.go @@ -0,0 +1,44 @@ +package action + +import ( + "math/big" + "testing" + + "github.com/iotexproject/iotex-core/pkg/util/byteutil" + "github.com/stretchr/testify/require" +) + +func TestGrandReward(t *testing.T) { + require := require.New(t) + tests := []struct { + rewardType int + height uint64 + }{ + {BlockReward, 100}, + {EpochReward, 200}, + } + for _, test := range tests { + g := &GrantReward{ + rewardType: test.rewardType, + height: test.height, + } + require.Equal(test.rewardType, g.RewardType()) + require.Equal(test.height, g.Height()) + require.NoError(g.SanityCheck()) + require.NoError(g.LoadProto(g.Proto())) + intrinsicGas, err := g.IntrinsicGas() + require.NoError(err) + require.Equal(uint64(0), intrinsicGas) + cost, err := g.Cost() + require.NoError(err) + require.Equal(big.NewInt(0), cost) + ethTx, err := g.ToEthTx(0) + require.NoError(err) + require.NotNil(ethTx) + require.Equal(byteutil.Must(g.EncodeABIBinary()), ethTx.Data()) + require.Equal(big.NewInt(0), ethTx.GasPrice()) + require.Equal(uint64(0), ethTx.Gas()) + require.Equal(big.NewInt(0), ethTx.Value()) + require.Equal(_rewardingProtocolEthAddr.Hex(), ethTx.To().Hex()) + } +} diff --git a/api/web3server_integrity_test.go b/api/web3server_integrity_test.go index 9e5c0579fb..347a5d9679 100644 --- a/api/web3server_integrity_test.go +++ b/api/web3server_integrity_test.go @@ -214,7 +214,7 @@ func getBlockByNumber(t *testing.T, handler *hTTPHandler) { params string expected int }{ - {`["1", true]`, 1}, + {`["1", true]`, 2}, {`["1", false]`, 2}, {`["10", false]`, 0}, } {