edge / wallet

The web wallet of the XE Blockchain.

Home Page:https://wallet.xe.network

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

NaN XE fee for withdrawals

annybs opened this issue · comments

commented

There is a critical problem in AccountPanel where props are reused across multiple inner "views" in a way that breaks fee calculation for withdrawals, both visually and in the actual withdrawal.

The same data.amount prop is bound to three inputs: here, here, and here. In turn, the data.amount prop is watched here:

amount: ['calculateEdge', 'calculateUSDC'],

This means that whenever data.amount is updated by any of the three inputs, both of these component methods are invoked, causing the fee to be recalculated - twice:

this.fee = Math.round(this.minimumFee + this.selectedFeeLevel)

this.fee = Math.round(this.minimumFee + this.exchangeRate.gas)

data.fee is itself bound to multiple elements (too many to list) with :value="fee" - the key effect being that the same data.amount and data.fee properties are used across all inner views (and, notably, persist across them even if the modal is opened/closed).

Going back to the watch rule: whenever the data.amount is updated, the data.fee property is updated twice, by calculateEdge() and then calculateUSDC() - with the result that the following reproduction steps will display a NaN fee:

  1. Open exchange modal
  2. Open 'Withdraw' inner view
  3. (optional) Select any transaction speed
  4. Update amount

We see NaN because the USDC fee calculation is done second, which uses data.exchangeRate the gas property of which is initially undefined. As a result, the calculation fails since undefined cannot be parsed to a number.

To fix this, you can select a transaction speed again. NaN is cleared and a correct fee is shown (and subsequently used while attempting withdrawal). This works because the options are bound to only calculateEdge() and not calculateUSDC():

selectFeeLevel(value) {
this.selectedFeeLevel = value
this.calculateEdge()
},

Another way to "fix" this (although improperly) is through the following reproduction steps:

  1. Open exchange modal
  2. Open 'Sell' inner view
  3. Cancel and reopen exchange modal
  4. Open 'Withdraw' inner view

Now, you can update amount before or after transaction speed, it doesn't matter. This works because opening the 'Sell' view updates the exchangeRate object with actual values, allowing the calculation to work.

Of course, these steps don't actually solve the problem, because you still see the USDC fee, which is likely to differ from the EDGE withdrawal fee. So, an unknowing user might follow these steps, and then inadvertently attempt to create a withdrawal transaction with an incorrect fee.

Fundamentally, the problem here is misappropriation of shared props for multiple different uses, and the optimal solution here is to isolate each inner view of the modal into its own component, using its own properties. A quicker fix might be just to define separate properties for each view within the AccountPanel component. However, the component is already complex enough as it is, and I think the larger task of refactoring is warranted in the circumstances.

Welcoming feedback from @adamkdean before I go ahead making fixes.

commented

I've monkey-patched this for now to minimise time spent on the problem: 1542e8b