ICO Launchpad 6.2.0
29 July 2026
This release has upgrade notes. Read them before updating — they describe behaviour changes that need your attention.
Token ICO v6.2.0
Release Date: July 29, 2026 Tags: SECURITY, MONEY FLOW, ESCROW, LIFECYCLE, KYC, ADMIN, SETTINGS, LANDING PAGE, THEME, CHARTS, ANNOUNCEMENTS, CLEANUP
Overview
Version 6.2.0 repairs the money path end to end. Before it, an ICO could take a contribution but could never pay it out or give it back: verifying and rejecting both failed outright, and the funds stayed on the platform wallet with no way out. Separately, every sale that ended was judged against a total that excluded the very contributions it had collected, so a fully-funded offering closed as a failure — and the failure path then moved those contributions into a state no refund would act on.
The whole addon also went through an appearance pass: every ICO screen — public, investor and admin — now draws from the platform's own theme instead of the hardcoded teal and grey it shipped with. The public landing page was rebuilt, and the security and compliance claims it made on your behalf — SEC compliance, full regulation, bank-grade encryption, 24/7 support — were removed. This is white-label software and those were not claims to make for someone else.
Three of the steps below look for records a past failure has already left wrong. Run them.
Requires Core v6.5.8.
Update Instructions
pnpm updatorThen, in this order:
1. Restart the backend
The lifecycle cron, the refund authority and the numeric DECIMAL getters all load at boot.
pm2 restart all2. Find contributions stranded by the escrow collision
Any offering whose transactions are stuck in VERIFICATION was hitting the unique-reference collision every time an admin pressed verify or reject. They can simply be retried now — no data repair is needed. To see how many you have:
SELECT o.name, COUNT(*) AS stuck, SUM(t.amount * t.price) AS held
FROM ico_transaction t
JOIN ico_token_offering o ON o.id = t.offeringId
WHERE t.status = 'VERIFICATION'
GROUP BY o.id;3. Find investors stranded by a past "failed" offering
Contributions the old lifecycle marked REJECTED were unreachable by every refund door. The refund authority now picks them up, but only when a refund is triggered. List them, then run Emergency Cancel & Refund on each offering from the admin offer screen, or POST /api/ico/refund/process:
SELECT o.id AS offeringId, o.name, o.status, COUNT(*) AS owed,
SUM(t.amount * t.price) AS amount
FROM ico_transaction t
JOIN ico_token_offering o ON o.id = t.offeringId
WHERE t.status = 'REJECTED'
AND NOT EXISTS (
SELECT 1 FROM transaction x
WHERE x.referenceId IN (CONCAT(t.id, '_refund'), t.id)
AND x.type = 'REFUND' AND x.status <> 'FAILED'
)
GROUP BY o.id;Refunds are idempotent: a contribution that already has a refund ledger entry is skipped, so re-running is safe.
4. Re-check your investment limits
The admin Investment Limits endpoints were writing to setting keys nothing read. They now read and write the same keys the purchase route enforces (icoMinInvestmentAmount, icoMaxInvestmentAmount). Open the ICO settings screen and confirm the values shown are the ones you intend — until now they were decorative.
If you had set a soft cap, set it again: icoSoftCapPercentage is now honoured (it previously stored a value that no code read).
Upgrade Notes
None in setup. Two behaviour changes worth knowing:
- Changed: a failed offering now refunds immediately when it is closed, rather than parking contributions in a stranded state.
- Changed: a link to a missing offering now returns a proper "not found" instead of a blank page reported as a success.
Changed
The whole addon now follows the platform theme
Every ICO screen — public, investor and admin — changes appearance. Nothing moved and no labels changed; this is presentation only.
- Colours: hardcoded teal, cyan and grey values were replaced with the platform's own theme colours. An operator who has re-themed the platform now sees the ICO addon follow their palette, which it previously ignored, and both light and dark themes render correctly.
- Status badges: offering and contribution states now use the same badge colours as the rest of the platform, so a "pending" here looks like a "pending" everywhere else.
- Stat tiles and charts: these now use the platform's shared versions, so spacing, typography and chart colours match.
- Surfaces: gradients and drop shadows gave way to flat surfaces.
The public landing page was rebuilt, and its unverifiable claims removed
The landing page is materially different. It now uses the shared landing layout with a single responsive offerings grid, and it no longer makes claims about your business that only you can make.
- One grid instead of four layouts: the page carried separate hand-written layouts for one, two, three and many projects. A single grid now handles any number.
- Claims removed: the trust bar and feature copy no longer assert "SEC Compliant", "SEC Guidelines", "Fully Regulated Platform", "Bank-Grade Security", "256-bit encryption" or "24/7 Support" on your behalf.
- Replaced with what the product actually does: issuer verification before listing, audited contracts with published reports, and funds returned when a soft cap is missed.
The investor dashboard now carries the full portfolio panel
The dashboard's portfolio chart was a single static line with no title and no controls. It has been replaced by the richer panel already used elsewhere in the addon:
- Timeframe selector: 1W, 1M, 3M, 1Y and ALL.
- Value tiles: initial investment, current value, and profit and loss.
- Tabs: performance over time, and asset allocation by token.
The old single-purpose chart was removed.
Fixed
The launch-fee balance check compared numbers as text
Balances were compared as text rather than as numbers. On a live database, a creator holding 126,944 USDT was refused a 1,999 USDT launch fee — while a creator holding 9 USDT sailed straight through, launched an offering for free, and was left with a balance of −1,990.
- Fixed every money comparison in the addon to be numeric, so the same mistake cannot be made again.
Refunds could be issued twice through different doors
Four different refund paths each recorded the same event differently, so a repeat could not be recognised. An admin rejection followed by an offering cancellation paid the same investor twice — and the second payment came out of the platform's own funds.
- Fixed the four paths into one refund authority, where an existing refund against a contribution is treated as proof it has already been paid — including refunds recorded by older versions.
The refund action created money
The refund action credited the investor without taking the money back out of escrow. Every refund it issued was paid out of platform funds while the contribution stayed in escrow. It was also callable by the offering owner, not only by admins.
- Fixed every refund to come from the escrow that has been holding it.
Launching a token sale is now checked against KYC on the server
The KYC requirement for launching an offering existed only as a screen in the launch wizard. Anyone who bypassed the wizard and submitted the offering directly created it without ever being checked.
- Fixed the server to apply the same check the screen showed.
- Applies to installs that have both KYC and per-feature KYC enforcement switched on. There, a creator who is unverified — or whose verification level does not carry ICO creation — is now refused with a permission error instead of creating an offering. Installs that have not switched on per-feature enforcement see no change.
Verifying or rejecting a contribution was impossible
Both actions failed with a database error every time. A seller could not be paid and a buyer could not be refunded — money went into escrow and stayed there.
- Fixed each stage of a contribution to record itself separately, so they can coexist. Existing contributions are unaffected and can simply be retried.
A fully-funded sale was closed as a failure
The automatic closing check ignored every contribution that had been paid but whose tokens had not yet been distributed — which is the normal state of every contribution until the creator sends tokens and an admin verifies. So a sale that had collected its entire target measured as having raised nothing, and was closed as failed. The progress bar the investor saw counted those same contributions, so the screen and the verdict disagreed on the same page.
- Fixed the definition of "raised" to one shared by the automatic closing, the soft-cap and hard-cap checks and the public progress figures alike.
A failed sale left every investor with no way to get their money back
On failure, every live contribution was moved into a state that all three refund paths refused to act on. The one piece of code that handled it was never scheduled and was used by nothing. The refund action answered "No transactions found for refund".
- Fixed a failed sale to refund its contributions at the moment it is marked failed. The manual refund paths accept the older stranded contributions too, so money already caught by this can be recovered (see update step 3).
The hourly lifecycle job reported a green run while settling nothing
The hourly ICO job caught any failure in its settlement stage, wrote it to the log, and then reported the run as completed with 100% success. That stage does all the real work — deciding whether an ended sale succeeded or failed, and paying refunds — so an operator watching the scheduled jobs screen could see clean runs indefinitely while not one ended offering was being closed.
- Fixed a failing sweep to be reported as failed, with the message naming the offerings that failed.
An "offering ended" notification could announce a settlement that never happened
The creator's "your offering has ended" notification was raised while the settlement was still being written, and notifications are recorded separately from it — so the notification survived even when the settlement was undone. If anything later in the sweep failed, a creator could be told their sale had closed as a success or a failure while the offering was in fact still running.
- Fixed the notification to be sent only once the settlement is final, and a notification failure no longer aborts the settlement.
Three different soft caps
Three parts of the system used 75%, 30% and 30% respectively. A sale that raised half its target simultaneously "passed" the soft cap and was closed as a failure. None of the three read the soft cap you had configured.
- Fixed the three to one threshold, read from your setting and defaulting to 30%.
The launch fee was destroyed rather than collected
The fee was taken with a direct balance write. There was no entry in the creator's transaction history to explain the drop, and no credit anywhere — so every launch fee the platform "charged" simply vanished.
- Fixed the fee to be charged properly and paid to the platform wallet, like every other fee.
Pausing an offering did nothing
The paused state was shown on every screen and read by no money path. A paused offering kept accepting contributions.
- Fixed a paused offering to refuse contributions.
An admin note destroyed the purchase record
The note field also holds the purchase details — amount invested, fee, phase, the linked ledger entry. Save note replaced all of it with free text. Afterwards the creator could not distribute tokens for that contribution at all, and refunds silently skipped it. Rejection and emergency cancellation overwrote it the same way.
- Fixed a note to be added alongside the record rather than replacing it. Remove note clears the note and leaves the purchase details. A note left by an older version is preserved.
Rejected and refunded tokens were burned
A rejected contribution returned the buyer's money but never returned its tokens to the phase that sold them, so that allocation was consumed permanently and could never be sold to anyone else. Refunds returned supply to the first phase regardless of which one had actually sold.
- Fixed the phase to be recorded at purchase, so both rejection and refund return supply to the phase the tokens came from.
The participant count only ever went up
An offering that had returned everyone's money still advertised its full head count.
- Fixed the count to be recalculated whenever a contribution is reversed.
Refunded money still counted as raised
Money already handed back inflated the progress bar and the landing-page totals.
- Fixed progress to count only contributions the offering actually holds.
Verified investors were told to complete verification they had already completed
The offering detail page and the launch wizard each carried their own KYC check. An approved investor whose verification level simply did not include ICO purchases was told to "Complete Verification" and sent to a verification page already showing 100% complete. Logged-out visitors — and every user for the moment a page was still loading — were shown the same KYC wall instead of a sign-in prompt.
- Fixed both screens to use one shared gate. An approved user whose level does not carry the feature reads that a higher verification level is required; a logged-out visitor is treated as a sign-in problem; nothing is shown while the page is still loading.
- Fixed: the wall now appears only when per-feature KYC enforcement is actually switched on, which is what the server enforces. On installs that have KYC enabled but have never curated which features each verification level carries, users who were previously locked out of the offering page can now reach it.
Both investment-limit screens were unreachable, and saved settings nothing read
Three separate faults on the same pair of screens. They checked for role names that do not exist on this platform, so they answered "Admin privileges required" to every real administrator. They saved to different settings than the ones the purchase page enforces. And nothing in the interface called them at all. The values they stored for the soft cap, refund grace period and vesting were read by nothing.
- Fixed the role check to match the real roles — which also restores the admin refund action and the refund-eligibility view, both of which had the same fault. The screens now read and write the settings that are actually enforced, and the soft cap is honoured.
The purchase form ignored the configured maximum
The amount slider was capped at 10% of the offering's target — unrelated to your configured maximum — so on a small offering the maximum could fall below the minimum and the slider became unusable. An over-limit amount was submitted and only rejected afterwards. And where no minimum was configured, the form rejected every amount with "Minimum investment is $NaN".
- Fixed both limits to be read correctly, enforced, and reflected in the slider.
A mail failure was reported as a failed purchase
An email hiccup returned an error to a buyer whose wallet had already been charged and whose tokens had already been allocated — and skipped the notifications and affiliate rewards that follow.
- Fixed a mail failure to be logged rather than reported as a failed purchase.
A configured zero was silently replaced by the default
An operator who set the minimum investment — or the platform fee — to 0 got the built-in default back instead.
- Fixed the fallback, so a value you set is the value that applies.
The creator earnings chart failed for every creator, and took the stats page with it
Every creator who opened their performance chart got a server error. The date grouping behind it was malformed for every time range, so no range worked and no creator ever saw the chart. Worse, the chart shared one loading and error state with the rest of the screen, so the whole creator stats page collapsed to "Error loading stats" — the stat tiles included.
- Fixed the chart and the stat tiles to both load, with the chart carrying its own state: a later failure to fetch chart data is reported inside the chart's own card, while the rest of the creator dashboard keeps working.
An offering's investor list showed figures from the administrator's own account
On the admin screen for a single offering, the summary figures above the investor table were calculated from the signed-in administrator's personal ICO contributions rather than from the offering being viewed. They were usually zeros, and always unrelated to the rows underneath them.
- Fixed the headline figures to describe the offering.
A landing-page outage told every visitor there were no offerings
When the landing data failed to load, the page rendered normally with an empty offerings section and a "be the first to launch" invitation — so during an outage the platform silently told every visitor it had no projects at all. The page had an error state, but it could never be reached.
- Fixed a failure to be shown as a failure.
A missing offering was reported as a success
Opening a link to an offering that does not exist rendered a blank offering page rather than a "not found" page, and was recorded as a successful request.
- Fixed it to return a proper "not found".
The announcement banner sat on top of the page hero
On installs with an ICO announcement configured, the banner was pinned near the top of the page and landed across the hero title and stat row of every ICO screen, making both unreadable and unclickable. The offset was a guess at one particular header height, so the overlap moved whenever the page above it changed.
- Fixed the banner to be a dismissible bar docked to the bottom of the screen that reserves exactly its own height, so it covers nothing — not the hero, not the footer links — and stays reachable while the visitor scrolls.
A switched-off toggle was being read as switched on
An operator who turned the ICO announcement off carried on showing it to every visitor. On the same reading fault, the launch requirements panel told prospective issuers that KYC verification was a launch requirement no matter how the operator had configured it.
- Fixed a setting that is turned off to be read as off, and the KYC requirement line to appear only when the requirement is actually configured.
Completed offerings displayed an invented loss
On the completed-offerings list, any project whose token has no market price showed a red falling-arrow chip reading just "%" — an invented loss on a sale that had actually succeeded. Nothing in the addon supplies a price-change figure at all, so this hit every completed offering.
- Fixed the chip to be omitted unless there is a real number to show.
The token simulator's Market Cap view drew an axis for a line that was never there
In the creator token simulator, the Market Cap view showed a second axis and a legend entry for circulating supply, with no line on the chart to match them.
- Fixed the circulating-supply series to render.
"Validation error" with no explanation
- Fixed the admin transaction actions reporting every failure as the bare string "Validation error". They now say what actually failed — which is how the escrow collision above was finally identified.
Token types displayed as raw identifiers on the landing page
Every offering created through the current launch flow showed a raw database identifier in place of its token type name. The page then filtered those out and reported the reduced count as authoritative — so it hid the correct offerings and counted only older ones.
- Fixed token types to be resolved to their real names, with counts merged by name so two entries sharing a name after a rename combine correctly. A type that has been deleted is dropped rather than printed.
Amounts printed without a currency
- Fixed the target amount on upcoming offerings and the total raised figure being shown without their currency, leaving the reader to guess. This is white-label software and the guess is wrong on most installs. Both now carry the offering's own currency.
Smaller corrections
- Fixed the admin ICO settings screen sitting lower and narrower than every other section — it applied its page padding twice and centred its content twice. It now matches every other admin section, and the admin transaction screen, which had the same fault, was corrected with it.
Removed
Two unreachable modules. Neither was running, and removing them changes no behaviour.
The old refund manager
This was the previous refund implementation, fully superseded by the single refund authority every live path now goes through — automatic closing, the refund action, and the admin emergency cancel-and-refund all use it.
The consolidation is what fixed two defects the older module was written around, and both fixes live on in the surviving code: a contribution marked rejected when an offering missed its soft cap can still be refunded, and every refund comes from escrow rather than being created out of nothing.
Keeping a second, conflicting settlement path alongside the authority was the risk: the removed module used a 30% soft cap while the old closing check used 75%, so if both had ever run they would have disagreed about which offerings failed and settled them twice.
The vesting scaffolding
Token vesting has never existed as a working feature. Its storage was empty by construction, and it could not be enabled by wiring:
- Only milestone schedules ever created release entries, so linear and cliff schedules could never pay out at all.
- There was no way to define a schedule in the first place.
- Its custody model contradicts the shipped product. Real distribution is manual and on-chain to the investor's own verified wallet; the module instead credited an internal platform balance in a currency the platform does not hold.
Delivering vesting is a feature project, not a reconnection of this code, so it was removed rather than wired.