Skip to content

Latest commit

 

History

History
743 lines (623 loc) · 28.9 KB

cap-0035.md

File metadata and controls

743 lines (623 loc) · 28.9 KB

CAP-0035: Asset Clawback

Preamble

CAP: 0035
Title: Asset Clawback
Working Group:
    Owner: Tomer Weller <@tomerweller>
    Authors: Dan Doney (Securrency, Inc.), Tomer Weller <@tomerweller>, Leigh McCulloch <@leighmcculloch>, Siddharth Suresh <@sisuresh>
    Consulted: Nicolas Barry <@MonsieurNicolas>, Jon Jove <@jonjove>, Eric Saunders <@ire-and-curses>
Status: Final
Created: 2020-12-14
Discussion: https://groups.google.com/g/stellar-dev/c/hPhkXhrl5-Y/m/ZF6eJcqKAgAJ
Protocol version: 17

Simple Summary

This proposal provides the Issuer with a means to clawback (and reissue if desired) assets in order to support regulatory requirements. This function can be used to:

  1. recover assets that have been fraudulently obtained
  2. respond to regulatory actions, if required
  3. enable identity proofed persons to recover an enabled asset in the event of loss of key custody or theft.

The proposal does not involve shared custody of the person’s account and does not affect custody of bearer assets in the persons account.

Working Group

This protocol change was initially authored by Dan Doney and Tomer Weller. The working group include other authors and the consulted persons include key individuals familiar with the implementation of the core protocol and maintainers of Horizon and its SDKs.

Motivation

In order to meet securities regulatory requirements in many jurisdictions globally, the issuer (or designated transfer agent) must be able to demonstrate the ability to revoke assets in the event of a mistaken or fraudulent transaction or other regulatory action regarding a specific person or asset wide. To receive approval, the Issuer must demonstrate the ability to perform this action with or without the permission of the affected person. Unlike approaches that involve multiple signatures on the person’s wallet (brokerage clawback), this approach does not compromise the custody of other assets in the person’s wallet. Additionally, this approach is an improvement over an approach that invalidates the trustline. While trustline invalidation freezes assets, tokens (asset shares) remain in circulation compromising accounting models. The approach has other benefits to owners of the affected asset including the ability to recover assets if wallet custody is lost including the important business continuity mitigations in the loss of control of custodial or omnibus account. Ex: https://www.ccn.com/190m-gone-how-canada-biggest-bitcoin-exchange-lost-it/

Goals Alignment

This CAP is aligned with the following Stellar Network Goals:

  • The Stellar Network should be secure and reliable.

  • The Stellar Network should enable cross-border payments, i.e. payments via exchange of assets, throughout the globe, enabling users to make payments between assets in a manner that is fast, cheap, and highly usable.

Abstract

This proposal introduces new operations ClawbackOp, ClawbackClaimableBalanceOp, and SetTrustLineFlagsOp, a new account flag AUTH_CLAWBACK_ENABLED_FLAG, a new trustline flag TRUSTLINE_CLAWBACK_ENABLED_FLAG, and a new claimable balance flag CLAIMABLE_BALANCE_CLAWBACK_ENABLED_FLAG.

The AUTH_CLAWBACK_ENABLED_FLAG flag on the issuing account must be set when a trustline is created to authorize a ClawbackOp operation submitted by the issuer account.

A claimable balance inherits its clawback enabled status from the account creating the claimable balance. A ClawbackClaimableBalanceOp operation is valid for claimable balances created by accounts whose trustline for the asset has clawback enabled, and for claimable balances created by an issuer account when the issuer account has clawback enabled.

The ClawbackOp and ClawbackClaimableBalanceOp operations result in the removal of the specified assets issued from the network.

The ClawbackOp and ClawbackClaimableBalanceOp operations only apply to assets issued by the source account. Assets that can be clawed back are easily distinguished from traditional blockchain assets (bearer instruments) so that asset owners are aware of rights.

The ClawbackOp may result in revocation of some or all of the specified assets from the designated account based on the amount provided in the operation.

The SetTrustLineFlagsOp allows the user to set and clear specific trustline flags. This operation can be used to unset TRUSTLINE_CLAWBACK_ENABLED_FLAG.

Specification

XDR changes

This patch of XDR changes is based on the XDR files in tag/commit v15.1.0 (90b2780584c6390207bf09291212d606896ce9f8) of stellar-core.

diff --git a/src/xdr/Stellar-ledger-entries.x b/src/xdr/Stellar-ledger-entries.x
index 8d7463915..26ff33d43 100644
--- a/src/xdr/Stellar-ledger-entries.x
+++ b/src/xdr/Stellar-ledger-entries.x
@@ -28,6 +28,17 @@ enum AssetType
     ASSET_TYPE_CREDIT_ALPHANUM12 = 2
 };
 
+union AssetCode switch (AssetType type)
+{
+case ASSET_TYPE_CREDIT_ALPHANUM4:
+    AssetCode4 assetCode4;
+
+case ASSET_TYPE_CREDIT_ALPHANUM12:
+    AssetCode12 assetCode12;
+
+    // add other asset types here in the future
+};
+
 union Asset switch (AssetType type)
 {
 case ASSET_TYPE_NATIVE: // Not credit
@@ -99,11 +110,16 @@ enum AccountFlags
     // otherwise, authorization cannot be revoked
     AUTH_REVOCABLE_FLAG = 0x2,
     // Once set, causes all AUTH_* flags to be read-only
-    AUTH_IMMUTABLE_FLAG = 0x4
+    AUTH_IMMUTABLE_FLAG = 0x4,
+    // Trustlines are created with clawback enabled set to "true",
+    // and claimable balances created from those trustlines are created
+    // with clawback enabled set to "true"
+    AUTH_CLAWBACK_ENABLED_FLAG = 0x8
 };
 
 // mask for all valid flags
 const MASK_ACCOUNT_FLAGS = 0x7;
+const MASK_ACCOUNT_FLAGS_V16 = 0xF;
 
 // maximum number of signers
 const MAX_SIGNERS = 20;
@@ -187,12 +203,16 @@ enum TrustLineFlags
     AUTHORIZED_FLAG = 1,
     // issuer has authorized account to maintain and reduce liabilities for its
     // credit
-    AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG = 2
+    AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG = 2,
+    // issuer has specified that it may clawback its credit, and that claimable
+    // balances created with its credit may also be clawed back
+    TRUSTLINE_CLAWBACK_ENABLED_FLAG = 4
 };
 
 // mask for all trustline flags
 const MASK_TRUSTLINE_FLAGS = 1;
 const MASK_TRUSTLINE_FLAGS_V13 = 3;
+const MASK_TRUSTLINE_FLAGS_V16 = 7;
 
 struct TrustLineEntry
 {
@@ -337,6 +357,27 @@ case CLAIMABLE_BALANCE_ID_TYPE_V0:
     Hash v0;
 };
 
+enum ClaimableBalanceFlags
+{
+    // If set, the issuer account of the asset held by the claimable balance may
+    // clawback the claimable balance
+    CLAIMABLE_BALANCE_CLAWBACK_ENABLED_FLAG = 0x1
+};
+
+const MASK_CLAIMABLE_BALANCE_FLAGS = 0x1;
+
+struct ClaimableBalanceEntryExtensionV1
+{
+    union switch (int v)
+    {
+    case 0:
+        void;
+    }
+    ext;
+
+    uint32 flags; // see ClaimableBalanceFlags
+};
+
 struct ClaimableBalanceEntry
 {
     // Unique identifier for this ClaimableBalanceEntry
@@ -356,6 +397,8 @@ struct ClaimableBalanceEntry
     {
     case 0:
         void;
+    case 1:
+        ClaimableBalanceEntryExtensionV1 v1;
     }
     ext;
 };
diff --git a/src/xdr/Stellar-transaction.x b/src/xdr/Stellar-transaction.x
index 7f08d7579..3c2b1f0be 100644
--- a/src/xdr/Stellar-transaction.x
+++ b/src/xdr/Stellar-transaction.x
@@ -46,7 +46,10 @@ enum OperationType
     CLAIM_CLAIMABLE_BALANCE = 15,
     BEGIN_SPONSORING_FUTURE_RESERVES = 16,
     END_SPONSORING_FUTURE_RESERVES = 17,
-    REVOKE_SPONSORSHIP = 18
+    REVOKE_SPONSORSHIP = 18,
+    CLAWBACK = 19,
+    CLAWBACK_CLAIMABLE_BALANCE = 20,
+    SET_TRUST_LINE_FLAGS = 21
 };
 
 /* CreateAccount
@@ -236,20 +239,9 @@ struct ChangeTrustOp
 struct AllowTrustOp
 {
     AccountID trustor;
-    union switch (AssetType type)
-    {
-    // ASSET_TYPE_NATIVE is not allowed
-    case ASSET_TYPE_CREDIT_ALPHANUM4:
-        AssetCode4 assetCode4;
-
-    case ASSET_TYPE_CREDIT_ALPHANUM12:
-        AssetCode12 assetCode12;
+    AssetCode asset;
 
-        // add other asset types here in the future
-    }
-    asset;
-
-    // 0, or any bitwise combination of TrustLineFlags
+    // 0, or any bitwise combination of the AUTHORIZED_* flags of TrustLineFlags
     uint32 authorize;
 };
 
@@ -376,6 +368,48 @@ case REVOKE_SPONSORSHIP_SIGNER:
     signer;
 };
 
+/* Claws back an amount of an asset from an account
+
+    Threshold: med
+
+    Result: ClawbackResult
+*/
+struct ClawbackOp
+{
+    Asset asset;
+    MuxedAccount from;
+    int64 amount;
+};
+
+/* Claws back a claimable balance
+
+    Threshold: med
+
+    Result: ClawbackClaimableBalanceResult
+*/
+struct ClawbackClaimableBalanceOp
+{
+    ClaimableBalanceID balanceID;
+};
+
+/* SetTrustLineFlagsOp
+
+   Updates the flags of an existing trust line.
+   This is called by the issuer of the related asset.
+
+   Threshold: low
+
+   Result: SetTrustLineFlagsResult
+*/
+struct SetTrustLineFlagsOp
+{
+    AccountID trustor;
+    Asset asset;
+
+    uint32 clearFlags; // which flags to clear
+    uint32 setFlags;   // which flags to set
+};
+
 /* An operation is the lowest unit of work that a transaction does */
 struct Operation
 {
@@ -424,6 +458,12 @@ struct Operation
         void;
     case REVOKE_SPONSORSHIP:
         RevokeSponsorshipOp revokeSponsorshipOp;
+    case CLAWBACK:
+        ClawbackOp clawbackOp;
+    case CLAWBACK_CLAIMABLE_BALANCE:
+        ClawbackClaimableBalanceOp clawbackClaimableBalanceOp;
+    case SET_TRUST_LINE_FLAGS:
+        SetTrustLineFlagsOp setTrustLineFlagsOp;
     }
     body;
 };
@@ -868,7 +908,8 @@ enum SetOptionsResultCode
     SET_OPTIONS_UNKNOWN_FLAG = -6,           // can't set an unknown flag
     SET_OPTIONS_THRESHOLD_OUT_OF_RANGE = -7, // bad value for weight/threshold
     SET_OPTIONS_BAD_SIGNER = -8,             // signer cannot be masterkey
-    SET_OPTIONS_INVALID_HOME_DOMAIN = -9     // malformed home domain
+    SET_OPTIONS_INVALID_HOME_DOMAIN = -9,     // malformed home domain
+    SET_OPTIONS_AUTH_REVOCABLE_REQUIRED = -10 // auth revocable is required for clawback
 };
 
 union SetOptionsResult switch (SetOptionsResultCode code)
@@ -1120,6 +1161,71 @@ default:
     void;
 };
 
+/******* Clawback Result ********/
+
+enum ClawbackResultCode
+{
+    // codes considered as "success" for the operation
+    CLAWBACK_SUCCESS = 0,
+
+    // codes considered as "failure" for the operation
+    CLAWBACK_MALFORMED = -1,
+    CLAWBACK_NOT_CLAWBACK_ENABLED = -2,
+    CLAWBACK_NO_TRUST = -3,
+    CLAWBACK_UNDERFUNDED = -4
+};
+
+union ClawbackResult switch (ClawbackResultCode code)
+{
+case CLAWBACK_SUCCESS:
+    void;
+default:
+    void;
+};
+
+/******* ClawbackClaimableBalance Result ********/
+
+enum ClawbackClaimableBalanceResultCode
+{
+    // codes considered as "success" for the operation
+    CLAWBACK_CLAIMABLE_BALANCE_SUCCESS = 0,
+
+    // codes considered as "failure" for the operation
+    CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST = -1,
+    CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER = -2,
+    CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED = -3
+};
+
+union ClawbackClaimableBalanceResult switch (ClawbackClaimableBalanceResultCode code)
+{
+case CLAWBACK_CLAIMABLE_BALANCE_SUCCESS:
+    void;
+default:
+    void;
+};
+
+/******* SetTrustLineFlags Result ********/
+
+enum SetTrustLineFlagsResultCode
+{
+    // codes considered as "success" for the operation
+    SET_TRUST_LINE_FLAGS_SUCCESS = 0,
+
+    // codes considered as "failure" for the operation
+    SET_TRUST_LINE_FLAGS_MALFORMED = -1,
+    SET_TRUST_LINE_FLAGS_NO_TRUST_LINE = -2,
+    SET_TRUST_LINE_FLAGS_CANT_REVOKE = -3,
+    SET_TRUST_LINE_FLAGS_INVALID_STATE = -4
+};
+
+union SetTrustLineFlagsResult switch (SetTrustLineFlagsResultCode code)
+{
+case SET_TRUST_LINE_FLAGS_SUCCESS:
+    void;
+default:
+    void;
+};
+
 /* High level Operation Result */
 enum OperationResultCode
 {
@@ -1176,6 +1282,12 @@ case opINNER:
         EndSponsoringFutureReservesResult endSponsoringFutureReservesResult;
     case REVOKE_SPONSORSHIP:
         RevokeSponsorshipResult revokeSponsorshipResult;
+    case CLAWBACK:
+        ClawbackResult clawbackResult;
+    case CLAWBACK_CLAIMABLE_BALANCE:
+        ClawbackClaimableBalanceResult clawbackClaimableBalanceResult;
+    case SET_TRUST_LINE_FLAGS:
+        SetTrustLineFlagsResult setTrustLineFlagsResult;
     }
     tr;
 default:

Semantics

Clawback operates similar to auth revocation in that it takes an amount of the asset out of active circulation by preventing the account from using it on the network. Auth revocation freezes the full balance of an asset in an account, but clawback provides fine grain control and allows the issuer to take out of the account and destroy a specific amount of the asset.

In order to execute a clawback of an amount in an account, an issuer account must have its AUTH_CLAWBACK_ENABLED_FLAG flag set when the account holding the asset created its trustline. The issuer submits a ClawbackOp operation specifying the from account containing the asset to be clawed back. This operation does not require the affected account’s signature. The transaction results in a change in balance to the recipient’s account. The amount of the asset clawed back is burned and is not sent to any other address. The issuer may reissue the asset to the same account or to another account if the intent of the clawback is to move the asset to another account.

If an issuer wishes to set AUTH_CLAWBACK_ENABLED_FLAG, it must also have AUTH_REVOCABLE_FLAG set.

In order to execute a clawback of a claimable balance, the claimable balance must have been created by an account that has clawback enabled on its trustline.

In order to execute a clawback of a claimable balance created by an issuer account, the claimable balance must have been created when clawback was enabled on the issuer account.

Account

This proposal introduces a new flag to accounts, AUTH_CLAWBACK_ENABLED_FLAG. When the flag is set, trustlines created to the account inherit the flag and the balances within those trustlines may be clawed back by the issuer.

An account may set or unset the flag using the existing SetOptionsOp operation, unless the AUTH_IMMUTABLE_FLAG flag is set, in the same way that existing AUTH_* flags may be set or unset unless the immutable flag is set.

Trustline

This proposal introduces a new flag to trustlines, TRUSTLINE_CLAWBACK_ENABLED_FLAG, that is set at the time the trustline is created if the issuer account of the asset of the trustline has its AUTH_CLAWBACK_ENABLED_FLAG flag set.

If the new flag is set it indicates that the balance held by the trustline can be clawed back by the issuer using the ClawbackOp, and that any claimable balance created by the account will also be clawback enabled.

Claimable Balance

This proposal introduces the first flag to claimable balances, CLAIMABLE_BALANCE_CLAWBACK_ENABLED_FLAG.

The CLAIMABLE_BALANCE_CLAWBACK_ENABLED_FLAG flag is set at the time the claimable balance is created if the account creating the claimable balance has TRUSTLINE_CLAWBACK_ENABLED_FLAG set on the trustline of the asset of the claimable balance.

If an issuer account creates a claimable balance for an asset it issues, the CLAIMABLE_BALANCE_CLAWBACK_ENABLED_FLAG flag is set at the time the claimable balance is created if the issuer account creating the claimable balance has AUTH_CLAWBACK_ENABLED set.

If the new flag is set it indicates that the balance held by the claimable balance can be clawed back by the issuer using the ClawbackClaimableBalanceOp.

Allow Trust Operation

This proposal introduces no changes to the AllowTrustOp operation XDR, but the operation will not accept the TRUSTLINE_CLAWBACK_ENABLED_FLAG as a valid flag that it will operate. The definition of what flags the operation supports will be limited to AUTHORIZED_* flags. When applying new flags to accounts the operation will not change the TRUSTLINE_CLAWBACK_ENABLED_FLAG.

If an AllowTrustOp operation is submitted with the TRUSTLINE_CLAWBACK_ENABLED_FLAG set, the operation will fail with the existing result code ALLOW_TRUST_MALFORMED.

Set Options Operation

This proposal introduces a new result code to the SetOptionsOp operation XDR, which will be returned if AUTH_REVOCABLE_FLAG flag is not set whenever the AUTH_CLAWBACK_ENABLED_FLAG flag is set.

This introduces a failing result in these cases:

  1. Setting only AUTH_CLAWBACK_ENABLED_FLAG without AUTH_REVOCABLE_FLAG already set will result in SET_OPTIONS_AUTH_REVOCABLE_REQUIRED.
  2. Clearing AUTH_REVOCABLE_FLAG while AUTH_CLAWBACK_ENABLED_FLAG is set will result in SET_OPTIONS_AUTH_REVOCABLE_REQUIRED.

Clawback Operation

This proposal introduces the ClawbackOp operation. The ClawbackOp operation reduces the balance of the asset in the account by the specified amount of the specific asset from the from account, returning it to the issuer account, burning it.

Similar to other operations the clawback operation will fail if the account balance is less than the amount specified when accounting for selling liabilities. If clawback is required of asset amounts locked up with selling liabilities then the issuer may use the AllowTrustOp operation to revoke authorization of the trustline, which will cancel any existing ledger entries creating selling liabilities, such as offers, and issue the ClawbackOp in the same transaction. If the issuer wishes to allow the from account to continue utilizing the asset it can include another AllowTrustOp after the ClawbackOp to authorize the account once again.

The clawback operation requires a medium threshold signature to authorize the operation.

CLAWBACK_MALFORMED will be returned for ClawbackOp during validation under the following conditions:

  • asset is native.
  • asset value is invalid.
  • asset.issuer != source account
  • amount is < 1.
  • from == source account

Possible return values for the ClawbackOp during application are:

  • CLAWBACK_SUCCESS if the clawback is successful.
  • CLAWBACK_NOT_CLAWBACK_ENABLED if the TRUSTLINE_CLAWBACK_ENABLED_FLAG is not set.
  • CLAWBACK_NO_TRUST if the from account does not have a trustline for asset.
  • CLAWBACK_UNDERFUNDED if the from account does not have sufficient available balance of asset after accounting for selling liabilities.

Clawback Claimable Balance Operation

This proposal introduces the ClawbackClaimableBalanceOp operation. The ClawbackClaimableBalanceOp operation destroys a claimable balance, returning the asset to the issuer account, burning it.

The operation will only succeed if the claimable balance has its CLAIMABLE_BALANCE_CLAWBACK_ENABLED_FLAG set.

The operation source account must be the issuer account of the asset held in the claimable balance.

The operation requires a medium threshold signature to authorize the operation.

The operation introduces no new or unique behavior to how sponsored reserves function. When the operation applies, removing the claimable balance ledger entry, the reserve held in sponsorship will be freed for the sponsor, in the same way it is freed when any sponsored ledger entry is removed.

ClawbackClaimableBalanceOp is always valid.

Possible return values for the ClawbackClaimableBalanceOp during application are:

  • CLAWBACK_CLAIMABLE_BALANCE_SUCCESS if the clawback is successful.
  • CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST if the claimable balance does not exist.
  • CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER if the source account is the not the issuer of the asset.
  • CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED if the CLAIMABLE_BALANCE_CLAWBACK_ENABLED_FLAG is not set.

Set TrustLine Flags Operation

This proposal introduces the SetTrustLineFlagsOp operation. The operation works like the AllowTrustOp, except it uses set and clear parameters to set/clear specific trustline flags. This will allow an issuer to clear the TRUSTLINE_CLAWBACK_ENABLED_FLAG. An important detail to note here is that SetTrustLineFlagsOp will mimic the changes to AllowTrustOp specified in CAP-0029.

The operation requires a low threshold signature to authorize the operation.

SET_TRUST_LINE_FLAGS_MALFORMED will be returned for SetTrustLineFlagsOp during validation under the following conditions:

  • Both AUTHORIZED_FLAG and AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG are set on setFlags.
  • asset is invalid.
  • asset is ASSET_TYPE_NATIVE.
  • setFlags and clearFlags are modifying the same flags.
  • setFlags or clearFlags are modifying unsupported flags.
  • setFlags has the TRUSTLINE_CLAWBACK_ENABLED_FLAG set.
  • trustor == source account
  • asset.issuer != source account

Possible return values for the SetTrustLineFlagsOp during application are:

  • SET_TRUST_LINE_FLAGS_SUCCESS if the operation is successful.
  • SET_TRUST_LINE_FLAGS_NO_TRUST_LINE if the trustline doesn't exist.
  • SET_TRUST_LINE_FLAGS_CANT_REVOKE if AUTH_REVOCABLE_FLAG is not set on the issuer, but the authorization is downgraded (AUTHORIZED_FLAG -> AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG, AUTHORIZED_FLAG -> 0, or AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG -> 0).
  • SET_TRUST_LINE_FLAGS_INVALID_STATE if the final state of the trustline flag has both AUTHORIZED_FLAG and AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG set.

Design Rationale

In the event of regulatory action, erroneous transaction, or loss of custody, the issuer may conduct a clawback transaction if the appropriate flags are set. In the event of loss of custody, the affected party would need to demonstrate they are the rightful owner of the account (usually through reproofing KYC credentials or otherwise authenticating). On obtaining this proof, the issuer could execute a clawback from the lost account followed by a subsequent payment to a separate account under control of the affected party. Needless to say, executing a reallocation is a significant responsibility and in many cases should be reserved for licensed entities (like a transfer agent) holding the issuer credentials and aware of responsibilities under the law of the jurisdiction of the affected party and asset.

Flags

The account AUTH_CLAWBACK_ENABLED_FLAG flag allows the issuer to indicate that it has control over the use of the asset on the network. By including the flag in account flags, account owners may review the revocability of an asset issued by the issuer and have the choice to avoid this type of asset if they object to the implied trust in the issuer.

The account AUTH_REVOCABLE_FLAG flag must also be set because for clawback to succeed in all cases that an account holds an asset, the issuer must be able to revoke authorization to release any offers creating selling liabilities with the asset. If an issuer enables clawback but not AUTH_REVOCABLE_FLAG it will likely be oversight.

By setting the TRUSTLINE_CLAWBACK_ENABLED_FLAG flag on the trustline, account owners have confidence that the clawback feature may not be enabled if it was not enabled when they created their trustline.

By setting the CLAIMABLE_BALANCE_CLAWBACK_ENABLED_FLAG flag on the claimable balance based on the state of the trustline of the account creating the claimable balance, account owners have confidence that the clawback feature may not be enabled for claimable balances they create if it was not enabled when they created their trustline.

Threshold

The clawback operations require a medium threshold signature because they are changing the balance of accounts and changing the states of claimable balances and is more aligned with impact of a payment operation than an allow trust operation.

SetTrustLineFlagsOp requires a low threshold signature because AllowTrustOp, the other operation that allows one to modify trustline flags, requires a low threshold as well.

Claimable Balances

Claimable balances are immutable and so any functionality to clawback a claimable balance is all or nothing. The clawback feature of claimable balances is proposed with a flag so that it is explicit when a claimable balance can be clawed back. The flag state is inherited from the trustline of the account creating the claimable balance to ensure that the balance controlled by the account holder does not change clawback enabled status when moving between account and claimable balances.

A separate operation is specified to ensure that clawback is transparent and highly visible in comparison to routine claiming of a claimable balance and to allow issuers that use claimable balances routinely to distinguish between claimable balances they can routinely claim and claimable balances they may clawback.

Claimable Balances Created by an Issuer

An issuer account has no trustline to itself for assets it issues, therefore setting the CLAIMABLE_BALANCE_CLAWBACK_ENABLED_FLAG flag based on the state of a trustline is not possible in this case. By setting the CLAIMABLE_BALANCE_CLAWBACK_ENABLED_FLAG flag on the claimable balance based on the state of the issuer account flags when the issuer account creates a claimable balance, the issuer account retains control to specify if claimable balances it creates are clawed back. This is intuitive, but not overly flexible. Issuer accounts that need to create claimable balances with clawback disabled, but need to have clawback enabled for new trustlines, can create claimable balances via a second account that it allows to have a trustline that is clawback disabled.

Allow Trust Operation

The AllowTrustOp is disallowed from operating on the new TRUSTLINE_CLAWBACK_ENABLED_FLAG trustline flag because this operation doesn't have a parameter to set/clear flags. It requires the user to be aware of existing flags, which is an operational burden.

A new operation, SetTrustLineFlagsOp, is proposed in this cap to make trustline flag modification simpler. Additionally the AllowTrustOp operation is semantically intended to change authorization and clawback is outside it's scope.

The AllowTrustOp is deprecated for SetTrustLineFlagsOp.

Set TrustLine Flags Operation

The SetTrustLineFlagsOp will make it easier for issuers to modify trustline flags.

In the context of clawback, an issuer can clear the TRUSTLINE_CLAWBACK_ENABLED_FLAG from a trustline without knowledge of the current state of the other flags. This is not possible with AllowTrustOp because it sets the trustline flags to the value passed in by AllowTrustOp. It is also not possible to add the existing flag to the AllowTrustOp operation without breaking existing users of that operation since they will not be expecting to include the current state of the TRUSTLINE_CLAWBACK_ENABLED_FLAG in the flags field.

Clearing the TRUSTLINE_CLAWBACK_ENABLED_FLAG allows the issuer to create a clawback enabled asset, with a subset of trustlines that are not subject to clawback. The ability to clear flag will also allow an issuer to disable clawback on an asset entirely by removing AUTH_CLAWBACK_ENABLED_FLAG on its own account and clearing TRUSTLINE_CLAWBACK_ENABLED_FLAG from all existing trustlines to that asset.

Asset instead of AssetCode

Both SetTrustLineFlagsOp and ClawbackOp use an Asset as a parameter instead of an AssetCode to defer the decision of who all future authorizers of the operation can be. The Asset includes the issuer account, where-as use of AssetCode would assume the source account is always the issuer account. In this proposal, only the issuer may authorize the operation. This decision makes it possible in a future proposal to expand the accounts that may be allowed to issue the operation.

Protocol Upgrade Transition

Backwards Incompatibilities

The change does not have an affect on previous assets, accounts, or transaction structure. It should not cause a breaking change in existing implementations.

Pre-authorized, pre-signed, or pre-planned transactions that create accounts, and create claimable balances, using assets that become clawback enabled could fail if those transactions did not include the issuer account as a claimant.

The ClawbackOp operation introduced is reversible meaning that their use if reversed has no impact on existing pre-signed or pre-authorized transactions involving the asset and the account that the clawback operates on.

The ClawbackClaimableBalanceOp operation is not reversible meaning that after their use there is no way to recreate the destroyed claimable balance with the same identifier. Pre-signed or pre-authorized transactions that claim the claimable balance will have encoded its identifier. Authors of contracts or systems utilizing pre-signed or pre-authorized transactions can identify that assets may be clawed back by inspecting the flags of the account that will create the claimable balance and the the flags of the issuer to understand if the issuer could enable clawback on new accounts.

Resource Utilization

No substantial changes to resource utilization.

Test Cases

None yet.

Implementation

stellar/stellar-core#2881 stellar/stellar-core#2893 stellar/stellar-core#2900 stellar/stellar-core#2918