[brc-20] Core Function Cleanup Phase 1

This post proposes the integration of a new core function, named “fraction,” into the brc-20 protocol to improve the experience of token transfers for all users. Given that simplicity is the fundamental tenet of the brc-20 standard, the suggestion to introduce an additional core function was made with considerable deliberation and is not intended to become commonplace.

Purpose:

The fraction function is introduced to safeguard against unwanted transfer inscriptions that could disrupt tokens and disrupt a user’s operations.

Problem:

The current brc-20 protocol allows anyone to create transfer inscriptions to any address. Although this accessibility allows for the use of inscription tools, it also opens the door for potentially disruptive actors to fragment users’ balances and interfere with their activities.To date, there has been very little evidence of these “attacks” occurring.

Proposed Solution:

By incorporating the fraction function directly into the brc-20 protocol, specific validity conditions are enforced on transfers. This measure is intended to deter attackers by making it more difficult and costly to execute such annoyances.

Functionality:

The fraction function is intended to be a core part of the brc-20 protocol and is not well-suited for modular implementation. It will set the permissible range for transfer amounts and/or required minimum padding for creating a valid transfer inscription.

Implementation:

An example of the proposed implementation is as follows:

{
  "p": "brc-20",
  "op": "fraction",
  "tick": "ordi",
  "min": "10",
  "max": "10000",
  "pad": "100000"
}

A user can apply this inscription to the address holding the balance they want to limit. After inscribing, they would initiate it by transferring the inscription to their own address. TAs per the given example, this would mandate that all incoming transfer inscriptions (inscribe-transfer) must specify an “amt” within the range of 10 to 10,000, and the padding/postage must exceed 100,000 satoshis.

Validity Conditions:

The fraction function validity conditions and rules:

  1. If min omitted, min = 0.
  2. If max omitted, max = ticker.max.
  3. Pad is not required.
  4. min <= max.
  5. The validity of the minimum and maximum values is not contingent upon the currently available balance and should fall within the 0 to maximum range of the tick.
  6. If the available balance is lower than min, inscribe-transfer cannot be performed. This effectively locks the balance in its available form.
  7. padding > 0.
  8. If the tick has not been deployed, fraction function is invalid.

Usage:

The average user won’t need to use this function. It only impacts the initial stage of the transfer inscription process (inscribe-transfer) and does not influence the subsequent actual transfer of valid inscriptions. Consequently, users who apply the padding condition can remove extra satoshis from the transfer inscription UTXO during the final stage of the transfer. Furthermore, those deploying tokens can utilize the min/max settings for a distribution mechanism resembling an Ethereum-style airdrop experience (claimdrop). This update also aims to foster innovation by providing security for bridges and relay mechanisms.

Alternative Solutions:

Various alternative options were also considered, including requiring the attachment of signatures to transfer inscriptions, requiring the use of a UTXO from a specified address when generating transfer inscriptions, or tracking the satoshis spent from a balance holding wallet. However, these approaches led to complexity, effected user experience, and added new attack vectors. If you have another innovative approach, please share your thoughts in the discussion below.

As this represents the first significant amendment since the protocol’s launch, community feedback on its advantages and possible drawbacks is encouraged. The initial deadline is set for two weeks; however, it may be extended if consensus is not reached within this timeframe. The subsequent phase will address the front-running challenges prevalent in meta-protocols.

6 Likes

Agree with this proposal. While maliciously inscribing transfer inscriptions to disrupt the balance typically doesn’t have a significant impact on individual users, such attacks can pose substantial inconvenience for service providers, such as exchanges and stablecoin issuers. I believe that adding this feature would be beneficial for more businesses to enter the BRC20 ecosystem.

2 Likes

Some additional robustness measures suggested by the Best in Slot team:


  • Apply mathematical notations instead of “within the range of” since border conditions may be misunderstood. Example: min <= amt <= max for inscribe-transfer validity.

  • When a fraction function inscription is transferred to a different wallet, it ought to be deactivated instantly. Moreover, sending this inscription back to the original address should not reactivate it.

  • Inscriptions using the fraction function should become invalid once activated, with only their initial transfer being monitored under the brc20 protocol. Subsequent transfers of these inscriptions should not be recognized as activations, only deactivations (outlined above).

    • For instance, if I inscribe two fraction functions and transfer the first one to myself, its rules should be activated. Similarly, if I then transfer the second inscription to myself, its rules should be enabled. However, if I were to transfer the first inscription to myself again, it should not function, as this would constitute a second movement of the fraction function, beyond the scope of initial activation tracking.
  • The inscription padding should be greater than or equal to the ‘pad’ variable. This can be concisely expressed in mathematical notation as: padding ≥ pad

  • Having a way to reset to default state (no restrictions) is a valuable feature. Achieve this by making all min/max/pad variables explicitly optional. To reset, send a new empty fraction inscription to yourself (must include p op and tick fields).


Considering these recommendations, I think it would be wise to prolong the discussion period until the end of November. This extension will provide all involved parties ample time to thoroughly review the initial proposal as well as the subsequently proposed amendments.

@nand from unisat has proposed an elegant alternative solution. This is it explained in detail:

Background

The “balance sent as fee” rule was implemented as a protective measure against accidental balance spending in ordinal-agnostic applications, a need underscored by recent challenges with OP_RETURN protocol mints. This rule ensures that balances, instead of being transferred to miners as fees, are reverted to the sender’s available balance. This design not only safeguards against unintentional balance expenditure but also facilitates the subsequent solution proposed for addressing spam fractionalization issues.

Proposal

A subtle modification to brc-20 order of operation rules to give priority to the “balance sent as fee” events offers a safeguard against spam fractionalization. The most effective application of this updated rule is in the reveal transaction of a new transfer inscription process, which permits the atomic transformation of a transferable balance from one value to another. While this method can also be applied in commit transactions, its effectiveness may be reduced due to there still being potential for intervention.

Example

For example, a user with a 100 ordi balance in its transferable form can change this to a 50 ordi balance. By using the 100 ordi transfer inscription as a fee in the reveal transaction of a new 50 ordi transfer inscription, this objective is achieved.

Pro/Con

The advantages of this approach include its alignment with brc-20’s core principle of simplicity and minimal intrusion into core functions and indexing. It also offers users complete control over their balance, unlike the fraction proposal which focuses on attack disincentivization.

The main disadvantage is the incompatibility with existing inscription tools. This drawback is somewhat lessened, as this feature is mainly necessary for advanced users.

Summary

In summary, this solution offers an elegant and non-intrusive method to tackle brc-20’s spam fractionalization issue, utilizing a mechanism introduced to protect users from accidentally spending their balances as fees and enabling atomic conversion of transferable balance sizes.

Next Steps

The proposed update, although straightforward in its design, presents a deviation from the fundamental block ordering principle of brc-20 and therefore warrants careful consideration before implementation. Some time must be given to decide the best path forward, whether that be “balance sent as fee”, “fraction”, or a whole different strategy. Please provide any thoughts in the discussion below.

2 Likes

Hello, I am developing BRC20 DEX and I want to suggest the way to solve malicious transfer inscription problem which can cause funds lose.

In most DEX, the swap rate depends on token balance in liquidity pool. Let’s think the scenario that transfer inscription can affect the token balance and liquidity pool is maintained by K = X * Y model.

Let’s think there are 1000 ORDI tokens and 10000 SATS tokens in the liquidity pool.
In normal case, when user sends 1000 ORDI token, then he can receive 5000 SATS token.
But if attacker inscribe transfer inscription with 999 ORDI token amount to the pool, then ORDI token balance can be calculated to 1 ORDI. In this case, if attacker sends 1 ORDI token, then he can receive 5000 SATS like using 1000 ORDI. In other words, attacker can use high swap ratio by inscribe disallowed transfer inscription.
Of course, there can be several mechanism to protect it but some operations can be halt several hours and it needs to send attacker’s inscription to self again.

To solve this, I suggest to change transfer inscription indexing mechanism.
In the current indexing module, if user has 1000 ORDI token and 500 transferable ORDI token, then he can’t inscribe 1000 ORDI transfer inscription himself even his total balance is 1000 ORDI. This problem is occured because token transfer validation check is done when user inscribe transfer inscription.

I think we can do the token transfer validation check when user send transfer inscription. Let’s think user has 1000 ORDI token and 500 and 700 transfer inscription. In this case, indexer doesn’t need to check validation check. When user try to send transfer inscription to others, then indexer can check validation. When user has 1000 ORDI token and if he send 700 transfer inscription, then it can be valid. After user sends 700 transfer inscription, user’s balance is changed to 300 ORDI, so user can’t send 500 transfer inscription. But if user receives 200 ORDI token from others, then he can send 500 transfer inscription.

In normal case, only user inscribes transfer inscription to himself, so there will be no problem. When attacker inscribe transfer inscription to others, user won’t use it so it’s useless.
I just thought my idea and hope to discuss more details if anyone is interested on it.

2 Likes

If I am understanding your proposal correctly, the issue lies with the fact that there would be no onchain event that invalidates an active transfer function. This becomes dangerous as a user could wait for their listed PSBT to be filled in the mempool then simultaneously send it elsewhere causing double spend.

1 Like

I think it’s not the problem. BRC20 token balance is only changed after send inscription confirmation. And BRC20 indexer check inscription one by one and there can’t be double spend problem. Even attacker list PSBT several times on mempool, only the first confirmed PSBT will be available. I hope to hear your opinion.

1 Like

Upgrading the transfer command to rely on UTXO (Unspent Transaction Output) rather than an index server, along with the proposed changes to the BRC20 protocol, can indeed bring several benefits to the system. Here’s a breakdown of the changes and their potential advantages:

Proposed Changes:

  1. Transfer Command Using UTXO:
  • The transfer command will now require a UTXO that was the result of a transfer or mint command.
  • This change ensures that the asset being transferred is indeed owned by the sender and has not been double-spent.
  1. Addition of OP_RETURN Output:
  • Introduce an OP_RETURN output in the transaction to signal to indexers that the following outputs carry a specified amount of the asset (ticker).
  • This change makes it easier for indexers to track asset transfers without parsing entire transaction histories.

Benefits:

  1. Single Transaction Transfers:
  • With the new approach, asset transfers can be completed in a single transaction, simplifying the process and potentially reducing fees.
  1. PSBT Support for Asset Swapping:
  • By using UTXOs for asset transfers, it becomes feasible to swap assets using PSBT (Partially Signed Bitcoin Transactions).
  • This adds a layer of security and flexibility, as transactions can be partially signed and then completed by another party.
  1. Creating Orders via PSBT:
  • Asset holders can create trade orders using PSBT instead of transferring assets to a marketplace.
  • This method allows holders to retain control over their assets until the trade is executed, enhancing security and trust in the marketplace.
1 Like