Withdrawals
Withdrawals are allowed after the fundraising period ends. Equillar separates project withdrawals from commission withdrawals.
Important: During the claim_block_ts period, contract activity may drop significantly: no new investments are accepted, and payout rounds have not yet begun. The most notable activity during this window is limited to commission withdrawals by the company and the integrator.
This reduced activity can cause the ledger entries storing positions, balances, and related contract data to become archived due to TTL (time-to-live) expiration. Starting with Protocol 23, archived entries in Persistent and Instance storage can be automatically restored as part of a transaction's execution, provided the entry is included in the transaction's restore footprint — which, in practice, is populated automatically when the invocation is simulated via Stellar RPC (the standard flow used by stellar-cli and most SDKs/integrators).
Given this, Equillar does not currently implement a proactive TTL-extension mechanism (e.g. a scheduled "keeper" call to renew TTLs during long inactivity windows). Instead, the contract relies on Protocol 23's automatic restoration during normal invocation. The practical implication for integrators is that the first call made after an extended period of inactivity may incur higher fees, due to the on-chain cost of restoring archived entries — but the call itself does not fail or require a separate manual restore step, as long as it goes through a client that simulates the transaction beforehand.
Note: if an integrator submits a transaction with a manually constructed footprint (bypassing RPC simulation) against an archived entry, that transaction will fail rather than auto-restore. This is not expected in standard integration flows, but is worth being aware of for custom transaction-building setups.
Company project withdrawals
The admin can move project funds out of the contract through the function withdrawn(amount, to)
stellar contract invoke \
--id <YOUR_CONTRACT_ID> \
-s admin \
--network testnet \
-- \
withdrawn \
--amount "3000000000"
--to "G....."
Company withdrawals are allowed only if all of the following conditions are met:
- the contract is not paused
- there is no active emergency
toholds thecompanyrole- the fundraising period has already ended
- the project balance is sufficient to cover the withdrawal
The total amount a company can withdraw is the sum of all user investments, minus commissions.
Following the example from the Fundraising and positions section, where we invested a total of 500_0000000 token units, the amount available for the project was 497.72, with the remainder allocated to the commissions budget.
Commission withdrawals
The admin can withdraw accumulated commissions through the function withdrawn_commissions(to)
stellar contract invoke \
--id <YOUR_CONTRACT_ID> \
-s admin \
--network testnet \
-- \
withdrawn_commissions \
--to "G....."
Commission withdrawals are allowed only if all of the following conditions are met:
- contract not paused
- no active emergency
toholds themanagerrole- fundraising has already ended
- there is pending commission still available to withdraw
Notice that the withdraw_commissions function does not require an amount. This is because it withdraws the full amount of commissions that has not yet been withdrawn. This is useful for integrators, since they don't need to track how much they're allowed to withdraw. That said, calls to this function should be spaced out enough to ensure there are commissions available each time, avoiding unnecessary calls that would fail due to having nothing left to withdraw.
General withdrawal
The admin can also sweep all remaining funds out of the contract to an address holding the manager role, by calling the withdraw_all(to) function.
This function is useful for integrators when funds remain locked in the contract beyond what's needed to cover the project's payment obligations — for example, if the company contributed more funds than strictly required to settle its obligations. Rather than leaving that excess trapped in the contract indefinitely, the admin can withdraw the full balance to a trusted manager address.
stellar contract invoke \
--id <YOUR_CONTRACT_ID> \
-s admin \
--network testnet \
-- \
withdraw_all \
--to "G....."
Events and balance after a company withdrawal
When the company withdraws project funds through withdrawn, the balance is updated via recalculate_from_company_withdrawal:
projectis reduced by the withdrawn amountproject_withdrawalsis increased by the same amount
This update is published through the standard ContractBalanceUpdated event (see Fundraising and positions section above).
In addition, the contract emits a dedicated event with the withdrawal details:
WithdrawalDone:
WithdrawalDone {
addr, // the address of the contract
total_withdrawn, // the total amount withdrawn by the company
}
Reading this event with stellar-cli
stellar events \
--id <YOUR_CONTRACT_ID> \
--network testnet \
--start-ledger <LEDGER_NUMBER> \
--type contract \
--topic "WithdrawalDone,*"
Events and balance after a commission withdrawal
When the integrator withdraws accrued commissions through withdrawn_commissions, the balance is updated via recalculate_from_comission_withdrawal:
comission_withdrawalis increased by the withdrawn amount
Note that this only tracks the cumulative amount withdrawn to date; it does not reduce the comission field itself, which keeps accruing as new investments come in.
This update is published through the standard ContractBalanceUpdated event (see Fundraising and positions section above).
In addition, the contract emits a dedicated event with the withdrawal details:
CommissionWithdrawn:
CommissionWithdrawn {
addr, // the address of the contract
amount, // the total commission amount withdrawn
}
Reading this event with stellar-cli
stellar events \
--id <YOUR_CONTRACT_ID> \
--network testnet \
--start-ledger <LEDGER_NUMBER> \
--type contract \
--topic "CommissionWithdrawn,*"
Events and balance after withdrawing all funds
When the admin sweeps all remaining funds out of the contract through withdrawn_all, the balance is fully reset via reset_balance. This function can only be called when there are no outstanding payment obligations (payment_obligations == 0), ensuring it's only used to recover truly excess funds and never to bypass a debt still owed to investors.
- every field in the balance (
reserve,project,comission,comission_withdrawal,payments,project_withdrawals,payment_obligations,collateral_received,collateral_liquidated,collateral_returned,refunded_to_investor) is set back to0
This update is published through the standard ContractBalanceUpdated event (see Fundraising and positions section).
In addition, the contract emits a dedicated event with the withdrawal details:
AllWithdrawn:
AllWithdrawn {
addr, // the address of the contract
amount, // the total amount withdrawn
}
Reading this event with stellar-cli
stellar events \
--id <YOUR_CONTRACT_ID> \
--network testnet \
--start-ledger <LEDGER_NUMBER> \
--type contract \
--topic "AllWithdrawn,*"