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
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:
- recover assets that have been fraudulently obtained
- respond to regulatory actions, if required
- 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.
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.
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/
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.
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
.
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:
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.
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.
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.
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
.
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
.
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:
- Setting only
AUTH_CLAWBACK_ENABLED_FLAG
withoutAUTH_REVOCABLE_FLAG
already set will result inSET_OPTIONS_AUTH_REVOCABLE_REQUIRED
. - Clearing
AUTH_REVOCABLE_FLAG
whileAUTH_CLAWBACK_ENABLED_FLAG
is set will result inSET_OPTIONS_AUTH_REVOCABLE_REQUIRED
.
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 accountamount
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 theTRUSTLINE_CLAWBACK_ENABLED_FLAG
is not set.CLAWBACK_NO_TRUST
if thefrom
account does not have a trustline forasset
.CLAWBACK_UNDERFUNDED
if thefrom
account does not have sufficient available balance ofasset
after accounting for selling liabilities.
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 theasset
.CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED
if theCLAIMABLE_BALANCE_CLAWBACK_ENABLED_FLAG
is not set.
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
andAUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG
are set onsetFlags
. asset
is invalid.asset
isASSET_TYPE_NATIVE
.setFlags
andclearFlags
are modifying the same flags.setFlags
orclearFlags
are modifying unsupported flags.setFlags
has theTRUSTLINE_CLAWBACK_ENABLED_FLAG
set.trustor
== source accountasset.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
ifAUTH_REVOCABLE_FLAG
is not set on the issuer, but the authorization is downgraded (AUTHORIZED_FLAG
->AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG
,AUTHORIZED_FLAG
-> 0, orAUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG
-> 0).SET_TRUST_LINE_FLAGS_INVALID_STATE
if the final state of the trustline flag has bothAUTHORIZED_FLAG
andAUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG
set.
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.
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.
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 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.
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.
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
.
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.
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.
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.
No substantial changes to resource utilization.
None yet.
stellar/stellar-core#2881 stellar/stellar-core#2893 stellar/stellar-core#2900 stellar/stellar-core#2918