FinP2P Escrow service provides various capabilities to the FinP2P Network, one of those is the capability to perform safe payment for Securities (Delivery vs Payment) in asset transfer transaction.
The flow is not actual “atomic” in the technical sense, but its a 2-way transaction that ensures that if A transfers an asset to B, B will transfers an asset to A.
For this flow we use a trusted third party entity, the Escrow node, to secure one leg, “The Escrow Leg”, of the transaction. This leg is usually associated with a stable digital representation of a fiat currency, but is not mandatory. The Escrow node will secure the assets from the “Escrow leg”, and will release them based on the outcome of the asset’s transaction leg. The release can have the outcome of moving the assets back to its original owner or to transfer them to the new owner.
The Escrow node holds accounts for each participant in the transaction, or, in some cases only an account for the buyer, while the seller account may be an address on a public blockchain. To secure assets for the escrow leg the Escrow transaction will first validate if the source account has enough balance.
Table of Contents
Out of Scope
This document does not cover the Escrow account provisioning and funding. A different document will define external interfaces to connect to an external Escrow service.
Escrow Service API
To interact with the Escrow node, any FinP2P node has to support the Escrow Service
interface
service EscrowService { rpc Transfer(SignedTransferRequest) returns (SignedTransferResponse) {} rpc Hold (SignedHoldRequest) returns (SignedHoldResponse) {} rpc Release(SignedReleaseRequest) returns (SignedReleaseResponse) {} }
Asset Transaction with Escrow
The escrow transaction involves multiple messages between multiple parties: Asset, Buyer, Seller and Escrow.
We have already defined a TransferTransaction between FinP2P nodes. We will call these nodes: BuyerNode, SellerNode and AssetNode. We introduce also the EscrowNode to define the new interactions.
Asset Service
The Asset service is extended to support a rule base condition parameter that can host multiple implementation of an asset transfer condition.
In this document the Escrow condition is defined and the TransferRequestPayload updated.
Addition of the escrow settlement property indicate to the Asset’s node that an Escrow service should be involved in the Transfer operation.
Escrow settlement type
message TransferRequest { common.Envelope envelope = 1; ... ... oneof settlement { EscrowPayload escrow = 10; } }
Escrow Payload
message EscrowPayload { uint32 expiry = 1; // time boundary for the escrow to hold the funds for the transaction }
The expiry
parameter represent the time to live for the Escrow transaction. This is the time the Escrow will wait before rolling back the escrow transaction. The detailed table of possible states is described later in this document.
Transaction
The Asset’s Node generates the Escrow Transaction when it receives a TransferRequest
with an embedded Escrow condition.
Holding of Assets
Escrow node perform an Hold operation on a Users Escrow account by allocating a new dedicated Escrow account and securing the specified amount of the Asset in that account, subsequent Release
operation may transfer the funds to the designated target account or roll back the funds into the original user account.
message SignedHoldRequest { HoldRequest request = 1; common.Signature signature = 2; } message HoldRequest { common.Envelope envelope = 1; HoldRequestPayload payload = 2; } // command to escrow to hold funds, the command includes the signature (including template and values) // signed by the user holding the account // it is the caller responsibility to assure that the expected destination account for the subsequent Release operation // is supported by the Escrow, otherwise the Release operation will fail. message HoldRequestPayload { common.ResourceID sourceAccount = 1; accounts.Asset asset = 2; // asset information for which to hold the specified amount, might be different than account asset and potentially trigger a conversion uint64 amount = 3; int32 expiry = 4; signature.Signature sourceAccountUserSignature = 5; // the signature format (template + signature) from the source account from which the funds will be put on hold // expected contain the asset term, settlement term and settlement instruction } message SignedHoldResponse { HoldResponse response = 1; common.Signature signature = 2; } message HoldResponse { common.Envelope envelope = 1; common.Status status = 2; common.ResourceID escrowID = 3; // This is the identifier to track the Escrow // contract. It is also needed to Release/Cancel an // escrow. }
Asset’s Node Process Asset Transfer with Escrow:
Besides the normal verification for the AssetTransfer, the FinP2P node has to validate the Escrow Transaction rules and parameters.
Generates an Asset Transaction ID to identify the asset the requested asset transfer
Creates and calls HoldRequest on the Escrow Service with the data included in the Asset Transfer Transaction
HoldRequest process:
On Success:
Provide Escrow account information where payment is held.
Execute the asset transaction
On Failure: Send Failure response to Asset’s Node
Escrow Contract
The Escrow Service has to guaranty the following:
Guaranties to the buyer:
The escrow holding assets will be released to the seller ONLY if the assets were transferred to the buyer’s account.
If the digital assets transfer failed, the holding assets will be rolled back to the buyer’s account
Guaranties to the seller
The digital assets transfer will be executed only if the Escrow node has secured a hold to the requested amount of “fiat” ( or other currency ) in the escrow account and the beneficiary of the escrow account is the seller*
If the time to live expires before the assets are transferred to the buyer, The escrow transactions rolls back and the asset transaction cannot complete.
Guaranties to the buyer and seller
If Escrow Transaction time to live expires and the asset transaction was not executed successfully, the holding is rolled back to the buyer.
Processing EscrowID
To minimize the risk of race conditions between Escrow timeouts, Rollback transactions and Asset Transfers, the Seller’s FinP2P node implements an atomic asset transfer by using the EscrowID as an anchor to the Escrow holdings.
The presence of this Anchor means that the Escrow Service Transaction is alive. If, for any reason, the Anchor is removed, The Escrow Transaction is no longer valid and Asset’s node MUST not execute the asset transfer.
State Machine
The following table illustrates the different of the Escrow Transaction in relation to the EscrowID Anchor.
EscrowID Anchor | Escrow Transaction | Seller Assets | Buyer funds |
---|---|---|---|
Valid | Buyer funds still on hold by the Escrow | Not transferred to Buyer | On hold by the Escrow |
Invalid ( removed ) | Escrow TTL expired | Not Transferred to Buyer | Escrow rollback founds to Buyer’s account |
Terminated | Asset Transaction failed | Escrow rollback founds to Buyer’s account | |
Terminated | Assets transferred to Buyer’s Account | Buyer Founds transferred to Seller’s Account |
Implementations of the EscrowID Anchor
The EscrowID Anchor is created by the Asset’s FinP2P Node with the data received by the HoldResponse
.
There is no mandatory implementation for the state machine, but any FinP2P implementation MUST provide support for the Escrow Contract rules.
This document propose 2 possible solutions that may be implemented by FinP2P nodes:
DLT based Anchor
In this proposal the EscrowID Anchor is represented by a non-fungible asset( NFA ) in the DLT.
This NFA is created by the Seller’s FinP2P node and its signed by the EscrowNode.
With the NFA created, the Asset Transfer is created with 2 transactions:
NFA Transaction
Input: NFA
Output: destroy
Asset Transaction
Input: Asset's Seller
Output: Buyer
The transfer succeeds if-and-only-if both transaction succeed. Id the NFA input is invalid or no longer exists, the transaction fail.
Database Based Anchor
This solution is similar, but the NFA is created on a centralized Databased managed by FinP2P Sellers Node.
In this case, the Asset Transaction is executed if-and-only-if the NFA exists in the Database. Once the Asset Transaction starts, the NFA record is locked until the Transaction is committed.
Escrow Termination
On Event Timeout, the Escrow Service has to remove or invalidate the EscrowID Anchor from the Asset’s Node.
We add a new method request to the Asset Service to handle this
### Modified Asset Service service AssetService { ... rpc EscrowCancelation(SignedEscrowCancelationRequest) return (SignedEscrowCancelationResponse) {} } message EscrowCancelationRequest { Envelope envelope = 1; EscrowCancelationPayload = 2; } message EscrowCancelationPayload { ResourceID escrowid = 1; enum Reason { TIMEOUT = 0; BUYER = 1; SELLER = 2; } Reason reason = 2; } message EscrowCancelationResponse { Envelope envelope = 1; Status status = 2; }
Asset Transaction Process
The Escrow validates incoming Hold
requests originating from the Asset’s Primary node which orchestrate the transaction, the Escrow validates the provided signature to insure the buyer permit the Hold operations, only once the signature is validated the buyer’s asset is put on hold.
Escrow will wait for the specified expiry of the Hold operation, in case a receipt containing confirmation of asset transfer between the Seller to the Buyer is not received he will attempt to cancel the Hold operation by contacting the Asset’s primary node and notifying him about a pending cancellation.
Release holdings
On a successful Asset Transfer Transaction, the escrow is expected to release the holdings and transfer the assets to the Seller’s account.
Release API
When the asset transaction is executed, the Asset’s Primary Node can request the release of the escrow holdings.
message SignedReleaseRequest { ReleaseRequest request = 1; common.Signature signature = 2; } message ReleaseRequest { common.Envelope envelope = 1; ReleaseRequestPayload payload = 2; } message ReleaseRequestPayload { common.ResourceID escrowID = 1; // Generated during Hold tokens.Receipt receipt = 2; enum Action { RELEASE = 0; ROLLBACK = 1; } Action action = 3; accounts.Account destinationAccount = 4; // destination account to release payment to uint64 amount = 5; } message SignedReleaseResponse { ReleaseResponse response = 1; common.Signature signature = 2; } message ReleaseResponse { common.Envelope envelope = 1; common.Status status = 2; }
Transfer
Transfer API may be utilize to transfer funds between one user Escrow to another user account, account may be another escrow account on the same Escrow service or external account which is supported by the Escrow service, as indicated by the Payment Assets the escrow published.
message SignedTransferRequest { TransferRequest request = 1; common.Signature signature = 2; } message TransferRequest { common.Envelope envelope = 1; TransferRequestPayload payload = 2; } message TransferRequestPayload { accounts.Account sourceAccount = 1; accounts.Account destinationAccount = 2; Amount amount = 3; signature.Signature signature = 4; } message SignedTransferResponse { TransferResponse response = 1; common.Signature signature = 2; } message TransferResponse { common.Envelope envelope = 1; common.Status status = 2; }
Payment Assets
Payment Asset is a new Resource type (104) that indicate to other nodes on the network the list of supported Assets and Accounts which the Escrow supports, the nodes should consult with that list, prior to any interaction with the Escrow Service that provides asset or account information, to avoid immanent failures.
Conversion Rates
Escrow Service may supply rate conversion capability as part of his operations, in case the source and destination account doesn’t share the same underlying Asset a conversion will be made and fees or other charges may be applied.
Interaction with External Services
The FinP2P Escrow Service Node can interact with an exciting Escrow Service by implementing the EscrowService gRPC service and relay the calls to the external service.
In a new document we will define the interaction flows and update this document with any missing functionality to support external services.
0 Comments