robosats icon indicating copy to clipboard operation
robosats copied to clipboard

Require buyer to pre‑declare payment‑account ID before chat to reduce triangulation/charge back frauds

Open TempleOfSats opened this issue 4 months ago • 14 comments

Summary

By requiring the buyer to specify their own payment‑account identifier before entering the trade chat, and automatically showing that ID to the seller, we ask seller to check: if the fiat actually arrive from the account the buyer declared in advanced. If it doesn’t, the seller ideally opens a dispute.

Proposed Flow

  1. After posting bond, before chat opens

    • At the buyer invoice posting phase, UI prompts the buyer to enter a payment‑account ID for every fiat payment enabled if maker, and to choose one and only one if taker:
      • Revolut: revtag
      • Wise: wisetag
      • SEPA: IBAN or initials of account holder (privacy‑friendlier)
      • PIX: initials of account holder??
      • Zelle: initials of account holder??
      • Cash, XMR, USDT, etc. → field can remain blank
    • Each method shows a ✅ when completed; buyer cannot advance until required IDs are filled.
  2. Upon entering chat

    • The declared account ID is automatically posted by the robot:

      Buyer payment account for Revolut: @johnsmith (example)

    • Seller sees a banner:

      Release sats only if fiat arrives from the exact account above. Otherwise open a dispute immediately without releasing the sats.

Benefits

  • Raises scammer’s cost— they must control a matching account before taking the order. In my experience as coordinator, while this might not block all attacks, it may prevent many. When such attacks occurs, usually buyer takes his time to procure the triangulated account or create a new bank account with stole IDs.

  • Better protection for sellers—Usually seller is the party more prone to attacks, as he locks the escrow in advance and give up his ID to buyer in advance. With this modification, buyer put some "skin in the game" in advance

Foundation to build later

If we can store the hashes of the buyer ID for payment, we can then imagine a reputation system linked to the IDs based on past trades. Obviously this would open a new world of possibilities but also tradeoffs (i.e. if we can fingerprint users with their ID, privacy would be damaged) worth exploring.

Drawbacks / Open Questions

  • Slightly more complex UI, but should not be too bad?

  • If the buyer’s bank "blocks" payment for whatever reason (common scammer excuse), it must be clear that this falls on buyer responsibility to be in the condition to pay anyway (buyer should check that his account is ok before proceeding to the trade). Maybe better guideline on this are needed on learn.robosats.org . At the same time, I think it is important to limit the collab cancel timeframe. I propose that collab cancel are only possible within 3 hours from the time chat opens. We have too many collab cancels compared to disputes. Ideally we want scammers to be punished more frequently and limiting the timeframe while it is possible to collab cancel can reduce the incentives of scammers to get away too easily.

  • Ideally, coordinator does not get to know buyer ID. Is it possible to hash the information and store it at coordinator, while avoiding mismatch due to the same information being typed in a slightly different form? Or maybe store it as a PGP encrypted message visible by seller PGP public key?

  • For multiple payment methods, taker must choose one method in advance. Let's say possible methods are "Zelle, Revolut, XMR", if he chose XMR the prompt to seller must inform him to not accept Zelle or Revolut .... This might add a lot of complexity to the code, so it might be a good idea to discuss the mechanics further.

  • There are a lot of possible payment methods that can be selected in Robosats. For the time being I would propose to narrow down the ID prompt for: Zelle, Cashapp, Wise, SEPA, PIX, Revolut, Strike, which are the most popular methods.

TempleOfSats avatar Jul 27 '25 01:07 TempleOfSats

Ideally, coordinator does not get to know buyer ID. Is it possible to hash the information and store it at coordinator, while avoiding mismatch due to the same information being typed in a slightly different form? Or maybe store it as a PGP encrypted message visible by seller PGP public key?

I think this can be solved as an initial chat message the client sends prior to the chat room. The user can share it later on as part of the chat history to the Coordinator if a dispute is opened.

The problem is that we can solve this for taking orders because we know the 2 peers, but we can't do that for created orders, @TempleOfSats do you thinks is it fine to do it after the order is taken and prior to the chat room or that's to late?

For multiple payment methods, taker must choose one method in advance. Let's say possible methods are "Zelle, Revolut, XMR", if he chose XMR the prompt to seller must inform him to not accept Zelle or Revolut .... This might add a lot of complexity to the code, so it might be a good idea to discuss the mechanics further.

The chat message can be created with a template, and include there all payment methods. If there are troubles this is going to be resolved by the coordinator manually so there is no need to be estrictly estructured on the content of the message.

Only 2 thoughts to add here:

I think we should start only with Payment Methods we know are problematic and are leabeled as revertible transactions.

We also need to think very well so we communicate this to the seller to avoid scammer to go around this with tricky sentences and social engineering in general.

KoalaSat avatar Jul 27 '25 09:07 KoalaSat

If we can store the hashes of the buyer ID for payment, we can then imagine a reputation system linked to the IDs based on past trades. Obviously this would open a new world of possibilities but also tradeoffs (i.e. if we can fingerprint users with their ID, privacy would be damaged) worth exploring.

I like this idea, let's not forget about this because I agree it's worth exploring

KoalaSat avatar Jul 27 '25 09:07 KoalaSat

The problem is that we can solve this for taking orders because we know the 2 peers, but we can't do that for created orders, @TempleOfSats do you thinks is it fine to do it after the order is taken and prior to the chat room or that's to late?

I was imagining that step to be taken at the same time buyer submit the invoice (after bond is locked / prior to chat).

I think we should start only with Payment Methods we know are problematic and are leabeled as revertible transactions.

We also need to think very well so we communicate this to the seller to avoid scammer to go around this with tricky sentences and social engineering in general.

To be honest I do not have yet a clear idea on what is "reversible". According to many user reports, when Revolut or Wise opens an investigation, the platform often places a temporary freeze on the customer’s assets. In all cases I have heard so far the funds are eventually returned, but some accounts do end up being permanently closed. The only real "reversed" case I have seen so far is PIX.

Again, I admit to not having a clear idea on this, and I hope some users with such experiences step in to contribute with their experiences.

Even if no money is lost, the experience is highly stressful, seeing your account frozen or, worse, shut down can feel like a significant setback and Robosats as a platform is also a victim in this.

In short we can put a warning on PIX, but my understanding is that if we put a warning on Revolut or Wise, we would need to put it in ALL the other fiat payment methods.

@gabbygator184 might have other useful inputs on this topic.

TempleOfSats avatar Jul 27 '25 14:07 TempleOfSats

By requiring the buyer to specify their own payment‑account identifier before entering the trade chat, and automatically showing that ID to the seller, we ask seller to check: if the fiat actually arrive from the account the buyer declared in advanced. If it doesn’t, the seller ideally opens a dispute.

I like the proposal, I think it could effective against triangulation attacks. Not so much against stolen IDs/accounts though, attackers will eventually create the accounts in advance.

If we can store the hashes of the buyer ID for payment, we can then imagine a reputation system linked to the IDs based on past trades.

I don't think this is a good idea. Any identifier that links many trades defeats the purpose of creating a new identity for every trade. I agree it would be great to be able to differentiate between honest and dishonest robots, but not at the cost of all robots' privacy.

Additionally, the rating would depend on the payment method and not the robot, a robot could have many reputations and this could incentivize them to utilize always the same platform for their trades (which could lead to more investigations and freezes).

Perhaps the best way to implement a reputation system is having a different kind of robot whose purpose is to be re-used and whose trade-offs are REALLY clear in the UI and documentation. The robot creation process should default to ephemeral robots and display warnings when switching to persistent ones.

This could help regular traders provide liquidity while keeping a positive track record and incentivize other users to take the orders.

[!Note] Persistent robots could be allowed to choose a name and avatar to differentiate themselves from the rest of the robots, in addition to having a badge/information about the fact they are persistent so the other robots know it.

I think this can be solved as an initial chat message the client sends prior to the chat room. The user can share it later on as part of the chat history to the Coordinator if a dispute is opened.

I second this approach, it would be much easier to implement and keeps the IDs private unless a dispute is open.


Related to this, there should be an additional step in the taker process where it chooses the payment method to be used in the trade (in case there are many). Because otherwise it could put the ID of the payment method A and end up paying through B (which is fraudulent).

aftermath2 avatar Jul 28 '25 18:07 aftermath2

I like the proposal, I think it could effective against triangulation attacks. Not so much against stolen IDs/accounts though, attackers will eventually create the accounts in advance.

For stolen IDs/accounts I have been observing a pattern from a specific malicious user.

He would create several orders as maker at the same time, with several different payment methods. But he wait for the order to be taken before forging the account, and in most cases let taker wait several hours in chat before being able to pay.

Also, and perhaps more importantly, they are sometimes unable to pay from an account and they retry several times from different account until the payment goes through.

The idea is to introduce an extra layer of protection for seller and of possible issues scammers can get caught in.

Not a silver bullet by any means.

I don't think this is a good idea. Any identifier that links many trades defeats the purpose of creating a new identity for every trade. I agree it would be great to be able to differentiate between honest and dishonest robots, but not at the cost of all robots' privacy.

Additionally, the rating would depend on the payment method and not the robot, a robot could have many reputations and this could incentivize them to utilize always the same platform for their trades (which could lead to more investigations and freezes).

Perhaps the best way to implement a reputation system is having a different kind of robot whose purpose is to be re-used and whose trade-offs are REALLY clear in the UI and documentation. The robot creation process should default to ephemeral robots and display warnings when switching to persistent ones.

This could help regular traders provide liquidity while keeping a positive track record and incentivize other users to take the orders.

Yeah, all valid points. Thanks for your contribution! I did not think about the fact that buyer might legitimately want to avoid reusing same payment method in some cases. I also do think we need to be careful about implementing this unless we can somehow find a way that avoid users to be fingerprinted across robots.

I think "buyer reputation system" can come later, first we can discuss on implementing the mechanics of the pre-declaration by buyer, which would alone already be a very aggressive redesign of the trade pipeline.

TempleOfSats avatar Jul 29 '25 01:07 TempleOfSats

Thank everybody for your comments I agree that would be just another way of implementing a too simple reputation system, so let's focus on the first step.

I'm thinking this first check is not really necessary for all payment methods, so maybe we can flag those that are usually used by escammers and enforce the buyer to include the id during the configuration state (right after being taken), and be very explicit explaining the user the reasons for doing so.

KoalaSat avatar Jul 29 '25 07:07 KoalaSat

The idea is to introduce an extra layer of protection for seller and of possible issues scammers can get caught in.

Absolutely, I think it would be great having it. Since the payment ID will be know to the other party earlier or later in the trade.

I think "buyer reputation system" can come later, first we can discuss on implementing the mechanics of the pre-declaration by buyer, which would alone already be a very aggressive redesign of the trade pipeline.

Agreed, we can keep this issue for the fraud prevention mechanism and open a new one for the reputation system.

aftermath2 avatar Jul 29 '25 10:07 aftermath2

I'm thinking this first check is not really necessary for all payment methods, so maybe we can flag those that are usually used by escammers and enforce the buyer to include the id during the configuration state (right after being taken), and be very explicit explaining the user the reasons for doing so.

This is how I see it in practice

Maker side (buyer)

  1. Create buy order
  2. Lock bond
  3. Wait for order to be taken
  4. Input payment ID (if applicable)
  5. Start chat
  6. Post template message including ID in the chat (if applicable)

1 -> Make 2, 4 -> Setup 5, 6 -> Trade

[!Note] The payment ID has to be shared after the order is taken because otherwise we don't know the payment method that will be used.

Taker side (buyer)

  1. Take sell order inputting order amount and payment method (if there are many)
  2. Lock bond
  3. Input payment ID (if applicable)
  4. Start chat
  5. Post template message including ID in the chat (if applicable)

1 -> Take 2, 3 -> Setup 4, 5 -> Trade

aftermath2 avatar Jul 29 '25 10:07 aftermath2

Sounds good, on a perfect world this would be just another step on the process so peers will automatically receive the ids, improving a lot the efficiency and trading experience. Unfortunately the initial implementation didn't take the ability to add extra steps in the middle into consideration and it's not trivial.

I'm not sure about the effort and implications, I need to investigate deeper. Worst case scenario we can just add it as part of the "In chat room" status, but would be really beneficial to make part of the pre-chat steps.

KoalaSat avatar Jul 29 '25 10:07 KoalaSat

Relatively new RS user here and recently got a chargeback (still under investigation).

Besides pre-declaring payment ID, I wanted to mention a couple things that could be useful for the developers.

Similar to the payment ID, what increases costs and deterrence is also a higher bond. Users set their own bonds already, but most leave it to the default 3%. Nothing to implement in code here, other than a clear mention in the docs perhaps.

In the event of a chargeback, defined as a disputed bank transaction (successful or not), it would be of help for the disputed user to show proof that the tx was as legitimate as possible via an obligatory standard payment reference.

Nothing fancy, perhaps something along the lines of: "this tx is legitimate, I, John Doe, confirm to be the sender".

This would help the disputed user a lot in the event of an investigation.


On the topic of reputation and preserving privacy.

Personally, privacy goes out the window for the seller already. Obviously all efforts are done to ensure privacy. But in case giving up even more privacy (reputation-based robots) drastically removes chargeback risks then I'm all for it.

Not everyone would be and that's understandable. What if users can choose? Users could keep their robots and earn points for successful trades with no disputes, to build reputation. For even less chargeback risk, robots can use a whitelist system to track with which robots they already had successful trades.

Some users care more about privacy? Simply re-generate them during every trade. If you re-generate you lose your points and start from zero again.


On another note, the known scammers BTC addresses could be flagged and users who happen to be in a trade with them could be warned about it. Perhaps a bit code-redundant, and more of a suggestion for all users. Got scammed? save the scammer's btc address and crosscheck it with all future traders.

0xf3dz avatar Aug 01 '25 12:08 0xf3dz

On another note, the known scammers BTC addresses could be flagged and users who happen to be in a trade with them could be warned about it. Perhaps a bit code-redundant, and more of a suggestion for all users. Got scammed? save the scammer's btc address and crosscheck it with all future traders.

A coordinator can only know where the payment was sent (a lightning node), there is no BTC address to be flagged. If the scammer received it with a custodial wallet, it is not possible to differentiate him from another user who uses the same wallet.

What if users can choose? Users could keep their robots and earn points for successful trades with no disputes, to build reputation. For even less chargeback risk, robots can use a whitelist system to track with which robots they already had successful trades.

This is the main point of the discussion, but I guess any solution would have its weaknesses. We could create a more generic solution and allow users more freedom to evaluate a robot or an order.

All robots own their own private Nostr key, so there are profiles on Nostr that are not being used. We could allow robots to publish their concluded orders on their Nostr profile using Robosats. It would be important to know if they were buyers or sellers, makers or takers, and maybe the amount and payment methods (i.e., information that allows another person to evaluate that robot/user). This would allow interaction between users after the negotiation while keeping their privacy.

Each order on the Offers tab could redirect the user to the robot's Nostr profile, allowing people to decide whether to take the order based on that information. A profile can be empty or filled with people confirming that the orders were really successful, and users can compare each profile. Someone can use more than one robot and repost the orders on a central profile, people could ask a previous counterpart for a new offer and protect it with a password. In any case, there are several possibilities, which would create a sense of trust and foster a stronger community for growth.

gabbygator184 avatar Aug 01 '25 18:08 gabbygator184

@gabbygator184 Lovely, I think nostr fits perfectly. I created the issue https://github.com/RoboSats/robosats/issues/2138#issue-3285853650 with some thoughts and implementation details, and so we can keep the discussion around the reputation system there and leave this one for the triangulation attack prevention mechanism on certain payment methods.

aftermath2 avatar Aug 02 '25 11:08 aftermath2

Okay let's then move the reputation conversation to that issue, thanks @aftermath2

I was thinking about the problem of setting the payment ID during the trade, but maybe that's not necessary, maybe we can do as Bisq, storing this payment ID as part of user's profile.

Applying this to Robosats, the user might store the hash of the payment ID and the encrypted payment ID as part of the robot (and additionally sent as a nostr note so it can be reused by other coordinators?) . That way we can seamlessly recover in client the ID for the Buyer to send it automatically to the Seller and we can validate it with the hash for the Seller.

For this scenario, we should discuss then what are the conditions to deal with an order if the user didn't have an ID for an specific payment method. Maybe highlight the payment methods not including a hash?

KoalaSat avatar Aug 13 '25 12:08 KoalaSat

I would propose a reputation-based system that adds an additional holding period to prevent charge back scams.

  • Specifically, if someone has opted in (for slightly less privacy) is a trusted buyer/seller, then sats would release immediately as they do now
  • If someone is not a trusted buyer/seller, then a 3 business day waiting period, that way the mismatch of the seller needing to access the ACH system to get his funds out of Revolut or Wise is matched with the ability of a low trust buyer to get the sats
  • By 3 business days, the seller should have mitigated charge back risk by getting money off the platforms, so a charge back strategy would shed the risk from the seller to the platform like rev or wise (unfortunately Wise is sketchy and sheds its own security risks to be liabilities of its users, and this would place the onus back on them)
  • To implement this, you could obviously create a 72 hour lock on the network, or perhaps even a temporary custodial situation for an increased fee to the market maker
  • This trusted system would only apply to custodial wallet payments like wise, rev, cash app, etc. if someone used stable coins or XMR or something like that then there'd be no need as it could remain completely trustless

If I think of other ways to make this better I'll add them, but the main problem I think this system has right now is the mismatch in timing between when someone can get their money off an app versus when a buyer can claim the sats, so solving for that would make it work as intended.

jp244btc avatar Oct 02 '25 02:10 jp244btc