Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problems dealing with total losses & bankruptcy #139

Open
gbtorrance opened this issue Feb 13, 2025 · 8 comments
Open

Problems dealing with total losses & bankruptcy #139

gbtorrance opened this issue Feb 13, 2025 · 8 comments

Comments

@gbtorrance
Copy link

gbtorrance commented Feb 13, 2025

Hi,

I was unfortunately caught up in the Celsius bankruptcy. I had a basket of tokens on Celsius at the time of bankruptcy in 2022, and received BTC and ETH distributions in exchanges for these tokens in 2024.

The way I wanted to deal with this was to record each token in the initial basket as a total loss (long-term capital loss), and also add "dummy" transactions to "buy" the BTC & ETH for "free" (the allocation from the bankruptcy) and later sell it in 2024 for my actual sell price, resulting in a long-term capital gain to offset the earlier loss. From a tax perspective that should correct (even though it's a bit of a hack).

But I've encountered two problems.

  1. I cannot record a BUY or SELL with zero spot price, because I get this error:
ERROR: Fatal exception occurred:
Traceback (most recent call last):
  File "/home/greg/.local/lib/python3.10/site-packages/rp2/rp2_main.py", line 151, in _rp2_main_internal
    input_data: InputData = parse_ods(configuration=configuration, asset=asset, input_file_handle=input_file_handle)
  File "/home/greg/.local/lib/python3.10/site-packages/rp2/ods_parser.py", line 127, in parse_ods
    _create_and_process_transaction(
  File "/home/greg/.local/lib/python3.10/site-packages/rp2/ods_parser.py", line 166, in _create_and_process_transaction
    transaction: AbstractTransaction = _create_transaction(configuration, current_table_type, internal_id, row_values)
  File "/home/greg/.local/lib/python3.10/site-packages/rp2/ods_parser.py", line 286, in _create_transaction
    transaction = OutTransaction(**argument_pack)
  File "/home/greg/.local/lib/python3.10/site-packages/rp2/out_transaction.py", line 63, in __init__
    raise RP2ValueError(f"{self.asset} {type(self).__name__} ({self.timestamp}, id {self.internal_id}): parameter 'spot_price' cannot be 0")
rp2.rp2_error.RP2ValueError: BTC OutTransaction (2023-09-18 16:09:00-04:00, id 572): parameter 'spot_price' cannot be 0

  1. I cannot use the LOST transaction type, even though the documentation seems to indicate that it is valid.

From the documentation:

transaction_type: DONATE, FEE, GIFT, LOST (useful to represent lost coins, due to exchange bankruptcy, theft, etc.), SELL or STAKING (useful to represent staking losses, due to node being offline, etc.).

I get the following error:

ERROR: Fatal exception occurred:
Traceback (most recent call last):
  File "/home/greg/.local/lib/python3.10/site-packages/rp2/rp2_main.py", line 151, in _rp2_main_internal
    input_data: InputData = parse_ods(configuration=configuration, asset=asset, input_file_handle=input_file_handle)
  File "/home/greg/.local/lib/python3.10/site-packages/rp2/ods_parser.py", line 127, in parse_ods
    _create_and_process_transaction(
  File "/home/greg/.local/lib/python3.10/site-packages/rp2/ods_parser.py", line 166, in _create_and_process_transaction
    transaction: AbstractTransaction = _create_transaction(configuration, current_table_type, internal_id, row_values)
  File "/home/greg/.local/lib/python3.10/site-packages/rp2/ods_parser.py", line 286, in _create_transaction
    transaction = OutTransaction(**argument_pack)
  File "/home/greg/.local/lib/python3.10/site-packages/rp2/out_transaction.py", line 45, in __init__
    super().__init__(configuration, timestamp, asset, transaction_type, spot_price, row, unique_id, notes)
  File "/home/greg/.local/lib/python3.10/site-packages/rp2/abstract_transaction.py", line 40, in __init__
    self.__transaction_type: TransactionType = TransactionType.type_check_from_string("transaction_type", transaction_type)
  File "/home/greg/.local/lib/python3.10/site-packages/rp2/entry_types.py", line 46, in type_check_from_string
    raise RP2ValueError(f"Parameter '{name}' has invalid transaction type value: {transaction_type}")
rp2.rp2_error.RP2ValueError: Parameter 'transaction_type' has invalid transaction type value: LOST

Is it possible to make spot price == 0 be a warning rather than an error? Seems there are cases where this is reasonable, right?

And shouldn't LOST be valid?

Thanks!


BTW, I'm on RP2 1.7.1

@gbtorrance
Copy link
Author

For the sells I ended up working around the issue by recording fiat_out_no_fee as 0.000001, which is close enough to zero that the desired effect was achieved. (fiat_out_no_fee also disallows zero values.)

For the buys of BTC and ETH (which I wanted to "buy" for "free" as they were distributed by Celsius) I decided to not record these in RP2 at all. (I could have done something similar to the above, but decided not to.) I will just record these as stand-alone long-term gains for TY2024.

@eprbell
Copy link
Owner

eprbell commented Feb 14, 2025

The correct way to represent this is via the LOST transaction type. The reason it's not recognized is that it was introduced after the latest release, so I need to cut a new release including the latest changes: I'll do that in the weekend. I don't think we should allow transactions with zero spot price, unless there is a compelling reason to do so.

@gbtorrance
Copy link
Author

Gotcha. Thanks!

@eprbell
Copy link
Owner

eprbell commented Feb 15, 2025

OK, I cut a new release of RP2 (1.7.2): can you try again?

@gbtorrance
Copy link
Author

Hi @eprbell. Sorry for the delayed reply.

I tested, and unfortunately it's not working as expected. Take this example.

All my AAVE on Celsius was lost, so I recorded the following.

Image

I entered a dummy spot_price of $1, since it really shouldn't matter. But I noticed that is being used to calculate non-zero "proceeds". But "proceeds" should be zero in the case of a LOST transaction.

Image

@eprbell
Copy link
Owner

eprbell commented Feb 19, 2025

I haven't looked much at the tax treatment of losses, so I may be wrong here, but the thinking was to show what the proceeds would be for any given out transaction (gain - cost), regardless of transaction type. This number can be used as necessary in various jurisdictions: e.g. maybe in the US it can be replaced with $0, maybe in other jurisdictions it has different treatments. The point is: if we wrote 0 there we would lose some information that may otherwise be useful under some tax jurisdictions.

@gbtorrance
Copy link
Author

Thanks for the reply, @eprbell. I'll argue the other side of it:

  • "Proceeds" represent what you get from the counter-party in a transaction. I get your point that it may not always be zero, but I'd argue it will be zero in 99.9% of the cases (and I can't even envision that 0.1% chance it is not). If tokens are lost, who is going to be on the other side of the transaction to reimburse? And even if something is recovered in a loss situation, it won't be like a SELL where spot price is multiplied by number of tokens to arrive at an amount for "proceeds". (Maybe if there is a non-zero value entered in fiat_out_no_fee that could be recorded for proceeds, but multiplying spot price by number of tokens just doesn't make sense.)
  • If, in the vast majority of cases, "proceeds" should be zero, would it not cause unnecessary confusion for RP2 users to have to be aware that the report is "wrong" and they need to adjust "proceeds" to zero for accurate tax reporting?
  • If it behaves basically the same as a SELL, is there really any purpose in having a LOST type?

IMO, non-zero proceeds for a LOST transaction doesn't make sense in the vast majority of cases, if ever.

That said, whatever you decide to do is fine. I'll just use SELL for my scenario with fiat_out_no_fee set to 0.000001.

@gbtorrance
Copy link
Author

Thinking about it some more, I suppose in a bankruptcy case getting something back (whether fiat or tokens) is certainly a possibility. (In the Celsius case, I mostly got back different tokens from what I put in, so I wasn't really thinking in terms of getting back fiat for my lost tokens.)

If I were to make a suggestion, it would be to treat LOST tokens as having zero proceeds by default, unless a non-zero value is entered in fiat_out_no_fee, in which case that would be used for proceeds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants