Skip to main content

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_investor returns 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 = 1044
  • regular_payment = 261

Now suppose some payment rounds have already happened before the emergency close's activation:

PositionTotalAlready paidRemaining obligations
A1044261783
B1044522522
C1044783261

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:

PositionAlready paid before emergencyEmergency payoutFinal received
A261450711
B522300822
C783150933

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:

  • reserve is reduced first, up to its available amount
  • any remaining portion of the payout is then deducted from project
  • payments is increased by the total amount paid
  • payment_obligations is 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,*"