github.com/iotexproject/iotex-core@v1.14.1-rc1/action/candidate_activate.go (about) 1 package action 2 3 import ( 4 "bytes" 5 "math/big" 6 "strings" 7 8 "github.com/ethereum/go-ethereum/accounts/abi" 9 "github.com/ethereum/go-ethereum/core/types" 10 "github.com/iotexproject/iotex-proto/golang/iotextypes" 11 "github.com/pkg/errors" 12 13 "github.com/iotexproject/iotex-core/pkg/version" 14 ) 15 16 const ( 17 // CandidateActivateBaseIntrinsicGas represents the base intrinsic gas for CandidateActivate 18 CandidateActivateBaseIntrinsicGas = uint64(10000) 19 20 // TODO: move all parts of staking abi to a unified file 21 candidateActivateInterfaceABI = `[ 22 { 23 "inputs": [ 24 { 25 "internalType": "uint64", 26 "name": "bucketIndex", 27 "type": "uint64" 28 } 29 ], 30 "name": "candidateActivate", 31 "outputs": [], 32 "stateMutability": "nonpayable", 33 "type": "function" 34 } 35 ]` 36 ) 37 38 var ( 39 candidateActivateMethod abi.Method 40 ) 41 42 // CandidateActivate is the action to update a candidate's bucket 43 type CandidateActivate struct { 44 AbstractAction 45 46 // bucketID is the bucket index want to be changed to 47 bucketID uint64 48 } 49 50 func init() { 51 candidateActivateInterface, err := abi.JSON(strings.NewReader(candidateActivateInterfaceABI)) 52 if err != nil { 53 panic(err) 54 } 55 var ok bool 56 candidateActivateMethod, ok = candidateActivateInterface.Methods["candidateActivate"] 57 if !ok { 58 panic("fail to load the candidateActivate method") 59 } 60 } 61 62 // BucketID returns the bucket index want to be changed to 63 func (cr *CandidateActivate) BucketID() uint64 { return cr.bucketID } 64 65 // IntrinsicGas returns the intrinsic gas of a CandidateRegister 66 func (cr *CandidateActivate) IntrinsicGas() (uint64, error) { 67 return CandidateActivateBaseIntrinsicGas, nil 68 } 69 70 // Cost returns the total cost of a CandidateRegister 71 func (cr *CandidateActivate) Cost() (*big.Int, error) { 72 intrinsicGas, err := cr.IntrinsicGas() 73 if err != nil { 74 return nil, errors.Wrap(err, "failed to get intrinsic gas for the CandidateRegister creates") 75 } 76 fee := big.NewInt(0).Mul(cr.GasPrice(), big.NewInt(0).SetUint64(intrinsicGas)) 77 return fee, nil 78 } 79 80 // Proto converts CandidateActivate to protobuf's Action 81 func (cr *CandidateActivate) Proto() *iotextypes.CandidateActivate { 82 return &iotextypes.CandidateActivate{ 83 BucketIndex: cr.bucketID, 84 } 85 } 86 87 // LoadProto converts a protobuf's Action to CandidateActivate 88 func (cr *CandidateActivate) LoadProto(pbAct *iotextypes.CandidateActivate) error { 89 if pbAct == nil { 90 return ErrNilProto 91 } 92 cr.bucketID = pbAct.GetBucketIndex() 93 return nil 94 } 95 96 func (cr *CandidateActivate) encodeABIBinary() ([]byte, error) { 97 data, err := candidateActivateMethod.Inputs.Pack(cr.bucketID) 98 if err != nil { 99 return nil, err 100 } 101 return append(candidateActivateMethod.ID, data...), nil 102 } 103 104 // ToEthTx returns an Ethereum transaction which corresponds to this action 105 func (cr *CandidateActivate) ToEthTx(_ uint32) (*types.Transaction, error) { 106 data, err := cr.encodeABIBinary() 107 if err != nil { 108 return nil, err 109 } 110 return types.NewTx(&types.LegacyTx{ 111 Nonce: cr.Nonce(), 112 GasPrice: cr.GasPrice(), 113 Gas: cr.GasLimit(), 114 To: &_stakingProtocolEthAddr, 115 Value: big.NewInt(0), 116 Data: data, 117 }), nil 118 } 119 120 // NewCandidateActivate returns a CandidateActivate action 121 func NewCandidateActivate(nonce, gasLimit uint64, gasPrice *big.Int, bucketID uint64) *CandidateActivate { 122 return &CandidateActivate{ 123 AbstractAction: AbstractAction{ 124 version: version.ProtocolVersion, 125 nonce: nonce, 126 gasLimit: gasLimit, 127 gasPrice: gasPrice, 128 }, 129 bucketID: bucketID, 130 } 131 } 132 133 // NewCandidateActivateFromABIBinary parses the smart contract input and creates an action 134 func NewCandidateActivateFromABIBinary(data []byte) (*CandidateActivate, error) { 135 var ( 136 paramsMap = map[string]any{} 137 cr CandidateActivate 138 ) 139 // sanity check 140 if len(data) <= 4 || !bytes.Equal(candidateActivateMethod.ID, data[:4]) { 141 return nil, errDecodeFailure 142 } 143 if err := candidateActivateMethod.Inputs.UnpackIntoMap(paramsMap, data[4:]); err != nil { 144 return nil, err 145 } 146 bucketID, ok := paramsMap["bucketIndex"].(uint64) 147 if !ok { 148 return nil, errDecodeFailure 149 } 150 cr.bucketID = bucketID 151 return &cr, nil 152 }