-
Notifications
You must be signed in to change notification settings - Fork 319
/
stake_adddeposit.go
129 lines (107 loc) · 3.72 KB
/
stake_adddeposit.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Copyright (c) 2020 IoTeX Foundation
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is didslaimed. This source code is governed by Apache
// License 2.0 that can be found in the LICENSE file.
package action
import (
"math/big"
"github.com/pkg/errors"
"google.golang.org/protobuf/proto"
"github.com/iotexproject/iotex-proto/golang/iotextypes"
"github.com/iotexproject/iotex-core/pkg/util/byteutil"
"github.com/iotexproject/iotex-core/pkg/version"
)
const (
// DepositToStakePayloadGas represents the DepositToStake payload gas per uint
DepositToStakePayloadGas = uint64(100)
// DepositToStakeBaseIntrinsicGas represents the base intrinsic gas for DepositToStake
DepositToStakeBaseIntrinsicGas = uint64(10000)
)
// DepositToStake defines the action of stake add deposit
type DepositToStake struct {
AbstractAction
bucketIndex uint64
amount *big.Int
payload []byte
}
// NewDepositToStake returns a DepositToStake instance
func NewDepositToStake(
nonce uint64,
index uint64,
amount string,
payload []byte,
gasLimit uint64,
gasPrice *big.Int,
) (*DepositToStake, error) {
stake, ok := new(big.Int).SetString(amount, 10)
if !ok {
return nil, errors.Wrapf(ErrInvalidAmount, "amount %s", amount)
}
return &DepositToStake{
AbstractAction: AbstractAction{
version: version.ProtocolVersion,
nonce: nonce,
gasLimit: gasLimit,
gasPrice: gasPrice,
},
bucketIndex: index,
amount: stake,
payload: payload,
}, nil
}
// Amount returns the amount
func (ds *DepositToStake) Amount() *big.Int { return ds.amount }
// Payload returns the payload bytes
func (ds *DepositToStake) Payload() []byte { return ds.payload }
// BucketIndex returns bucket indexs
func (ds *DepositToStake) BucketIndex() uint64 { return ds.bucketIndex }
// Serialize returns a raw byte stream of the Stake Create struct
func (ds *DepositToStake) Serialize() []byte {
return byteutil.Must(proto.Marshal(ds.Proto()))
}
// Proto converts to protobuf DepositToStake Action
func (ds *DepositToStake) Proto() *iotextypes.StakeAddDeposit {
act := &iotextypes.StakeAddDeposit{
BucketIndex: ds.bucketIndex,
Payload: ds.payload,
}
if ds.amount != nil {
act.Amount = ds.amount.String()
}
return act
}
// LoadProto converts a protobuf's Action to DepositToStake
func (ds *DepositToStake) LoadProto(pbAct *iotextypes.StakeAddDeposit) error {
if pbAct == nil {
return errors.New("empty action proto to load")
}
ds.bucketIndex = pbAct.GetBucketIndex()
ds.payload = pbAct.GetPayload()
ds.amount = big.NewInt(0)
if len(pbAct.GetAmount()) > 0 {
ds.amount.SetString(pbAct.GetAmount(), 10)
}
return nil
}
// IntrinsicGas returns the intrinsic gas of a DepositToStake
func (ds *DepositToStake) IntrinsicGas() (uint64, error) {
payloadSize := uint64(len(ds.Payload()))
return calculateIntrinsicGas(DepositToStakeBaseIntrinsicGas, DepositToStakePayloadGas, payloadSize)
}
// Cost returns the total cost of a DepositToStake
func (ds *DepositToStake) Cost() (*big.Int, error) {
intrinsicGas, err := ds.IntrinsicGas()
if err != nil {
return nil, errors.Wrap(err, "failed to get intrinsic gas for the stake creates")
}
depositToStakeFee := big.NewInt(0).Mul(ds.GasPrice(), big.NewInt(0).SetUint64(intrinsicGas))
return big.NewInt(0).Add(ds.Amount(), depositToStakeFee), nil
}
// SanityCheck validates the variables in the action
func (ds *DepositToStake) SanityCheck() error {
if ds.Amount().Sign() <= 0 {
return errors.Wrap(ErrInvalidAmount, "negative value")
}
return ds.AbstractAction.SanityCheck()
}