SEP: 0008
Title: Regulated Assets
Author: Interstellar.com
Status: Final
Created: 2018-08-22
Version 1.0.0
Regulated Assets provide ecosystem support for assets that require an issuer’s approval (or a delegated third party’s approval, such as a licensed securities exchange) on a per-transaction basis. It standardizes the identification of such assets as well as defines the protocol for performing compliance checks and requesting issuer approval.
Target Audience: Asset issuers, issuance platforms, wallet developers, and exchanges
Stellar aims to be an ideal platform for issuing securities. As such, it must provide tools to comply with various regulatory requirements. Regulation often requires asset issuers to monitor and approve every transaction involving the issued asset and to enforce an assortment of constraints. This SEP provides support for these requirements.
Implementing a Regulated Asset consists of these parts:
- Stellar.toml: Issuers will advertise the existence of an Approval Service and the approval criteria via their stellar.toml file.
- Approval Server: HTTP protocol for transaction signing.
- Account Setup: Wallets will have to work with accounts that are controlled or at least partially controlled (via multisig) by asset issuers, rather than the wallet end user.
Note: this step may not be required once the proposed protocol change allowing for protocol-level per-transaction approval is implemented.
- User creates and signs a transaction.
- Wallet resolves asset information and detects that it's a regulated asset.
- Wallet sends the transaction to the approval server.
- Approval server determines whether the transaction is compliant based on the current state of the ledger, known pending transactions, and its compliance ruleset.
- Wallet handles approval response:
- Success? Transaction has been approved and signed by issuer. Submit to Horizon.
- Revised? Transaction has been revised to be made compliant, and signed by the issuer. Wallet will show the changes to the user and ask them to sign the new transaction. Submit to Horizon once signed.
- Pending? The issuer will need to asynchronously approve this transaction. Wallet should send the same transaction to the approval service after a specified timeout (Return to 3).
- Action Required? Transaction requires a user action to be completed. Wallet will present the attached action url as a clickable link, along with the attached message and an option to resubmit once the action has been taken.
- Rejected? Wallet should display given error message to the user.
Issuers will advertise the existence of an Approval Service through their stellar.toml file. This is done in the [[CURRENCIES]] section as different assets can have different requirements.
regulated
is a boolean indicating whether or not this is a regulated asset. If missing,false
is assumed.approval_server
is the url of an approval service that signs validated transactions.approval_criteria
is a human readable string that explains the issuer's requirements for approving transactions.
[[CURRENCIES]]
code="GOAT"
issuer="GD5T6IPRNCKFOHQWT264YPKOZAWUMMZOLZBJ6BNQMUGPWGRLBK3U7ZNP"
regulated=true
approval_server="https://goat.io/tx_approve"
approval_criteria="The goat approval server will ensure that transactions are compliant with NFO regulation"
The transaction approval server receives a signed transaction, checks for compliance and signs if possible.
- Success: Transaction was found compliant and signed by service.
- Revised: Transaction was modified to be compliant and signed by service. It should be re-signed by the client.
- Pending: The issuer will asynchronously validate the transaction and respond later.
- Action Required: The user must complete an action in order to have the transaction approved.
- Rejected: Transaction was rejected.
Transaction approval requests are executed by submitting an HTTP POST
to approval_server
with Content-Type=application/x-www-form-urlencoded
and a single tx
parameter. tx
value is a base64 encoded Transaction Envelope XDR signed by the user. This is the transaction that will be tested for compliance and signed if possible.
HTTP responses have an application/json
encoded body. All responses will contain, at least, a top level status
parameter that indicates the type of the result.
A Successful response will have a 200
HTTP status code and success
as the status
value. This response means that the transaction was found compliant and signed.
Parameters:
Name | Data Type | Description |
---|---|---|
status | string | "success" |
tx | string | Transaction Envelope XDR, Base64 encoded. This transaction will have both the original signature(s) from the request, as well as an additional issuer signature. |
message | string | A human readable string containing information to pass on to the user (optional). |
A Revised response will have a 200
HTTP status code and revised
as the status
value. It means that the transaction was revised to be made compliant. The user should examine and resign the transaction.
Parameters:
Name | Data Type | Description |
---|---|---|
status | string | "revised" |
tx | string | Transaction Envelope XDR, Base64 encoded. This transaction is a revised compliant version of the original request transation, signed by the issuer. |
message | string | A human readable string explaining the modifications made to the transaction to make it compliant. |
A Pending response will have a 200
HTTP status code and pending
as the status
value. It means that the issuer needs to asynchronously validate the transaction. The user should resubmit the transaction after a given timeout.
Parameters:
Name | Data Type | Description |
---|---|---|
status | string | "pending" |
timeout | integer | Number of milliseconds to wait before submitting the same transaction again. |
message | string | A human readable string containing information to pass on to the user (optional). |
An Action Required response will have a 200
HTTP status code and action_required
as the status
value. It means that the user must complete an action before this transaction can be approved. The approval service will provide a URL that facilitates the action. Upon completion, the user will resubmit the transaction.
Parameters:
Name | Data Type | Description |
---|---|---|
status | string | "action_required" |
message | string | A human readable string containing information regarding the action required. |
action_url | string | A URL that allows the user to complete the actions required to have the transaction approved. |
A Rejected response will have a 400
HTTP status code and rejected
as the status
value. It means that the transaction is not compliant and could not be revised to be made compliant.
Parameters:
Name | Data Type | Description |
---|---|---|
status | string | "rejected" |
error | string | A human readable string explaining why the transaction is not compliant and could not be made compliant. |
- If a transaction was revised, ALWAYS explain the changes that were made to a transaction through the
message
parameter. - Core operations shouldn't be modified as that can be confusing and misleading. For example, if the user wishes to put an offer for 1000 GOATS but due to velocity limits they can only put an offer for 500 GOATS, it is better to error with a message than to change the amount.
- Adding an upper timebound to a transaction can help the issuer ensure that their view of the world does not get out of sync.
- Issuers can enforce additional fees by adding additional operations. For example, any transaction involving goats, will also send 0.1 GOAT to Boris’ account.
- Once a transaction has been signed, the issuer should mark it as pending and take it into account, as long as it hasn’t been timed out, so that they can have a accurate view of the world.
Implementing Regulated Assets requires the participating accounts to be “managed” by the issuer. This is achieved by having the issuer be a co-signer on the account, such that a medium threshold operation cannot be submitted without the issuer’s approval.
In the future, this requirement can be replaced by introducing protocol level CoSigned assets.
Ideally, no. Implementing Regulated Assets should only be used when absolutely necessary, such as for regulatory reasons. It comes with a substantial operational overhead, added complexity, and burden for users. Issuers should only go down this route if it is absolutely required. Alternatively, some other available options are to utilize SEP006 in order to perform KYC on deposit and withdraw, and/or use AUTHORIZATION_REQUIRED which allows issuers to whitelist specific accounts to hold their issued assets.
- Separation of concerns between signing transactions and submitting them.
- Transactions might require more signatures from further regulated asset issuers.