Henriable
Inherits: HHelper
Title: The Henriable contract.
Author: Obiaraije Henry
All USD amounts are expressed as integers in USDC base units (6 decimals), i.e.
micro-USDC, where 1 USDC == USDC_UNIT == 10 ** 6 base units (e.g. $14 ==
14_000_000 and $0.14 == 140_000). The contract never converts or scales; it moves
the raw base-unit value. Callers must therefore pass base units: the frontend uses
viem’s parseUnits(x, 6), not a whole-dollar number.
Functions
constructor
Deploys Henriable, setting the contract owner, the USDC token and the NFT.
constructor(address initialOwner, IERC20 ownerUsdToken_, HenriableVehicleNFT vehicleNft_)
HHelper(initialOwner, ownerUsdToken_, vehicleNft_);
Parameters
| Name | Type | Description |
|---|---|---|
initialOwner | address | The address that will own the contract. |
ownerUsdToken_ | IERC20 | The USDC token used for investments, payouts and payments. |
vehicleNft_ | HenriableVehicleNFT | The vehicle-title NFT collection, whose minter must be set to this contract so it can mint and later transfer asset titles. |
actionAdminSetOwner2
Sets the secondary owner, who may run every admin action but not manage owners.
Only owner1 ({onlyOwner}) may call this, so owner2 cannot set or clear owners.
Pass address(0) to clear owner2; rejected when _owner2 is owner1 itself.
States updated: {owner2}.
function actionAdminSetOwner2(address _owner2) external onlyOwner;
Parameters
| Name | Type | Description |
|---|---|---|
_owner2 | address | The new secondary owner address, or address(0) to clear it. |
actionAdminAddAsset
Adds a new asset that can be invested in.
Only an owner (admin: owner1 or owner2) may call this. Validates the asset, forces it active, appends it to {assetsList} and records its position in the {assets} index mapping. States updated: {assetsList}, {assets}.
function actionAdminAddAsset(HAsset calldata _asset) external onlyOwners;
Parameters
| Name | Type | Description |
|---|---|---|
_asset | HAsset | The asset configuration to register. Its id must be unique and non-zero, name non-empty, and costPrice/sellPrice non-zero. The active field is ignored and set to true. |
actionAdminChangeAssetStatus
Enables or disables an asset.
Only an owner (admin: owner1 or owner2) may call this. The asset status may only change while every investment that depends on the asset is still {HInvestmentStatus.Pending}; once any such investment has moved past Pending, the asset is locked. Disabling an asset also disables its still-pending investments. Enabling an asset does NOT re-enable those investments. States updated: {assetsList}, and {investmentsList} when disabling.
function actionAdminChangeAssetStatus(bytes32 _assetId, bool _status) external onlyOwners;
Parameters
| Name | Type | Description |
|---|---|---|
_assetId | bytes32 | The id of the asset to update. |
_status | bool | The new active status. |
actionAdminAddInvestment
Adds a new investment opportunity against an existing active asset.
Only an owner (admin: owner1 or owner2) may call this. {HInvestment} contains mappings and therefore cannot be passed as a calldata parameter, so the admin-supplied settings are taken as individual arguments. Validates them, checks the level-1 settings against the asset, forces the opportunity active and Pending, appends it to {investmentsList}, records its position in the {investments} index mapping and links it to its asset via {assetInvestments}. States updated: {investmentsList}, {investments}, {assetInvestments}.
function actionAdminAddInvestment(
bytes32 _investmentId,
bytes32 _assetId,
uint256 _riderInitialBuyinUsd,
uint256 _periodicRiderPayingInMinutes,
uint256 _minimumRiderPeriodicPayingsUsd
) external onlyOwners;
Parameters
| Name | Type | Description |
|---|---|---|
_investmentId | bytes32 | Unique, non-zero id of the new investment slot. |
_assetId | bytes32 | Id of the asset to invest in; must exist and be active. |
_riderInitialBuyinUsd | uint256 | Initial rider buy-in, in USDC base units (6 decimals); must be non-zero. Callers pass base units (frontend: parseUnits(x, 6)). |
_periodicRiderPayingInMinutes | uint256 | Length of a rider period, in minutes; must be non-zero. |
_minimumRiderPeriodicPayingsUsd | uint256 | Minimum rider payment per period, in USDC base units (6 decimals); must be non-zero. Callers pass base units. |
actionAdminChangeInvestmentStatus
Enables or disables an investment opportunity.
Only an owner (admin: owner1 or owner2) may call this. The investment’s active flag may only change while no investor has joined it; once the senior or junior pool has any investor, the opportunity is locked. States updated: {investmentsList}.
function actionAdminChangeInvestmentStatus(bytes32 _investmentId, bool _status) external onlyOwners;
Parameters
| Name | Type | Description |
|---|---|---|
_investmentId | bytes32 | The id of the investment to update. |
_status | bool | The new active status. |
actionAdminSetNextInvestmentTimes
Sets the start and end of the next investment round for an investment.
Only an owner (admin: owner1 or owner2) may call this.
The opportunity must still be Pending or in investment(to extend it) and its asset active, and the
round must be in the future with _endTime after _startTime.
States updated: {investmentsList}.
function actionAdminSetNextInvestmentTimes(bytes32 _investmentId, uint256 _startTime, uint256 _endTime)
external
onlyOwners;
Parameters
| Name | Type | Description |
|---|---|---|
_investmentId | bytes32 | The id of the investment to schedule. |
_startTime | uint256 | Timestamp at which the next investment round starts; must be in the future. |
_endTime | uint256 | Timestamp at which the next investment round ends; must be after _startTime. |
actionAdminClearNextInvestmentsTimes
Clears the start and end of the next investment round for an investment.
Only an owner (admin: owner1 or owner2) may call this. The opportunity must still be Pending; both times are reset to 0. States updated: {investmentsList}.
function actionAdminClearNextInvestmentsTimes(bytes32 _investmentId) external onlyOwners;
Parameters
| Name | Type | Description |
|---|---|---|
_investmentId | bytes32 | The id of the investment whose round is cleared. |
actionInvest
Lets an address invest into a tier of an active investment opportunity.
The investor is {msg.sender}; _investor only supplies name, country
and age. The asset defines the per-investor buying price and the number
of slots, so the required amount is the tier’s one-investor buying price.
The contract pulls exactly that amount from the investor’s USDC.
An address may call this repeatedly and in either tier, taking one seat
per call, so the same address can appear more than once in a tier’s list
(each entry is a separate seat and is paid its own equal share).
States updated: {investorsList}, {investors}, and the chosen tier’s
list and mapping inside {investmentsList}.
function actionInvest(
HInvestor calldata _investor,
HInvestmentType _investmentType,
bytes32 _investmentId,
uint256 _approvedUSDAmount
) external;
Parameters
| Name | Type | Description |
|---|---|---|
_investor | HInvestor | The investor profile (name, country, age) to create or update. |
_investmentType | HInvestmentType | The tier to invest in (Senior or Junior). |
_investmentId | bytes32 | The id of the investment to invest in. |
_approvedUSDAmount | uint256 | The USDC amount approved for this slot, in USDC base units (6 decimals); must equal the slot amount. Callers pass base units (frontend: parseUnits(x, 6)). |
actionSetNextHireRoundTime
Sets the window during which riders may request to hire an investment’s asset.
Only an owner (admin: owner1 or owner2) may call this.
The opportunity must be funded ({HInvestmentStatus.InvestmentDone}) or, once a
hire round is open, still accepting riders ({HInvestmentStatus.AcceptingRiders})
so an in-progress round can be extended. The window must be in the future with
_endTime after _startTime.
States updated: {investmentsList}.
function actionSetNextHireRoundTime(bytes32 _investmentId, uint256 _startTime, uint256 _endTime)
external
onlyOwners;
Parameters
| Name | Type | Description |
|---|---|---|
_investmentId | bytes32 | The id of the investment to schedule. |
_startTime | uint256 | Timestamp at which the next hire-request round starts; must be in the future. |
_endTime | uint256 | Timestamp at which the next hire-request round ends; must be after _startTime. |
actionClearNextHireTime
Clears the rider hire-request window for a funded investment.
Only an owner (admin: owner1 or owner2) may call this. The opportunity must be funded ({HInvestmentStatus.InvestmentDone}); both hire-request times are reset to 0. States updated: {investmentsList}.
function actionClearNextHireTime(bytes32 _investmentId) external onlyOwners;
Parameters
| Name | Type | Description |
|---|---|---|
_investmentId | bytes32 | The id of the investment whose hire window is cleared. |
actionRiderRegisterAsARider
Registers the caller as a rider for a funded investment’s hire round.
The rider is {msg.sender}; the initial buy-in is pulled into the contract so it can be refunded if the rider is later rejected. Registration is only allowed while the investment is {HInvestmentStatus.AcceptingRiders}. States updated: {ridersList}, {riders}, {ridersHirePurchasesRequestsList}, {ridersHireRequestPurchasesByInvestment}, and the investment’s {HInvestment.ridersHirePurchaseRequestsList}/{ridersHirePurchaseRequests}.
function actionRiderRegisterAsARider(
bytes32 _name,
bytes32 _country,
uint8 _age,
uint256 _approvedInitialBuyin,
bytes32 _investmentId
) external;
Parameters
| Name | Type | Description |
|---|---|---|
_name | bytes32 | The rider’s name; must be non-zero. |
_country | bytes32 | The rider’s country; must be non-zero. |
_age | uint8 | The rider’s age; must be at least 18. |
_approvedInitialBuyin | uint256 | The USDC the rider approved, in USDC base units (6 decimals); must cover the required buy-in. Callers pass base units. |
_investmentId | bytes32 | The id of the investment to register for. |
actionAdminAcceptRider
Accepts one applicant as the rider for a funded investment and rejects the rest.
Only an owner (admin: owner1 or owner2) may call this. The investment must still be {HInvestmentStatus.AcceptingRiders} and have no hired rider yet; the chosen rider must exist, must have applied for the investment (recorded by actionRiderRegisterAsARider) and must not have been rejected before. Every other applicant is marked rejected via {rejectedRiders} and has their initial buy-in refunded. The accepted rider’s buy-in is credited toward their hire-purchase total and shared with the investor pools and the owner immediately. The investment then moves to {HInvestmentStatus.Hired} and the rider’s next payment date is set one period from now. States updated: {HInvestment.riderWhoHiredIt}, {HInvestment.riderNextPayinDate}, {HInvestment.status}, {rejectedRiders}, {HInvestment.riderPayinsHistory}, {ownerPayoutsList}, {investorPayoutList} and the payout histories.
function actionAdminAcceptRider(bytes32 _investmentId, address _riderAddress) external onlyOwners;
Parameters
| Name | Type | Description |
|---|---|---|
_investmentId | bytes32 | The id of the investment whose rider is being chosen. |
_riderAddress | address | The applicant to accept as the hired rider. |
actionAdminExtendRiderPayingForInvestment
Pushes the hired rider’s next payment due date to a later time and optionally slashes an amount from the rider’s accumulated savings.
Only an owner (admin: owner1 or owner2) may call this.
The opportunity must be {HInvestmentStatus.Hired}, i.e. a rider is
currently paying, and the new date must be later than the current
next-payment date. Extending the date gives the rider more time before
actionRiderPayin treats their next payment as late.
When _slashAmount is non-zero it must not exceed the rider’s saved amount;
the savings are reduced by it and the amount is split to the owner and
investor pools exactly like a rider payment, recorded as
{HPayoutType.RiderSavingsSlash} payouts and tracked via {HRiderSavingsSlash}.
States updated: {HInvestment.riderNextPayinDate}, {HInvestment.riderSavings},
{riderSavingsSlashesList}, and the investment’s slash and payout histories.
function actionAdminExtendRiderPayingForInvestment(
bytes32 _investmentId,
uint256 _newNextPayinDate,
uint256 _slashAmount
) external onlyOwners;
Parameters
| Name | Type | Description |
|---|---|---|
_investmentId | bytes32 | The id of the investment whose rider payment is extended. |
_newNextPayinDate | uint256 | The new timestamp at which the rider’s next payment is due; must be later than the investment’s current next-payment date. |
_slashAmount | uint256 | Amount to slash from the rider’s savings, in USDC base units (6 decimals); 0 extends without slashing. Callers pass base units. |
actionRiderPayin
Lets the hired rider make a periodic payment under a running hire purchase.
The rider must be the one hired on an investment in {HInvestmentStatus.Hired}, must not have completed the target total, and must make a non-late payment of at least {HInvestment.minimumRiderPeriodicPayingsUsd} plus the asset’s {HAsset.riderSlashableRepayableExtraCharge}. The extra charge is set aside as the rider’s savings, and the rest is split by {calcSharingFormula} and credited to the owner and the senior/junior investor pools. States updated: {riderPayinsList}, {riderPayins}, {HInvestment.riderPayinsHistory}, {HInvestment.riderNextPayinDate}, {ownerPayoutsList}, {investorPayoutList}, {HInvestment.riderSavings}, {HInvestment.investmentPayoutHistory} and the per-investor payout histories.
function actionRiderPayin(bytes32 _investmentId, uint256 _approvedUSD) external;
Parameters
| Name | Type | Description |
|---|---|---|
_investmentId | bytes32 | The id of the investment being paid. |
_approvedUSD | uint256 | The USDC the rider is paying, in USDC base units (6 decimals); must be at least the minimum plus the savings charge. Callers pass base units (frontend: parseUnits(x, 6)). |
actionTransferOwnershipToRider
Completes a hire purchase by transferring ownership of the asset to the rider.
Only valid once the rider has finished paying. The rider’s accumulated savings are refunded to them and cleared, the investment is marked {HInvestmentStatus.Complete}, the completion timestamps are recorded and the investment is appended to the completed lists. It cannot run twice, so the completion side effects happen exactly once. States updated: {HInvestment.riderSavings}, {investmentsList}, {completedRiderInvestmentList} and {investmentsCompleted}.
function actionTransferOwnershipToRider(address _rider, bytes32 _investmentId) public;
Parameters
| Name | Type | Description |
|---|---|---|
_rider | address | The rider receiving ownership; must be the investment’s hired rider. |
_investmentId | bytes32 | The id of the investment being completed. |
getStats
Returns every aggregate statistic the frontend displays in one call.
Counters are maintained in O(1) as the contract is used; the totals that mirror list lengths are filled in here so there is a single source of truth. Investor figures count filled slots, not distinct addresses.
function getStats() external view returns (HStats memory);
Returns
| Name | Type | Description |
|---|---|---|
<none> | HStats | platformStats The platform-wide statistics. |