Crypto One supports two Weight Average Cost (WAC) methods. One is perpetual and the other one is periodic. This article will outline the behavior of the accounting algorithm.
The algorithm moves from down the inventory in an increasing timestamp. Perpetual inventory systems require the cost of goods sold to be calculated each time there is a sale (send or sell transaction). Therefore, at the time of each sale, the algorithm calculates the weighted average cost of the units available in the inventory at the time of the sale.
In this example, we will have the following transaction list:
The following transaction pool shows one inflow inventory 0.1 ETH coming in at a unit price of $927.95. Since it's the only inflow transaction the WAC calculated to be $927.95. The remaining outflow transactions are calculated at the said WAC value.
Then the following transactions occur. One inflow and three outflows. Based on the new remaining inventory and the new inventory the WAC is updated.
WAC is calculate by getting all the inflow transactions with datetimestamps prior or equal outflow transaction. WAC Equation:
WAC = (Sum of cost basis / Sum of units available)
inflow transactions with timestamps <= outflow tranaction timestamp
Therefore WAC is recalculated the followiing way:
0.098796908999 (remaining inventory) x $927.95 (WAC) = $91.67859170562205
64.23440 (new inventory) x $867.62 (unit price) = $55731.050128
WAC = $55822.72871970562205 ÷ 64.3331969089989 (Total Inventory) = $867.712649173465258
The remaining outflows are calculated the following way:
Special Scenario - Transactions having the same timestamp
Case #1 - Two consecutive outflows where the second outflow as an inflow with the same timetamp
|13||Out||2/26/2023 12:12||WAC does not use the inventory on transaction #14|
The WAC is recalculated everytime an inflow transaction occurs in the inventory. In the world of crypto, there is room for complications as inflow/outflow transactions can happen at the same time in transactions such as dex swaps, trades etc. Therefore If a outflow and a inflow transaction happens at the same time, this will trigger a race condition whether the recalculated WAC will apply to the outflow transaction thats in the same timestamp as the inflow.
In Crypto One, we handle this issue by assinging a priority to the ledger line item. If an outflow and an inflow transaction happened at the same time, the system gives priority to the ledger insertion order id. If the outflow contains a lower id than the inflow (regardless of having the same timestamp), the WAC used in the outflow transaction will not include the inventory of the inflow transaction.
In the opposite scenario, If the inflow was inserted before the outflow (regardless of having the same timestamp), the WAC value used in the outflow transaction will be include the inventory of the inflow transaction.
Above scenario assumes, the transaction prior to the outflow is also an outflow.
Case #2 - Inflow transaction followed by an outflow and inflow pair with the same timestamp
In the following scenario, we have:
|12||In||2/26/2023 11:11||Receive transaction has a higher id than send. Does not use transaction #11 for WAC|
|13||Out||2/26/2023 12:12||WAC contains previous inventory prior to #11, #12 and #14 (since #14 happened on a time <= to the #13 timestamp)|
Upon reaching transaction #11, transaction #12 will not be used to recalculate WAC regardless of having the same timestamp as #11. Recalculation of WAC will infact does not happen at all at transaction #11. It will continue to use the WAC calculated prior to transaction #11.
On reaching transaction #12, a trigger is sent to the algorithm to recalculate WAC upon next outflow. At transaction #13 the trigger is executed to recalculate WAC on the next outflow. Hence a new WAC is calculated at #13 by combining the WAC calculated on #11 + #12 and #14.
In summary, this special case occurs because #12 which is an inflow triggered a recalculation of WAC. Therefore #13 gets #14 included in the WAC calculation vs where #11 did not get #12 included in the WAC.