Payment rounds
After the claim block period ends (the period that comes after the fundraising one), the project enters the regular payment phase. Equillar does not force integrators to send the payments within the contract. Let's explore how this is achieved within the rest of the section.
Payment rounds with transfers
These types of rounds are carried out in two steps:
- The company transfer
- The payments to the users
The company transfer
In this first step, the company transfers sufficient funds to cover the corresponding payments for the next round to all investors. This is carried out through the function add_company_transfer.
stellar contract invoke \
--id <YOUR_CONTRACT_ID> \
-s admin \
--network testnet \
-- \
add_company_transfer \
--amount "21000000"
--from "G....."
Company transfers are allowed only if all of the following conditions are met:
- requires admin
- requires
fromto holdcompany - requires no active emergency
- requires the claim block to be over
Following the example from the Fundraising and positions section, where we invested a total of 500_0000000 token units, as the return_type was "Coupon", unless it was the last payment, it would be enough for the company to transfer a total of 2.1 token units (2_1000000) since the regular_payment for that token id was 2.07 token units.
After the company transfers the funds to the contract, the payments are not executed automatically. They remain in the reserve bucket until the payment function is called. The round number is incremented so that the payment function is ready to pay investors. If the round number were not incremented, the payment function would fail because it would attempt to pay for a round that has already been paid for. Let's explore the payment function in the next section.
The payment function
The payment to the investors is carried out through the function process_investor_payment:
stellar contract invoke \
--id <YOUR_CONTRACT_ID> \
-s admin \
--network testnet \
-- \
process_investor_payment \
--token_id 1234
Payments are allowed only if all of the following conditions are met:
- requires admin
- requires no active emergency
- requires a valid position
- requires the position not to be completed
- requires the reserve to be sufficient for the current round
- requires the right payment round
After the functon is executed, the payment is sent to the token_id propietary, that is, the operator address that called te invest function.
The process_investor_payment is called individually for each token_id that invested in the project. This results in many calls to the contract, but in return it gives integrators the flexibility to distribute payments according to their needs or requirements.
It is important that all payments for a given round have been submitted before executing the next round, that is, before calling the add_company_transfer function again. Otherwise, funds could become locked in the contract.
Payment rounds without transfers
As said at the begining of the section, equillar does not force integrators to transfer the payments within the contract. This option is disabled by default but it can be enabled during the block period, before the payments start.
Enabling / Disabling investment liquidations
To do that, the contract exposes the following functions:
- enable_investment_liquidations
- disable_investment_liquidations
- check_investment_liquidations
So, for disabling investment liquidations within the contract we can call the corresponding function as follows:
stellar contract invoke \
--id <YOUR_CONTRACT_ID> \
-s admin \
--network testnet \
-- \
disable_investment_liquidations
If you would want to enable it again you could call enable_investment_liquidations just as we did with disable_investment_liquidations.
stellar contract invoke \
--id <YOUR_CONTRACT_ID> \
-s admin \
--network testnet \
-- \
enable_investment_liquidations
For checking what is the current status of the contract investment liquidations, we can call the check_investment_liquidations function as follows:
stellar contract invoke \
--id <YOUR_CONTRACT_ID> \
-s admin \
--network testnet \
-- \
check_investment_liquidations \
--caller "G...."
Notice that check_investment_liquidations requires the caller address as parameter. This is because any role (company, admin, operator and manager) can check the liquidation investments status. The other functions can only be called by the admin.
Updating positions without transfers
With the investment liquidations disabled, there is no need to call the function add_company_transfer since the payments (transfers) are not going to be sent within the contract. Even so, it is important to call the process_investor_payment function so that the position is updated once the payment has been sent via the alternative method.
Events and balance after a company transfer into reserve
When the company transfers funds into the contract to cover upcoming investor payments through add_company_transfer, the balance is updated via recalculate_from_company_contribution:
reserveis increased by the transferred amount
This update is published through the standard ContractBalanceUpdated event (see Fundraising and positions section).
In addition, the contract emits a dedicated event with the transfer details:
CompanyTransferReceived:
CompanyTransferReceived {
addr, // the address of the contract
total_received, // the total amount transferred by the company
}
Reading this event with stellar-cli
stellar events \
--id <YOUR_CONTRACT_ID> \
--network testnet \
--start-ledger <LEDGER_NUMBER> \
--type contract \
--topic "CompanyTransferReceived,*"
Events and balance after a regular investor payment
When a payment round is processed for an investor through process_investor_payment, the balance is updated via recalculate_from_payment_to_investor:
reserveis reduced by the paid amountpaymentsis increased by the same amountpayment_obligationsis reduced by the same amount
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:
PaymentSent:
PaymentSent {
addr, // the address of the contract
total_sent, // the total amount sent to the investor
}
Reading this event with stellar-cli
stellar events \
--id <YOUR_CONTRACT_ID> \
--network testnet \
--start-ledger <LEDGER_NUMBER> \
--type contract \
--topic "PaymentSent,*"