github.com/iotexproject/iotex-core@v1.14.1-rc1/action/claimreward.go (about) 1 // Copyright (c) 2019 IoTeX Foundation 2 // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability 3 // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. 4 // This source code is governed by Apache License 2.0 that can be found in the LICENSE file. 5 6 package action 7 8 import ( 9 "bytes" 10 "math/big" 11 "strings" 12 13 "github.com/ethereum/go-ethereum/accounts/abi" 14 "github.com/ethereum/go-ethereum/core/types" 15 "github.com/pkg/errors" 16 "google.golang.org/protobuf/proto" 17 18 "github.com/iotexproject/iotex-core/pkg/util/byteutil" 19 "github.com/iotexproject/iotex-proto/golang/iotextypes" 20 ) 21 22 const _claimRewardingInterfaceABI = `[ 23 { 24 "inputs": [ 25 { 26 "internalType": "uint256", 27 "name": "amount", 28 "type": "uint256" 29 }, 30 { 31 "internalType": "uint8[]", 32 "name": "data", 33 "type": "uint8[]" 34 } 35 ], 36 "name": "claim", 37 "outputs": [], 38 "stateMutability": "nonpayable", 39 "type": "function" 40 } 41 ]` 42 43 var ( 44 // ClaimFromRewardingFundBaseGas represents the base intrinsic gas for claimFromRewardingFund 45 ClaimFromRewardingFundBaseGas = uint64(10000) 46 // ClaimFromRewardingFundGasPerByte represents the claimFromRewardingFund payload gas per uint 47 ClaimFromRewardingFundGasPerByte = uint64(100) 48 49 _claimRewardingMethod abi.Method 50 _ EthCompatibleAction = (*ClaimFromRewardingFund)(nil) 51 ) 52 53 func init() { 54 claimRewardInterface, err := abi.JSON(strings.NewReader(_claimRewardingInterfaceABI)) 55 if err != nil { 56 panic(err) 57 } 58 var ok bool 59 _claimRewardingMethod, ok = claimRewardInterface.Methods["claim"] 60 if !ok { 61 panic("fail to load the claim method") 62 } 63 } 64 65 // ClaimFromRewardingFund is the action to claim reward from the rewarding fund 66 type ClaimFromRewardingFund struct { 67 AbstractAction 68 69 amount *big.Int 70 data []byte 71 } 72 73 // Amount returns the amount to claim 74 func (c *ClaimFromRewardingFund) Amount() *big.Int { return c.amount } 75 76 // Data returns the additional data 77 func (c *ClaimFromRewardingFund) Data() []byte { return c.data } 78 79 // Serialize returns a raw byte stream of a claim action 80 func (c *ClaimFromRewardingFund) Serialize() []byte { 81 return byteutil.Must(proto.Marshal(c.Proto())) 82 } 83 84 // Proto converts a claim action struct to a claim action protobuf 85 func (c *ClaimFromRewardingFund) Proto() *iotextypes.ClaimFromRewardingFund { 86 return &iotextypes.ClaimFromRewardingFund{ 87 Amount: c.amount.String(), 88 Data: c.data, 89 } 90 } 91 92 // LoadProto converts a claim action protobuf to a claim action struct 93 func (c *ClaimFromRewardingFund) LoadProto(claim *iotextypes.ClaimFromRewardingFund) error { 94 *c = ClaimFromRewardingFund{} 95 amount, ok := new(big.Int).SetString(claim.Amount, 10) 96 if !ok { 97 return errors.New("failed to set claim amount") 98 } 99 c.amount = amount 100 c.data = claim.Data 101 return nil 102 } 103 104 // IntrinsicGas returns the intrinsic gas of a claim action 105 func (c *ClaimFromRewardingFund) IntrinsicGas() (uint64, error) { 106 dataLen := uint64(len(c.Data())) 107 return CalculateIntrinsicGas(ClaimFromRewardingFundBaseGas, ClaimFromRewardingFundGasPerByte, dataLen) 108 } 109 110 // Cost returns the total cost of a claim action 111 func (c *ClaimFromRewardingFund) Cost() (*big.Int, error) { 112 intrinsicGas, err := c.IntrinsicGas() 113 if err != nil { 114 return nil, errors.Wrap(err, "error when getting intrinsic gas for the claim action") 115 } 116 return big.NewInt(0).Mul(c.GasPrice(), big.NewInt(0).SetUint64(intrinsicGas)), nil 117 } 118 119 // SanityCheck validates the variables in the action 120 func (c *ClaimFromRewardingFund) SanityCheck() error { 121 if c.Amount().Sign() < 0 { 122 return ErrNegativeValue 123 } 124 125 return c.AbstractAction.SanityCheck() 126 } 127 128 // ClaimFromRewardingFundBuilder is the struct to build ClaimFromRewardingFund 129 type ClaimFromRewardingFundBuilder struct { 130 Builder 131 claim ClaimFromRewardingFund 132 } 133 134 // SetAmount sets the amount to claim 135 func (b *ClaimFromRewardingFundBuilder) SetAmount(amount *big.Int) *ClaimFromRewardingFundBuilder { 136 b.claim.amount = amount 137 return b 138 } 139 140 // SetData sets the additional data 141 func (b *ClaimFromRewardingFundBuilder) SetData(data []byte) *ClaimFromRewardingFundBuilder { 142 b.claim.data = data 143 return b 144 } 145 146 // Build builds a new claim from rewarding fund action 147 func (b *ClaimFromRewardingFundBuilder) Build() ClaimFromRewardingFund { 148 b.claim.AbstractAction = b.Builder.Build() 149 return b.claim 150 } 151 152 // encodeABIBinary encodes data in abi encoding 153 func (c *ClaimFromRewardingFund) encodeABIBinary() ([]byte, error) { 154 data, err := _claimRewardingMethod.Inputs.Pack(c.Amount(), c.Data()) 155 if err != nil { 156 return nil, err 157 } 158 return append(_claimRewardingMethod.ID, data...), nil 159 } 160 161 // ToEthTx converts action to eth-compatible tx 162 func (c *ClaimFromRewardingFund) ToEthTx(_ uint32) (*types.Transaction, error) { 163 data, err := c.encodeABIBinary() 164 if err != nil { 165 return nil, err 166 } 167 return types.NewTx(&types.LegacyTx{ 168 Nonce: c.Nonce(), 169 GasPrice: c.GasPrice(), 170 Gas: c.GasLimit(), 171 To: &_rewardingProtocolEthAddr, 172 Value: big.NewInt(0), 173 Data: data, 174 }), nil 175 } 176 177 // NewClaimFromRewardingFundFromABIBinary decodes data into action 178 func NewClaimFromRewardingFundFromABIBinary(data []byte) (*ClaimFromRewardingFund, error) { 179 var ( 180 paramsMap = map[string]interface{}{} 181 ok bool 182 ac ClaimFromRewardingFund 183 ) 184 // sanity check 185 if len(data) <= 4 || !bytes.Equal(_claimRewardingMethod.ID[:], data[:4]) { 186 return nil, errDecodeFailure 187 } 188 if err := _claimRewardingMethod.Inputs.UnpackIntoMap(paramsMap, data[4:]); err != nil { 189 return nil, err 190 } 191 if ac.amount, ok = paramsMap["amount"].(*big.Int); !ok { 192 return nil, errDecodeFailure 193 } 194 if ac.data, ok = paramsMap["data"].([]byte); !ok { 195 return nil, errDecodeFailure 196 } 197 return &ac, nil 198 }