Archive post
Escrows, what are they and how do they work in depth
• howo
Hey, Recently @TheRealWolf released a tool to manage escrows: he mentioned how hard it was to find any docs on escrows, and a few more people chimed in asking for it too

Hey, Recently @TheRealWolf released a tool to manage escrows: https://peakd.com/@therealwolf/beescrow-escrow-powered-by-hive he mentioned how hard it was to find any docs on escrows, and a few more people chimed in asking for it too.
Recently I looked deeply into the escrow code when I implemented the rosetta api for hive (prerequisite for a coinbase listing). So I figured it would be a good time to write a good doc about it for future users.
# What are escrows
Escrows are a way to send HIVE or HBD to another person while a third party is here as an arbiter to the transaction with minimal trust.
Let's say I want to purchase an item from someone for 100 HBD, but I don't trust that the person will send the item to me and the sender doesn't trust that I'll send the money once I receive the item.
We can agree on a common third person that we both trust, we'll call him the `agent` and create an escrow using `escrow_transfer_operation`:
When I execute the transaction, the 100 HBD leaves my account and is put into a safe that neither me nor the seller can access.
In order to release the funds to the seller, the seller **AND** the agent must execute a transaction to approve the escrow (two separate transactions). If that's the case the money can be released via `escrow_release_operation`
But then let's say I didn't receive the item I wanted or it's damaged. Me or the seller can submit a `escrow_dispute_operation`.
Once the escrow is disputed, the money is entirely in control of the agent who gets to mediate and chose how much money to send to the seller or the buyer.
Note that at no point the agent can run away with the money, making it safer than a traditional escrow service where you would send the money to the agent.
Now that you got a broad overview of how escrows work, let's dig into the details as there's a bunch of edge cases and more details to cover.
# Creating an escrow: escrow_transfer_operation
Now let's dig into the details, these are the parameters, I've put obvious details on the comments
```
account_name_type from; // User creating the transaction and sending the money
account_name_type to; // User receiving the money
account_name_type agent; // Account who will manage the escrow
uint32_t escrow_id = 30; // Id must be unique
asset hbd_amount = asset( 0, HBD_SYMBOL );
asset hive_amount = asset( 0, HIVE_SYMBOL );
asset fee; // Fee will be paid to the agent upon escrow resolution
time_point_sec ratification_deadline;
time_point_sec escrow_expiration;
json_string json_meta; // Json metadata, you may input whatever data you want there
```
`ratification_deadline` sets the deadline within which the escrow must be approved (see later on how that works). If the escrow isn't approved by both the `agent` and `to` all the funds (including the fee) go back to the the `from` account, effectively undoing the effects of the `escrow_transfer_operation`. This is done automatically.
`escrow_expiration` is a timer on the agent, If there is no dispute and escrow has not expired, either party can release funds to the other, allowing an escrow to be resolved without the agent. So `from` can release funds to `to` and `to` can release funds to `from`. But nobody can release funds to themselves. This is not automatic and needs to be explicit through the `escrow_release_operation`
Some extra details:
- Escrow ID is unique per `from` account
- You can create an escrow that pays out HBD AND HIVE at the same time
- The fee has to be in HBD or HIVE, can't be a mix of the two
- The fee will be deducted from the `from` account along with the `hbd_amount` and `hive_amount` when the transaction is executed not when the escrow is finished
- An account can have a maximum of 254 escrow transfers open at once
# Approving or Cancelling the escrow: escrow_approve_operation
let's look at the params
```
account_name_type from;
account_name_type to;
account_name_type agent;
account_name_type who; // Either to or agent
uint32_t escrow_id = 30;
bool approve = true;
```
In order for an escrow to be releasable, both `to` and `agent` must submit an `escrow_approve_operation` with `approve` set to true. Once approved, the `agent` receives their fee, and the escrow funds become available for release
If either the `agent` or `to` sets `approve` to `false` the escrow is cancelled, all the funds (including the fee) goes back to `from` effectively undoing the effects of the `escrow_transfer_operation`. An `escrow_rejected_operation` virtual operation is generated.
Once both `from` and `to` approve, then the escrow is deemed valid, the `agent` gets its fee. Then an `escrow_approved_operation` virtual operation is generated.
Once any party approves the escrow, they cannot revoke their approval. Subsequent escrow approve operations, regardless of what approval is set to (true/false), will be rejected.
# Disputing the escrow: escrow_dispute_operation
If any party (`from` or `to`) has an issue with the escrow, they may raise a dispute and let the agent resolve the issue.
The params are pretty straightforward:
```
account_name_type from;
account_name_type to;
account_name_type agent;
account_name_type who; // Defines which account is raisining the dispute, either "to" or "from"
uint32_t escrow_id = 30;
```
Some extra details:
- Disputing must happen before the escrow expiration time
- You can only dispute an escrow that has been approved by both `to` and the `agent`
- Once an escrow is disputed, it can't be un-disputed and only the `agent` has the power to move funds at that point through `escrow_release_operation`
# Releasing the funds: escrow_release_operation
This is the operation that is used to release the funds in the escrow. The escrow must be approved by both `to` and `agent` before any release can happen
Depending on the state of the escrow, different people will have permission to release funds:
- If there is no dispute and the escrow has not expired, either `from` or `to` can release funds to the other.
- If the escrow expires and there is no dispute, either `from` or `to` can release funds to either party. Meaning a party can send the money to himself !
- If there is a dispute regardless of expiration, only the agent can release funds to either `from` or `to`
Let's look at the params:
```
account_name_type from;
account_name_type to; // the original 'to'
account_name_type agent;
account_name_type who; ///< the account that is attempting to release the funds, determines valid 'receiver'
account_name_type receiver; ///< the account that should receive funds (might be from, might be to)
uint32_t escrow_id = 30;
asset hbd_amount = asset( 0, HBD_SYMBOL ); ///< the amount of HBD to release
asset hive_amount = asset( 0, HIVE_SYMBOL ); ///< the amount of HIVE to release
```
Note that you can execute the transaction multiple times in case you want to release funds in installments or split the funds between `to` or `from`.
The escrow is only deleted once there is no more funds.