From cc1cdafbcb30173cb7023d434a537f213c840c7c Mon Sep 17 00:00:00 2001 From: Jeremy Letang Date: Tue, 22 Oct 2024 11:08:27 +0100 Subject: [PATCH] fix: avoid paying fee with staking related transfers Signed-off-by: Jeremy Letang --- core/banking/fee_estimate.go | 8 ++++++-- core/banking/oneoff_transfers.go | 4 ++-- core/banking/recurring_transfers.go | 2 +- core/banking/transfers_common.go | 12 ++++++++---- core/types/staking.go | 6 +++++- core/vesting/engine.go | 2 +- datanode/api/trading_data_v2.go | 2 ++ 7 files changed, 25 insertions(+), 11 deletions(-) diff --git a/core/banking/fee_estimate.go b/core/banking/fee_estimate.go index 0c2d94d45b6..c738da26fba 100644 --- a/core/banking/fee_estimate.go +++ b/core/banking/fee_estimate.go @@ -31,9 +31,10 @@ func EstimateFee( fromAccountType types.AccountType, fromDerivedKey *string, to string, + toAccountType types.AccountType, ) (fee *num.Uint, discount *num.Uint) { tFee := calculateFeeForTransfer(assetQuantum, maxQuantumAmount, transferFeeFactor, amount, from, - fromAccountType, fromDerivedKey, to) + fromAccountType, fromDerivedKey, to, toAccountType) return calculateDiscount(accumulatedDiscount, tFee) } @@ -46,12 +47,15 @@ func calculateFeeForTransfer( fromAccountType types.AccountType, fromDerivedKey *string, to string, + toAccountType types.AccountType, ) *num.Uint { feeAmount := num.UintZero() // no fee for Vested account // either from owner's vested to their general account or from derived key vested to owner's general account - if fromAccountType == types.AccountTypeVestedRewards && (from == to || fromDerivedKey != nil) { + if (fromAccountType == types.AccountTypeVestedRewards && (from == to || fromDerivedKey != nil)) || + (fromAccountType == types.AccountTypeLockedForStaking && from == to) || + (fromAccountType == types.AccountTypeGeneral && toAccountType == types.AccountTypeLockedForStaking && from == to) { return feeAmount } diff --git a/core/banking/oneoff_transfers.go b/core/banking/oneoff_transfers.go index 9531c506610..732e1cc2e6f 100644 --- a/core/banking/oneoff_transfers.go +++ b/core/banking/oneoff_transfers.go @@ -93,7 +93,7 @@ func (e *Engine) updateStakingAccounts( BlockHeight: height, BlockTime: now, LogIndex: 1, - EthereumAddress: transfer.From, + EthereumAddress: "", } } @@ -112,7 +112,7 @@ func (e *Engine) updateStakingAccounts( BlockHeight: height, BlockTime: now, LogIndex: 1, - EthereumAddress: transfer.From, + EthereumAddress: "", } } diff --git a/core/banking/recurring_transfers.go b/core/banking/recurring_transfers.go index db70b0da861..3bbc0c9ad6c 100644 --- a/core/banking/recurring_transfers.go +++ b/core/banking/recurring_transfers.go @@ -321,7 +321,7 @@ func (e *Engine) distributeRecurringTransfers(ctx context.Context, newEpoch uint ) } else { // check if the amount + fees can be covered by the party issuing the transfer - if err = e.ensureFeeForTransferFunds(a, amount, v.From, v.FromAccountType, v.FromDerivedKey, v.To); err == nil { + if err = e.ensureFeeForTransferFunds(a, amount, v.From, v.FromAccountType, v.FromDerivedKey, v.To, v.ToAccountType); err == nil { // NB: if the metric is market value we're going to transfer the bonus if any directly // to the market account of the asset/reward type - this is similar to previous behaviour and // different to how all other metric based rewards behave. The reason is that we need the context of the funder diff --git a/core/banking/transfers_common.go b/core/banking/transfers_common.go index cd7a7dfb5d7..a5390f62e11 100644 --- a/core/banking/transfers_common.go +++ b/core/banking/transfers_common.go @@ -95,7 +95,7 @@ func (e *Engine) CheckTransfer(t *types.TransferBase) error { return err } - if err = e.ensureFeeForTransferFunds(a, t.Amount, t.From, t.FromAccountType, t.FromDerivedKey, t.To); err != nil { + if err = e.ensureFeeForTransferFunds(a, t.Amount, t.From, t.FromAccountType, t.FromDerivedKey, t.To, t.ToAccountType); err != nil { return fmt.Errorf("could not transfer funds, %w", err) } return nil @@ -166,7 +166,7 @@ func (e *Engine) processTransfer( // ensure the party have enough funds for both the // amount and the fee for the transfer - feeTransfer, discount, err := e.makeFeeTransferForFundsTransfer(ctx, assetType, amount, from, fromAcc, fromDerivedKey, to) + feeTransfer, discount, err := e.makeFeeTransferForFundsTransfer(ctx, assetType, amount, from, fromAcc, fromDerivedKey, to, toAcc) if err != nil { return nil, fmt.Errorf("could not pay the fee for transfer: %w", err) } @@ -249,6 +249,7 @@ func (e *Engine) calculateFeeTransferForTransfer( fromAccountType types.AccountType, fromDerivedKey *string, to string, + toAccountType types.AccountType, ) *num.Uint { return calculateFeeForTransfer( asset.Details.Quantum, @@ -259,6 +260,7 @@ func (e *Engine) calculateFeeTransferForTransfer( fromAccountType, fromDerivedKey, to, + toAccountType, ) } @@ -270,8 +272,9 @@ func (e *Engine) makeFeeTransferForFundsTransfer( fromAccountType types.AccountType, fromDerivedKey *string, to string, + toAccountType types.AccountType, ) (*types.Transfer, *num.Uint, error) { - theoreticalFee := e.calculateFeeTransferForTransfer(asset, amount, from, fromAccountType, fromDerivedKey, to) + theoreticalFee := e.calculateFeeTransferForTransfer(asset, amount, from, fromAccountType, fromDerivedKey, to, toAccountType) feeAmount, discountAmount := e.ApplyFeeDiscount(ctx, asset.ID, from, theoreticalFee) if err := e.ensureEnoughFundsForTransfer(asset, amount, from, fromAccountType, fromDerivedKey, feeAmount); err != nil { @@ -306,9 +309,10 @@ func (e *Engine) ensureFeeForTransferFunds( fromAccountType types.AccountType, fromDerivedKey *string, to string, + toAccountType types.AccountType, ) error { assetType := asset.ToAssetType() - theoreticalFee := e.calculateFeeTransferForTransfer(assetType, amount, from, fromAccountType, fromDerivedKey, to) + theoreticalFee := e.calculateFeeTransferForTransfer(assetType, amount, from, fromAccountType, fromDerivedKey, to, toAccountType) feeAmount, _ := e.EstimateFeeDiscount(assetType.ID, from, theoreticalFee) return e.ensureEnoughFundsForTransfer(assetType, amount, from, fromAccountType, fromDerivedKey, feeAmount) } diff --git a/core/types/staking.go b/core/types/staking.go index 21e52a26d7a..87eb77fb2ce 100644 --- a/core/types/staking.go +++ b/core/types/staking.go @@ -141,6 +141,10 @@ func (s *StakeLinking) IntoProto() *eventspb.StakeLinking { func StakeLinkingFromProto(sl *eventspb.StakeLinking) *StakeLinking { amt, _ := num.UintFromString(sl.Amount, 10) + var ethereumAddress string + if len(sl.EthereumAddress) > 0 { + ethereumAddress = crypto.EthereumChecksumAddress(sl.EthereumAddress) + } return &StakeLinking{ ID: sl.Id, Type: sl.Type, @@ -153,7 +157,7 @@ func StakeLinkingFromProto(sl *eventspb.StakeLinking) *StakeLinking { BlockHeight: sl.BlockHeight, BlockTime: sl.BlockTime, LogIndex: sl.LogIndex, - EthereumAddress: crypto.EthereumChecksumAddress(sl.EthereumAddress), + EthereumAddress: ethereumAddress, } } diff --git a/core/vesting/engine.go b/core/vesting/engine.go index c9187fcf4b5..e30c7759580 100644 --- a/core/vesting/engine.go +++ b/core/vesting/engine.go @@ -217,7 +217,7 @@ func (e *Engine) updateStakingAccount( BlockHeight: height, BlockTime: now, LogIndex: logIndex, - EthereumAddress: party, + EthereumAddress: "", } e.stakeAccounting.AddEvent(context.Background(), stakeLinking) diff --git a/datanode/api/trading_data_v2.go b/datanode/api/trading_data_v2.go index d8de10a837c..b273fcefb15 100644 --- a/datanode/api/trading_data_v2.go +++ b/datanode/api/trading_data_v2.go @@ -5728,6 +5728,8 @@ func (t *TradingDataServiceV2) EstimateTransferFee(ctx context.Context, req *v2. req.FromAccountType, req.FromAmmKey, req.ToAccount, + // irrelvant here + vega.AccountType_ACCOUNT_TYPE_UNSPECIFIED, ) return &v2.EstimateTransferFeeResponse{