Emergency close
Emergency close is the engines's post-fundraising wind-down path. It can be activated when the company fails and there is no collateral to pay investors.
It is not the same as
refund_investor:refund_investorreturns the full deposited amount to the investor when the project's fundraising is cancelled before the fundraising period ends — at that point the company hasn't started operating yet, and therefore hasn't started spending the raised funds.
Collateral vs. Emergency close: Collateral liquidation and emergency close are independent, severity-scoped mechanisms. Collateral acts as a per-position safeguard — if a specific investor's payment round cannot be covered from
reserve, that individual position can be settled immediately using the available collateral, without affecting the rest of the project. Emergency close, on the other hand, is a project-wide, terminal wind-down path, used when the company fails and there's no collateral left to keep covering payments. In other words, collateral liquidation is what most individual payment shortfalls resolve into, while emergency close is reserved for when that safeguard is no longer enough.
Activating the emergency close
The emergency close activation can be achieved by the function: activate_emergency_close.
stellar contract invoke \
--id <YOUR_CONTRACT_ID> \
-s admin \
--network testnet \
-- \
activate_emergency_close
The emergency close can be activated when the following conditions are met:
- The fundraising period has already ended
- Emergency close has not already been activated
- The integrator has withdrawn all pending commissions
- There are still funds to distribute to investors
- There are still outstanding payment obligations to cover
After the emergency close is activated, no more investments, payments and withdrawns are allowed.
Note: Activating emergency close is also valid
Worked example
Suppose there are currently three active positions, all created from the same 1000 deposit. Each position originally had:
total = 1044regular_payment = 261
Now suppose some payment rounds have already happened before the emergency close's activation:
| Position | Total | Already paid | Remaining obligations |
|---|---|---|---|
| A | 1044 | 261 | 783 |
| B | 1044 | 522 | 522 |
| C | 1044 | 783 | 261 |
So the global remaining obligations are:
783 + 522 + 261 = 1566
Before emergency close can be activated, pending commissions must already be withdrawn.
Assume the contract state at that moment is:
reserve = 120
project = 780
commission = 0
payment_obligations = 1566
That means the emergency pool is:
emergency_pool_total = reserve + project = 900
This is the important setup:
- investors are still owed
1566 - the emergency pool only has
900
So equillar cannot make investors whole. It can only distribute the remaining pool proportionally.
Emergency payout for position A
Position A still has:
remaining obligation = 783
So its payout is:
amount_to_pay = 783 * 900 / 1566 = 450
After paying A:
emergency_pool_remaining = 900 - 450 = 450
emergency_obligations_left = 1566 - 783 = 783
At contract-balance level, emergency payout consumes reserve first and then project:
reserve used = 120
project used = 330
reserve = 0
project = 450
Position A is marked as completed.
Emergency payout for position B
Position B still has:
remaining obligation = 522
Now the contract uses the updated emergency state:
amount_to_pay = 522 * 450 / 783 = 300
After paying B:
emergency_pool_remaining = 450 - 300 = 150
emergency_obligations_left = 783 - 522 = 261
reserve = 0
project = 150
Position B is marked as completed.
Emergency payout for position C
Position C still has:
remaining obligation = 261
At this point, position C's own remaining obligation (261) equals the total obligations still left in the contract (emergency_obligations_left = 261) — which is expected, since it's the last position pending payment. When a position's remaining obligation is greater than or equal to the total obligations left, it receives the full remaining emergency pool rather than a proportional share:
amount_to_pay = 150
After paying C:
emergency_pool_remaining = 0
emergency_obligations_left = 0
reserve = 0
project = 0
payment_obligations = 0
Position C is also marked as completed.
Final outcome for each investor
The users keep whatever they had already received before emergency close, and then receive their proportional emergency payout:
| Position | Already paid before emergency | Emergency payout | Final received |
|---|---|---|---|
| A | 261 | 450 | 711 |
| B | 522 | 300 | 822 |
| C | 783 | 150 | 933 |
None of them reaches 1044, because the emergency pool was smaller than the remaining obligations.
Events after activating emergency close
Activating emergency close through activate_emergency_close does not modify the balance. It only emits an event capturing the emergency state at the moment of activation:
EmergencyCloseActivated:
EmergencyCloseActivated {
addr, // the address of the contract
emergency_pool_total, // funds available to distribute among investors (project + reserve)
emergency_obligations_total, // total payment obligations still owed to investors
}
Reading this event with stellar-cli
stellar events \
--id <YOUR_CONTRACT_ID> \
--network testnet \
--start-ledger <LEDGER_NUMBER> \
--type contract \
--topic "EmergencyCloseActivated,*"
Events and balance after an emergency payment
When an investor receives a proportional emergency payout through emergency_pay_investor, the balance is updated via recalculate_from_emergency_payment:
reserveis reduced first, up to its available amount- any remaining portion of the payout is then deducted from
project paymentsis increased by the total amount paidpayment_obligationsis reduced by the position's outstanding amount at the time of payment
This update is published through the standard ContractBalanceUpdated event (see Fundraising and positions section).
In addition, the contract emits a dedicated event with the payment details:
EmergencyPaymentSent:
EmergencyPaymentSent {
addr, // the address of the contract
to, // the operator address the payment is sent to
total_sent, // the total amount transferred
}
Reading this event with stellar-cli
stellar events \
--id <YOUR_CONTRACT_ID> \
--network testnet \
--start-ledger <LEDGER_NUMBER> \
--type contract \
--topic "EmergencyPaymentSent,*"