-
Notifications
You must be signed in to change notification settings - Fork 199
/
claimDeveloperRewards.go
107 lines (90 loc) · 3.05 KB
/
claimDeveloperRewards.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
package builtInFunctions
import (
"bytes"
"math/big"
"sync"
"github.com/ElrondNetwork/elrond-go/core"
"github.com/ElrondNetwork/elrond-go/core/check"
"github.com/ElrondNetwork/elrond-go/core/vmcommon"
"github.com/ElrondNetwork/elrond-go/data/state"
"github.com/ElrondNetwork/elrond-go/process"
)
var _ process.BuiltinFunction = (*claimDeveloperRewards)(nil)
type claimDeveloperRewards struct {
gasCost uint64
mutExecution sync.RWMutex
}
// NewClaimDeveloperRewardsFunc returns a new developer rewards implementation
func NewClaimDeveloperRewardsFunc(gasCost uint64) *claimDeveloperRewards {
return &claimDeveloperRewards{gasCost: gasCost}
}
// SetNewGasConfig is called whenever gas cost is changed
func (c *claimDeveloperRewards) SetNewGasConfig(gasCost *process.GasCost) {
c.mutExecution.Lock()
c.gasCost = gasCost.BuiltInCost.ClaimDeveloperRewards
c.mutExecution.Unlock()
}
// ProcessBuiltinFunction processes the protocol built-in smart contract function
func (c *claimDeveloperRewards) ProcessBuiltinFunction(
acntSnd, acntDst state.UserAccountHandler,
vmInput *vmcommon.ContractCallInput,
) (*vmcommon.VMOutput, error) {
c.mutExecution.RLock()
defer c.mutExecution.RUnlock()
if vmInput == nil {
return nil, process.ErrNilVmInput
}
if vmInput.CallValue.Cmp(zero) != 0 {
return nil, process.ErrBuiltInFunctionCalledWithValue
}
gasRemaining := computeGasRemaining(acntSnd, vmInput.GasProvided, c.gasCost)
if check.IfNil(acntDst) {
// cross-shard call, in sender shard only the gas is taken out
return &vmcommon.VMOutput{ReturnCode: vmcommon.Ok, GasRemaining: gasRemaining}, nil
}
if !bytes.Equal(vmInput.CallerAddr, acntDst.GetOwnerAddress()) {
return nil, process.ErrOperationNotPermitted
}
if vmInput.GasProvided < c.gasCost {
return nil, process.ErrNotEnoughGas
}
value, err := acntDst.ClaimDeveloperRewards(vmInput.CallerAddr)
if err != nil {
return nil, err
}
vmOutput := &vmcommon.VMOutput{GasRemaining: gasRemaining, ReturnCode: vmcommon.Ok}
outTransfer := vmcommon.OutputTransfer{
Value: big.NewInt(0).Set(value),
GasLimit: 0,
Data: nil,
CallType: vmcommon.DirectCall,
}
if vmInput.CallType == vmcommon.AsynchronousCall {
outTransfer.GasLocked = vmInput.GasLocked
outTransfer.GasLimit = vmOutput.GasRemaining
outTransfer.CallType = vmcommon.AsynchronousCallBack
vmOutput.GasRemaining = 0
}
outputAcc := &vmcommon.OutputAccount{
Address: vmInput.CallerAddr,
BalanceDelta: big.NewInt(0).Set(value),
OutputTransfers: []vmcommon.OutputTransfer{outTransfer},
}
vmOutput.OutputAccounts = make(map[string]*vmcommon.OutputAccount)
vmOutput.OutputAccounts[string(outputAcc.Address)] = outputAcc
if check.IfNil(acntSnd) {
return vmOutput, nil
}
err = acntSnd.AddToBalance(value)
if err != nil {
return nil, err
}
if core.IsSmartContractAddress(vmInput.CallerAddr) {
vmOutput.OutputAccounts = make(map[string]*vmcommon.OutputAccount)
}
return vmOutput, nil
}
// IsInterfaceNil returns true if underlying object is nil
func (c *claimDeveloperRewards) IsInterfaceNil() bool {
return c == nil
}