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  }