From 03fd22d412aca78bc0553580a36839f133daa6e3 Mon Sep 17 00:00:00 2001 From: Leigh McCulloch Date: Fri, 28 May 2021 12:39:01 -0700 Subject: [PATCH] CAP-35: Replace CRLF line endings with LF line endings (#952) Replace CRLF line endings with LF line endings. This is the only CAP in the repo that has CRLF line endings. Consistency would make some things easier. Folks on Windows can configure their git to autocrlf as needed for their workflows without introducing CRs upstream. This was discovered in https://github.com/stellar/stellar-protocol/pull/950. --- core/cap-0035.md | 1486 +++++++++++++++++++++++----------------------- 1 file changed, 743 insertions(+), 743 deletions(-) diff --git a/core/cap-0035.md b/core/cap-0035.md index b02028fa1..a9b17dcc8 100644 --- a/core/cap-0035.md +++ b/core/cap-0035.md @@ -1,743 +1,743 @@ -# CAP-0035: Asset Clawback - -## Preamble - -```text -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: Accepted -Created: 2020-12-14 -Discussion: https://groups.google.com/g/stellar-dev/c/hPhkXhrl5-Y/m/ZF6eJcqKAgAJ -Protocol version: TBD -``` - -## 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 -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](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0029.md). - -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 - -https://github.com/stellar/stellar-core/pull/2881 -https://github.com/stellar/stellar-core/pull/2893 -https://github.com/stellar/stellar-core/pull/2900 -https://github.com/stellar/stellar-core/pull/2918 - -[stellar-core]: https://github.com/stellar/stellar-core +# CAP-0035: Asset Clawback + +## Preamble + +```text +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: Accepted +Created: 2020-12-14 +Discussion: https://groups.google.com/g/stellar-dev/c/hPhkXhrl5-Y/m/ZF6eJcqKAgAJ +Protocol version: TBD +``` + +## 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 +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](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0029.md). + +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 + +https://github.com/stellar/stellar-core/pull/2881 +https://github.com/stellar/stellar-core/pull/2893 +https://github.com/stellar/stellar-core/pull/2900 +https://github.com/stellar/stellar-core/pull/2918 + +[stellar-core]: https://github.com/stellar/stellar-core