CAP: 0013
Title: Change Trustlines to Balances
Author: Dan Robinson
Status: Draft
Created: 2018-11-14
Discussion: https://github.com/stellar/stellar-protocol/pull/213
Protocol version: TBD
This proposal would rename trustlines to "balances", and would add operations allowing any account to add a balance to any other account (as long as they also send the base reserve
lumens to support that newly added balance), and to remove any of its own balances (including ones where the issuer has frozen the balance). It also adds an ALLOW_ADD_BALANCE flag to accounts, which, if unset, means that AddBalance operations that set that account as the destination
will fail.
This proposal would bring the behavior of Stellar assets and accounts somewhat closer to the behavior of ERC20 tokens on Ethereum, where, by default, any asset can be sent to any user without permission. Under these principles, any asset-specific differentiatxion from these rules should be enforced by the asset issuer, via the AUTHORIZATION_REQUIRED flag (or other flags we may introduce, such as co-signed assets or immutable accounts). Any account-specific differentiation should be enforced by the ALLOW_ADD_BALANCE flag.
This makes it easier for an issuer, exchange, or other service provider to send new assets to users without any interaction from that user. SEP-0013 is an alternative partial solution to this problem that does not involve protocol changes.
The RemoveBalance operation also fixes some quirks in how the existing protocol handles merging accounts. Right now, it is impossible to presign or preauthorize transactions that will reliably merge an account into another account, because there is no way to reliably remove trustlines (since a ChangeTrust operation to remove a trustline can be foiled by anyone else sending you the asset) or merge accounts that still have trustlines. Additionally, in the current protocol, any issuer with which you have a trustline can make it impossible to merge your account, simply by freezing that asset. This would prevent you from recovering the 2*base reserve
XLM for the account as well as the 1*base reserve
XLM for that asset. (If we end up rejecting this proposal, we could create a new proposal that would solve these issues in a different way.)
Rename "trustline" to "balance" in the documentation, internal implementations, and newly created operations. Horizon's API already uses "Balances" to refer to trustlines. Any external APIs that currently use the term "Trustline" or "Lines" (particularly including the ChangeTrust and AllowTrust ops) should not be changed.
The concept of limits on balances is deprecated, and we clearly communicate our intention to remove it in the future (in favor of all Balances having the "max" limit).
The Change Trust operation is deprecated. Removing it from the protocol (even years after being deprecated) may not be worth the potential cost, but we should clearly discourage its use, and encourage users to use AddBalance even for adding balances to their own accounts. (To make this easier, SDKs could set the destination
on AddBalance to be sourceAccount
by default, if no destination is provided.)
struct AddBalanceOp
{
Asset asset;
AccountID destination;
};
If destination
does not have a balance for asset
, the operation transfers base_reserve XLM from sourceAccount
to destination
(unless sourceAccount
and destination
are the same), and adds a balance for asset
to destination
.
If asset
has the AUTHORIZATION_REQUIRED flag, the trustline's authorized flag is initialized to false.
If destination
already has a balance for asset
, this operation does nothing.
If destination
has the ALLOW_ADD_BALANCE flag set to false, the operation fails.
struct AddBalanceOp
{
Asset asset;
};
Removes the asset
balance from sourceAccount
, sending any tokens stored in that balance to the issuer (i.e., burning them).
If there is no balance for asset
on sourceAccount
, this operation does nothing.
If there is a balance, this operation works regardless of whether the balance has the authorized
flag set.
This (unlike ChangeTrust) allows an account to successfully remove a balance even if the issuer has frozen it or if some third party has unexpectedly sent some tokens to it, thus fixing two of the warts in the current protocol.
This account flag, if set to false, prevents the AddBalance operation from adding balances to the account.
This flag is set to true on accounts that are created after the protocol change takes effect. It is set to false on accounts that already existed before the protocol change takes effect.
This flag is necessary for some special cases because otherwise, when merging an account, any other user would be able to cause the merge to fail by using AddBalance to add some balance to your account. Wallets can use this flag to stop new balances from being added to an account, which gives them an opportunity to remove all existing balances with RemoveBalance before merging the account. This flag can also be set to false when an account is initially created, if that account will be used in any deterministic protocols that rely on AccountMerge working successfully.
The ability to add balances to other users' accounts is a significant conceptual change in the protocol.
Wallet software will have to be changed to correctly notice third-party addition of new balances to the account. Any lumen-only wallet (which previously was assured that the account it managed would not receive unexpected assets) will have to make a choice whether to support additional assets, or just ignore any incoming payments of other assets. Any wallets that fully support the AccountMerge operation will need to add support for locking the account and removing any stray balances before merging the account.
Any protocol that relies on the deterministic behavior of AccountMerge will need to be changed. One such protocol is Starlight, which currently merges the channel accounts into a wallet account as the last step of the protocol, but we have already decided to remove AccountMerge from that protocol, in favor of setting the options on the channel accounts to give the recipient control over them. I am not aware of any other protocols that use AccountMerge (and it would be unwise for them to do so in most cases, since AccountMerge can already be caused to fail by the issuers of any assets that have trustlines on that account). Setting the ALLOW_ADD_BALANCE flag to false on all existing accounts should also reduce any compatibility issues caused by this change.
I can't currently think of other ways that these changes could upset reasonable expectations, but the community might raise some.
This proposal previously skipped the ALLOW_ADD_BALANCE change, and would have changed the behavior of AccountMerge so that non-lumen balances were merged as well. However, it was pointed out that the change to AccountMerge would mean that a single AccountMerge operation could have up to ~N effects (where N is the number of assets on that account), which is undesirable behavior for denial-of-service reasons.
SEP-0013, as mentioned above, is a potential solution to some of the same problems that does not involve protocol changes.
If we decide not to make protocol changes to allow adding balances, we still might want to add the RemoveBalance operation (which works unconditionally) in order to allow accounts to be merged predictably, and to prevent an issuer with which you have a trustline from preventing you from ever merging your account.