github.com/iotexproject/iotex-core@v1.14.1-rc1/action/protocol/staking/ethabi/stake_base.go (about)

     1  package ethabi
     2  
     3  import (
     4  	"encoding/hex"
     5  	"errors"
     6  	"math/big"
     7  
     8  	"github.com/ethereum/go-ethereum/accounts/abi"
     9  	"github.com/ethereum/go-ethereum/common"
    10  	"github.com/iotexproject/iotex-proto/golang/iotextypes"
    11  
    12  	"github.com/iotexproject/iotex-core/action/protocol"
    13  	"github.com/iotexproject/iotex-core/pkg/util/addrutil"
    14  )
    15  
    16  var (
    17  	errInvalidCallData  = errors.New("invalid call binary data")
    18  	errInvalidCallSig   = errors.New("invalid call sig")
    19  	errConvertBigNumber = errors.New("convert big number error")
    20  	errDecodeFailure    = errors.New("decode data error")
    21  )
    22  
    23  type (
    24  	// BucketEth struct for eth
    25  	BucketEth struct {
    26  		Index                     uint64
    27  		CandidateAddress          common.Address
    28  		StakedAmount              *big.Int
    29  		StakedDuration            uint32
    30  		CreateTime                int64
    31  		StakeStartTime            int64
    32  		UnstakeStartTime          int64
    33  		AutoStake                 bool
    34  		Owner                     common.Address
    35  		ContractAddress           common.Address
    36  		StakedDurationBlockNumber uint64
    37  		CreateBlockHeight         uint64
    38  		StakeStartBlockHeight     uint64
    39  		UnstakeStartBlockHeight   uint64
    40  	}
    41  
    42  	// BucketTypeEth struct for eth
    43  	BucketTypeEth struct {
    44  		StakedAmount   *big.Int
    45  		StakedDuration uint32
    46  	}
    47  
    48  	// CandidateEth struct for eth
    49  	CandidateEth struct {
    50  		OwnerAddress       common.Address
    51  		OperatorAddress    common.Address
    52  		RewardAddress      common.Address
    53  		Name               string
    54  		TotalWeightedVotes *big.Int
    55  		SelfStakeBucketIdx uint64
    56  		SelfStakingTokens  *big.Int
    57  	}
    58  )
    59  
    60  func encodeVoteBucketListToEth(outputs abi.Arguments, buckets *iotextypes.VoteBucketList) (string, error) {
    61  	args := make([]BucketEth, len(buckets.Buckets))
    62  	for i, bucket := range buckets.Buckets {
    63  		args[i] = BucketEth{}
    64  		args[i].Index = bucket.Index
    65  		addr, err := addrutil.IoAddrToEvmAddr(bucket.CandidateAddress)
    66  		if err != nil {
    67  			return "", err
    68  		}
    69  		args[i].CandidateAddress = addr
    70  		if amount, ok := new(big.Int).SetString(bucket.StakedAmount, 10); ok {
    71  			args[i].StakedAmount = amount
    72  		} else {
    73  			return "", errConvertBigNumber
    74  		}
    75  
    76  		args[i].AutoStake = bucket.AutoStake
    77  		addr, err = addrutil.IoAddrToEvmAddr(bucket.Owner)
    78  		if err != nil {
    79  			return "", err
    80  		}
    81  		args[i].Owner = addr
    82  
    83  		if bucket.ContractAddress == "" {
    84  			// native bucket contract address is 0x0000000000000000000000000000000000000000
    85  			args[i].ContractAddress = common.Address{}
    86  			args[i].StakedDuration = bucket.StakedDuration
    87  			args[i].CreateTime = bucket.CreateTime.Seconds
    88  			args[i].StakeStartTime = bucket.StakeStartTime.Seconds
    89  			args[i].UnstakeStartTime = bucket.UnstakeStartTime.Seconds
    90  		} else {
    91  			addr, err = addrutil.IoAddrToEvmAddr(bucket.ContractAddress)
    92  			if err != nil {
    93  				return "", err
    94  			}
    95  			args[i].ContractAddress = addr
    96  			args[i].StakedDurationBlockNumber = bucket.StakedDurationBlockNumber
    97  			args[i].CreateBlockHeight = bucket.CreateBlockHeight
    98  			args[i].StakeStartBlockHeight = bucket.StakeStartBlockHeight
    99  			args[i].UnstakeStartBlockHeight = bucket.UnstakeStartBlockHeight
   100  		}
   101  	}
   102  
   103  	data, err := outputs.Pack(args)
   104  	if err != nil {
   105  		return "", nil
   106  	}
   107  	return hex.EncodeToString(data), nil
   108  }
   109  
   110  func encodeCandidateToEth(candidate *iotextypes.CandidateV2) (*CandidateEth, error) {
   111  	result := &CandidateEth{}
   112  	addr, err := addrutil.IoAddrToEvmAddr(candidate.OwnerAddress)
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  	result.OwnerAddress = addr
   117  	addr, err = addrutil.IoAddrToEvmAddr(candidate.OperatorAddress)
   118  	if err != nil {
   119  		return nil, err
   120  	}
   121  	result.OperatorAddress = addr
   122  	addr, err = addrutil.IoAddrToEvmAddr(candidate.RewardAddress)
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  	result.RewardAddress = addr
   127  	result.Name = candidate.Name
   128  	if amount, ok := new(big.Int).SetString(candidate.TotalWeightedVotes, 10); ok {
   129  		result.TotalWeightedVotes = amount
   130  	} else {
   131  		return nil, errConvertBigNumber
   132  	}
   133  	result.SelfStakeBucketIdx = candidate.SelfStakeBucketIdx
   134  	if amount, ok := new(big.Int).SetString(candidate.SelfStakingTokens, 10); ok {
   135  		result.SelfStakingTokens = amount
   136  	} else {
   137  		return nil, errConvertBigNumber
   138  	}
   139  	return result, nil
   140  }
   141  
   142  func encodeBucketTypeListToEth(outputs abi.Arguments, bucketTypes *iotextypes.ContractStakingBucketTypeList) (string, error) {
   143  	args := make([]BucketTypeEth, len(bucketTypes.BucketTypes))
   144  	for i, bt := range bucketTypes.BucketTypes {
   145  		args[i] = BucketTypeEth{}
   146  		if amount, ok := new(big.Int).SetString(bt.StakedAmount, 10); ok {
   147  			args[i].StakedAmount = amount
   148  		} else {
   149  			return "", errConvertBigNumber
   150  		}
   151  		args[i].StakedDuration = bt.StakedDuration
   152  	}
   153  
   154  	data, err := outputs.Pack(args)
   155  	if err != nil {
   156  		return "", err
   157  	}
   158  	return hex.EncodeToString(data), nil
   159  }
   160  
   161  // BuildReadStateRequest decode eth_call data to StateContext
   162  func BuildReadStateRequest(data []byte) (protocol.StateContext, error) {
   163  	if len(data) < 4 {
   164  		return nil, errInvalidCallData
   165  	}
   166  
   167  	switch methodSig := hex.EncodeToString(data[:4]); methodSig {
   168  	case hex.EncodeToString(_bucketsMethod.ID):
   169  		return newBucketsStateContext(data[4:])
   170  	case hex.EncodeToString(_bucketsByCandidateMethod.ID):
   171  		return newBucketsByCandidateStateContext(data[4:])
   172  	case hex.EncodeToString(_bucketsByIndexesMethod.ID):
   173  		return newBucketsByIndexesStateContext(data[4:])
   174  	case hex.EncodeToString(_bucketsByVoterMethod.ID):
   175  		return newBucketsByVoterStateContext(data[4:])
   176  	case hex.EncodeToString(_bucketsCountMethod.ID):
   177  		return newBucketsCountStateContext()
   178  	case hex.EncodeToString(_candidatesMethod.ID):
   179  		return newCandidatesStateContext(data[4:])
   180  	case hex.EncodeToString(_candidateByNameMethod.ID):
   181  		return newCandidateByNameStateContext(data[4:])
   182  	case hex.EncodeToString(_candidateByAddressMethod.ID):
   183  		return newCandidateByAddressStateContext(data[4:])
   184  	case hex.EncodeToString(_totalStakingAmountMethod.ID):
   185  		return newTotalStakingAmountContext()
   186  	case hex.EncodeToString(_compositeBucketsMethod.ID):
   187  		return newCompositeBucketsStateContext(data[4:])
   188  	case hex.EncodeToString(_compositeBucketsByCandidateMethod.ID):
   189  		return newCompositeBucketsByCandidateStateContext(data[4:])
   190  	case hex.EncodeToString(_compositeBucketsByIndexesMethod.ID):
   191  		return newCompositeBucketsByIndexesStateContext(data[4:])
   192  	case hex.EncodeToString(_compositeBucketsByVoterMethod.ID):
   193  		return newCompositeBucketsByVoterStateContext(data[4:])
   194  	case hex.EncodeToString(_compositeBucketsCountMethod.ID):
   195  		return newCompositeBucketsCountStateContext()
   196  	case hex.EncodeToString(_compositeTotalStakingAmountMethod.ID):
   197  		return newCompositeTotalStakingAmountContext()
   198  	case hex.EncodeToString(_contractBucketTypesMethod.ID):
   199  		return newContractBucketTypesStateContext(data[4:])
   200  	default:
   201  		return nil, errInvalidCallSig
   202  	}
   203  }