Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Henriable

Git Source

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

NameTypeDescription
initialOwneraddressThe address that will own the contract.
ownerUsdToken_IERC20The USDC token used for investments, payouts and payments.
vehicleNft_HenriableVehicleNFTThe 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

NameTypeDescription
_owner2addressThe 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

NameTypeDescription
_assetHAssetThe 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

NameTypeDescription
_assetIdbytes32The id of the asset to update.
_statusboolThe 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

NameTypeDescription
_investmentIdbytes32Unique, non-zero id of the new investment slot.
_assetIdbytes32Id of the asset to invest in; must exist and be active.
_riderInitialBuyinUsduint256Initial rider buy-in, in USDC base units (6 decimals); must be non-zero. Callers pass base units (frontend: parseUnits(x, 6)).
_periodicRiderPayingInMinutesuint256Length of a rider period, in minutes; must be non-zero.
_minimumRiderPeriodicPayingsUsduint256Minimum 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

NameTypeDescription
_investmentIdbytes32The id of the investment to update.
_statusboolThe 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

NameTypeDescription
_investmentIdbytes32The id of the investment to schedule.
_startTimeuint256Timestamp at which the next investment round starts; must be in the future.
_endTimeuint256Timestamp 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

NameTypeDescription
_investmentIdbytes32The 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

NameTypeDescription
_investorHInvestorThe investor profile (name, country, age) to create or update.
_investmentTypeHInvestmentTypeThe tier to invest in (Senior or Junior).
_investmentIdbytes32The id of the investment to invest in.
_approvedUSDAmountuint256The 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

NameTypeDescription
_investmentIdbytes32The id of the investment to schedule.
_startTimeuint256Timestamp at which the next hire-request round starts; must be in the future.
_endTimeuint256Timestamp 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

NameTypeDescription
_investmentIdbytes32The 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

NameTypeDescription
_namebytes32The rider’s name; must be non-zero.
_countrybytes32The rider’s country; must be non-zero.
_ageuint8The rider’s age; must be at least 18.
_approvedInitialBuyinuint256The USDC the rider approved, in USDC base units (6 decimals); must cover the required buy-in. Callers pass base units.
_investmentIdbytes32The 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

NameTypeDescription
_investmentIdbytes32The id of the investment whose rider is being chosen.
_riderAddressaddressThe 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

NameTypeDescription
_investmentIdbytes32The id of the investment whose rider payment is extended.
_newNextPayinDateuint256The new timestamp at which the rider’s next payment is due; must be later than the investment’s current next-payment date.
_slashAmountuint256Amount 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

NameTypeDescription
_investmentIdbytes32The id of the investment being paid.
_approvedUSDuint256The 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

NameTypeDescription
_rideraddressThe rider receiving ownership; must be the investment’s hired rider.
_investmentIdbytes32The 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

NameTypeDescription
<none>HStatsplatformStats The platform-wide statistics.