trezor-suite
trezor-suite copied to clipboard
Solana: Include priority fee in TX
User Story
As a Solana user I want to send transactions So that I can operate within the Solana ecosystem
Acceptance Criteria
Given I sign a transaction When I broadcast it Then it should appear as confirmed
Proposal
Introduce dynamic priority fee. From user POV it will be labelled as 'fee', whilst in fact it will be the sum of the base fee and the network influenced priority fee.
nu.fi wallet has just launched priority fee support.
Background
Solana has entered a high fee environment and the default base fee of 0.000005 SOL
limits users ability to move funds. Reddit posts: 1, 2, 3
Related
High fee mitigation with a faux 'sending' phase of the SOL TX. https://github.com/trezor/trezor-suite/pull/11033
As discussed offline I’m writing here the proposal for SOL priority fees implementation. Should you have any questions or ideas for improvements, please let me know. cc @matejcik for the Firmware section below 🙏
Compute unit price of transactions
SOL transfer: 150 (tx example) - 450 (tx example) (Solana docs actually mention 300, perhaps it’s 300 without the compute unit limit instruction)
Token transfer: 5876 (tx example)
Token transfer with account creation: 26663 (tx example)
The values might vary if priority fees are included, I’d check the values properly during implementation.
Trezor Suite
Fee fetching and computation
Recent priority fees can be fetched using the getRecentPrioritizationFees RPC call which returns fee data from the most recent 150 blocks.
We’d like to use TrezorConnect.BlockchainEstimateFee
to estimate the fee which would require adding an estimateFee
function to the Solana worker. The estimateFee
function would call the getRecentPrioritizationFees RPC function, take the 25th percentile value of the fees returned and use that value as the compute unit price.
const computeUnitPriceLamports = _.sortBy(
recentFees.map((f) => f.prioritizationFee),
).reverse()[Math.floor(recentFees.length / 4)]
There will however be also a minimum priority fee added to each transaction in case the fees fetched from the network are 0 (which is most of the time). This will be equal to 4000 lamports (default fee is 5000 lamports). 100_000 micro-lamports compute unit price * 40_000 compute unit limit.
const DEFAULT_COMPUTE_UNIT_PRICE = 100_000 // used as default by other wallets, micro-lamports
const DEFAULT_COMPUTE_UNIT_LIMIT = 40_000 // should be enough to cover transactions made via Trezor Suite
const computeUnitPriceLamports = DEFAULT_COMPUTE_UNIT_PRICE * (10 ** -6)
const finalFeeLamports = 5000 + (computeUnitPriceLamports * DEFAULT_COMPUTE_UNIT_LIMIT)
// 9000 lamports
40_000 compute unit limit should be enough for transaction made by Suite - I’d verify this though during development as the default seems to be 200K per instruction. The compute unit limit could also be adjusted depending on the transaction but given the fees on Solana are rather low, this seems unnecessary (other wallets default to 200_000 or 300_000 compute units for all their transactions).
The resulting default fee in Suite would thus be 9000 lamports (i.e. almost twice the fee without priority fees). In times of network congestion, the price would increase depending on the values returned from the getRecentPrioritizationFees RPC function.
Transaction building
Hopefully the only other changes would need to be made in solanaUtils (or sendFormSolanaThunks) where the transactions are being built. We would need to modify all transactions to include the ComputeBudget instructions with the priority fees.
Firmware
Trezor Firmware supports a feature we can call “simplified UI” for SOL transfers and Token transfers (with or without token account creation). This feature however doesn’t take Priority Fees’ instructions into consideration and so the “simplified UI” would never be shown for transactions including priority fees i.e. all Suite transactions in the future.
Firmware would thus also need to be updated to ignore SetComputeUnitLimit and SetComputeUnitPrice instructions when determining whether a “simplified UI” should be shown (around here).
Also since these two compute budget instructions (SetComputeUnitLimit and SetComputeUnitPrice) affect only the fee which is properly displayed on Trezor, we can safely always hide these two instructions from the user (i.e. not only in “simplified UI”).
@trezor/qa can we close this? Is it OK? :)