The Reserve is reimbursing RUNE to pools for Inactive vault refunds (the 'difference' part of the gas)
(Noticed when certain Flipside charts crashed from divide-by-zero errors,
expected to never happen for that context.
Other examples were in blocks 11527981, 11986959, and 11987126 (all BTC rather than LTC).)
[Edit: The phenomenon might occur for all InactiveVault UTXO refunds,
but is easiest to identify in blocks with no other gas-costing transactions.]
There are 32 transactions in the /txs endpoint for block 11520098,
and all are observations for the same LTC.LTC REFUND:
, TxID 2637..E1D7.
https://thornode-v1.ninerealms.com/txs?limit=100&tx.height=11520098
https://midgard.ninerealms.com/v2/debug/block/11520098
{
"attributes": {
"asset": "LTC.LTC",
"asset_amt": "8503",
"rune_amt": "848470",
"transaction_count": "0"
},
"type": "gas"
}
Intuitively, how can THORChain be reimbursing non-zero gas for zero transactions?
[Edit: See update below.]
The rune_amt was indeed transferred to the Pool Module from the Reserve.
{
"attributes": {
"amount": "848470rune",
"recipient": "thor1g98cy3n9mmjrpn0sxmn63lztelera37n8n67c0",
"sender": "thor1dheycdevq39qlkxs2a6wuuzyn4aqxhve4qxtxt"
},
"type": "transfer"
},
{
"attributes": {
"chain": "LTC",
"coin": "2994935 LTC.LTC",
"from": "ltc1qcp4vwpr34g5kh0nw05mdn8jlcf8d0mnz4x9k2f",
"id": "2637D2ADCE985B7C5099ED00076B4C8B4CEF7BB11ED7232466C3869DB7FBE1D7",
"in_tx_id": "6EC193D7822DDD4780B7717DD25A7A528D49478C384F2418F3F4EB6764E50832",
"memo": "REFUND:6EC193D7822DDD4780B7717DD25A7A528D49478C384F2418F3F4EB6764E50832",
"to": "ltc1q4dytvvx9zj2smf0q0pvhe9j0qhjla26lmm3zf4"
},
"type": "outbound"
}
],
"gas": [
{
"asset": "LTC.LTC",
"amount": "27122"
}
],
This seems as though the "gas" event should have asset_amt 27122 and transaction_count 1.
Instead it has asset_amt 18298 and transaction_count 0.
These blocks are from v1.114.0 and later;
this appears to be related to v1.112.0's !2869 (merged)
'make "best efforts" to refund txns sent to inactive vault'.
This refund was from an Inactive vault:
https://thornode-v1.ninerealms.com/thorchain/queue/outbound?height=11520097
"vault_pub_key": "thorpub1addwnpepqv2es3uqtvsmkwnhdxcfkwzvh2zmer4s5jh00ymxl8p8g8pnuchnjcenhqh",
https://thornode-v1.ninerealms.com/thorchain/vaults/pubkeys?height=11520098
https://thornode-v1.ninerealms.com/thorchain/vault/thorpub1addwnpepqv2es3uqtvsmkwnhdxcfkwzvh2zmer4s5jh00ymxl8p8g8pnuchnjcenhqh?height=11520098
In particular, since the gas was paid out of the gas asset to be refunded (which was not added to the pool and with leftover not left in the pool),
the Reserve should not be reimbursing RUNE to the pool for this gas.
Update:
https://gitlab.com/thorchain/thornode/-/blob/v1.116.0/x/thorchain/manager_gas_current.go#L47-56
// AddGasAsset to the EventGas
func (gm *GasMgrVCUR) AddGasAsset(gas common.Gas, increaseTxCount bool) {
gm.gas = gm.gas.Add(gas)
if !increaseTxCount {
return
}
for _, coin := range gas {
gm.gasCount[coin.Asset]++
}
}
That increaseTxCount bool argument is perhaps how transaction_count can remain 0.
The bool is true for addGasFees
and false for handler_common_outbound.go
.
This false case is when adjusting the gas of the gas event to a higher number, to reflect that part of the MaxGas has been received by the user as an Amount addition.
I believe the code assumes the transaction_count has already been incremented by addGasFees
in handler_observed_txout.go
.
Here the "gas" event reports a lower amount than the voter gas amount,
so I suspect the main amount (being for an Inactive vault refund) is not calling addGasFees
,
but that handler_common_outbound.go
is still adding the 'diffGas' amount to the "gas" event, which is then being reimbursed by the Reserve.
Looking--
https://gitlab.com/thorchain/thornode/-/blob/v1.116.0/x/thorchain/handler_observed_txout.go#L225-231
// Apply Gas fees
if vault.Status != InactiveVault {
if err := addGasFees(ctx, h.mgr, tx); err != nil {
ctx.Logger().Error("fail to add gas fee", "error", err)
continue
}
}
I currently suggest adding a tx.ObservedPubKey GetVault
and vault.Status != InactiveVault
condition to (within) the
if maxGasAmt.GT(realGasAmt) {
handler_common_outbound.go conditional,
following the pattern of handler_observed_txout.go .
Specifically, this is my current code proposal: !3052 (merged)
'Don't reimburse gas difference for an outbound from an InactiveVault'.