github.com/iotexproject/iotex-core@v1.14.1-rc1/action/depositreward.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 _depositRewardInterfaceABI = `[ 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": "deposit", 37 "outputs": [], 38 "stateMutability": "payable", 39 "type": "function" 40 } 41 ]` 42 43 var ( 44 // DepositToRewardingFundBaseGas represents the base intrinsic gas for depositToRewardingFund 45 DepositToRewardingFundBaseGas = uint64(10000) 46 // DepositToRewardingFundGasPerByte represents the depositToRewardingFund payload gas per uint 47 DepositToRewardingFundGasPerByte = uint64(100) 48 49 _depositRewardMethod abi.Method 50 _ EthCompatibleAction = (*DepositToRewardingFund)(nil) 51 ) 52 53 func init() { 54 depositRewardInterface, err := abi.JSON(strings.NewReader(_depositRewardInterfaceABI)) 55 if err != nil { 56 panic(err) 57 } 58 var ok bool 59 _depositRewardMethod, ok = depositRewardInterface.Methods["deposit"] 60 if !ok { 61 panic("fail to load the deposit method") 62 } 63 } 64 65 // DepositToRewardingFund is the action to deposit to the rewarding fund 66 type DepositToRewardingFund struct { 67 AbstractAction 68 69 amount *big.Int 70 data []byte 71 } 72 73 // Amount returns the amount to deposit 74 func (d *DepositToRewardingFund) Amount() *big.Int { return d.amount } 75 76 // Data returns the additional data 77 func (d *DepositToRewardingFund) Data() []byte { return d.data } 78 79 // Serialize returns a raw byte stream of a deposit action 80 func (d *DepositToRewardingFund) Serialize() []byte { 81 return byteutil.Must(proto.Marshal(d.Proto())) 82 } 83 84 // Proto converts a deposit action struct to a deposit action protobuf 85 func (d *DepositToRewardingFund) Proto() *iotextypes.DepositToRewardingFund { 86 return &iotextypes.DepositToRewardingFund{ 87 Amount: d.amount.String(), 88 Data: d.data, 89 } 90 } 91 92 // LoadProto converts a deposit action protobuf to a deposit action struct 93 func (d *DepositToRewardingFund) LoadProto(deposit *iotextypes.DepositToRewardingFund) error { 94 *d = DepositToRewardingFund{} 95 amount, ok := new(big.Int).SetString(deposit.Amount, 10) 96 if !ok { 97 return errors.New("failed to set deposit amount") 98 } 99 d.amount = amount 100 d.data = deposit.Data 101 return nil 102 } 103 104 // IntrinsicGas returns the intrinsic gas of a deposit action 105 func (d *DepositToRewardingFund) IntrinsicGas() (uint64, error) { 106 dataLen := uint64(len(d.Data())) 107 return CalculateIntrinsicGas(DepositToRewardingFundBaseGas, DepositToRewardingFundGasPerByte, dataLen) 108 } 109 110 // Cost returns the total cost of a deposit action 111 func (d *DepositToRewardingFund) Cost() (*big.Int, error) { 112 intrinsicGas, err := d.IntrinsicGas() 113 if err != nil { 114 return nil, errors.Wrap(err, "error when getting intrinsic gas for the deposit action") 115 } 116 return big.NewInt(0).Mul(d.GasPrice(), big.NewInt(0).SetUint64(intrinsicGas)), nil 117 } 118 119 // SanityCheck validates the variables in the action 120 func (d *DepositToRewardingFund) SanityCheck() error { 121 if d.Amount().Sign() < 0 { 122 return ErrNegativeValue 123 } 124 125 return d.AbstractAction.SanityCheck() 126 } 127 128 // DepositToRewardingFundBuilder is the struct to build DepositToRewardingFund 129 type DepositToRewardingFundBuilder struct { 130 Builder 131 deposit DepositToRewardingFund 132 } 133 134 // SetAmount sets the amount to deposit 135 func (b *DepositToRewardingFundBuilder) SetAmount(amount *big.Int) *DepositToRewardingFundBuilder { 136 b.deposit.amount = amount 137 return b 138 } 139 140 // SetData sets the additional data 141 func (b *DepositToRewardingFundBuilder) SetData(data []byte) *DepositToRewardingFundBuilder { 142 b.deposit.data = data 143 return b 144 } 145 146 // Build builds a new deposit to rewarding fund action 147 func (b *DepositToRewardingFundBuilder) Build() DepositToRewardingFund { 148 b.deposit.AbstractAction = b.Builder.Build() 149 return b.deposit 150 } 151 152 // encodeABIBinary encodes data in abi encoding 153 func (d *DepositToRewardingFund) encodeABIBinary() ([]byte, error) { 154 data, err := _depositRewardMethod.Inputs.Pack(d.Amount(), d.Data()) 155 if err != nil { 156 return nil, err 157 } 158 return append(_depositRewardMethod.ID, data...), nil 159 } 160 161 // ToEthTx converts action to eth-compatible tx 162 func (d *DepositToRewardingFund) ToEthTx(_ uint32) (*types.Transaction, error) { 163 data, err := d.encodeABIBinary() 164 if err != nil { 165 return nil, err 166 } 167 return types.NewTx(&types.LegacyTx{ 168 Nonce: d.Nonce(), 169 GasPrice: d.GasPrice(), 170 Gas: d.GasLimit(), 171 To: &_rewardingProtocolEthAddr, 172 Value: big.NewInt(0), 173 Data: data, 174 }), nil 175 } 176 177 // NewDepositToRewardingFundFromABIBinary decodes data into action 178 func NewDepositToRewardingFundFromABIBinary(data []byte) (*DepositToRewardingFund, error) { 179 var ( 180 paramsMap = map[string]interface{}{} 181 ok bool 182 ac DepositToRewardingFund 183 ) 184 // sanity check 185 if len(data) <= 4 || !bytes.Equal(_depositRewardMethod.ID[:], data[:4]) { 186 return nil, errDecodeFailure 187 } 188 if err := _depositRewardMethod.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 }