Trust Bitcoin Info

Trust Bitcoin has an edge in DeFi services because of its best-in-class offerings. With the likes of services like mining, smart contracts, digital wallets, governance and creating dApps. Also, miners will have exceptional benefits for adding a block to the Trust Bitcoin blockchain.

Trust Bitcoin Logo

Team and KYC Verification

The team has securely submitted their personal information to SolidProof.io for verification.

In the event of any fraudulent activities, this information will be promptly reported to the relevant authorities to ensure accountability and compliance.

TrustNet Score

The TrustNet Score evaluates crypto projects based on audit results, security, KYC verification, and social media presence. This score offers a quick, transparent view of a project's credibility, helping users make informed decisions in the Web3 space.

12.57
Poor Excellent

Real-Time Threat Detection

Real-time threat detection, powered by Cyvers.io, is currently not activated for this project.

This advanced feature provides continuous monitoring and instant alerts to safeguard your assets from potential security threats. Real-time detection enhances your project's security by proactively identifying and mitigating risks. For more information, click here.

Security Assessments

Select the audit
"\"\\\"Static Analysis Dynamic Analysis Symbolic Execution SWC Check Manual Review\\\"\""
Contract address
N/A
Network N/A
License N/A
Compiler N/A
Type N/A
Language Solidity
Onboard date 2025/08/20
Revision date 2026/08/04

Summary and Final Words

No crucial issues found

The contract does not contain issues of high or medium criticality. This means that no known vulnerabilities were found in the source code.

Contract owner cannot mint

It is not possible to mint new tokens.

Contract owner cannot blacklist addresses.

It is not possible to lock user funds by blacklisting addresses.

Contract owner cannot set high fees

The fees, if applicable, can be a maximum of 25% or lower. The contract can therefore not be locked. Please take a look in the comment section for more details.

Token transfer can be locked

Owner can lock user funds with owner functions.

Token cannot be burned

There is no burning within the contract without any allowances

Ownership is not renounced

The owner retains significant control, which could potentially be used to modify key contract parameters.

Contract is not upgradeable

The contract does not use proxy patterns or other mechanisms to allow future upgrades. Its behavior is locked in its current state.

Scope of Work

This audit encompasses the evaluation of the files listed below, each verified with a SHA-1 Hash. The team referenced above has provided the necessary files for assessment.

The auditing process consists of the following systematic steps:

  1. Specification Review: Analyze the provided specifications, source code, and instructions to fully understand the smart contract's size, scope, and functionality.
  2. Manual Code Examination: Conduct a thorough line-by-line review of the source code to identify potential vulnerabilities and areas for improvement.
  3. Specification Alignment: Ensure that the code accurately implements the provided specifications and intended functionalities.
  4. Test Coverage Assessment: Evaluate the extent and effectiveness of test cases in covering the codebase, identifying any gaps in testing.
  5. Symbolic Execution: Analyze the smart contract to determine how various inputs affect execution paths, identifying potential edge cases and vulnerabilities.
  6. Best Practices Evaluation: Assess the smart contracts against established industry and academic best practices to enhance efficiency, maintainability, and security.
  7. Actionable Recommendations: Provide detailed, specific, and actionable steps to secure and optimize the smart contracts.

A file with a different Hash has been intentionally or otherwise modified after the security review. A different Hash may indicate a changed condition or potential vulnerability that was not within the scope of this review.

Final Words

The following provides a concise summary of the audit report, accompanied by insightful comments from the auditor. This overview captures the key findings and observations, offering valuable context and clarity.


Smart Contract Analysis Statement

Contract Analysis

The TBCDistributionPlan contract implements a staged distribution and peer-to-peer resale system for the native TBC coin, settled in the AUSD accounting token. Buyers purchase one of six fixed packages at one of five price stages, receive native TBC directly to their wallet, and may allocate part of the purchase into resale positions at higher stages that later buyers fill through a first-in-first-out queue. Layered on top is a referral programme paying ten levels, together with working, royalty, foreign-tour and monthly sales bonuses. The contract is the second generation of the design and is built to import users, balances and resale positions from the version currently live on chain. At the time of this review it is deployed but not yet initialised - the sale is closed, no participants have been migrated and the contract holds no funds - so every observation below can still be acted on before value is at risk.

The review combined a line-by-line reading of the source with deterministic analysis, symbolic reasoning, coverage-guided fuzzing and a purpose-built set of executable proofs, and the results were then checked a second time against an independent peer review. Forty findings are recorded, of which one is critical and six are high. The project team has responded to fourteen of them in writing; five were downgraded on the strength of those replies, three are now closed, and the team's position is recorded against each. A further eight entries from the previous issue were consolidated away - three because they could not be supported on re-examination, five because they duplicated a fix already required elsewhere. Nothing was reduced in severity to shorten the list; the critical, high and medium findings stand exactly as assessed. The most significant concern the resale queue and the migration path, and they compound one another: the queue erases a resale position in full when the owner's deposited balance does not cover it, while the migration imports every position from the old contract but leaves the deposited balance behind. Taken together these mean that the roughly 115,000 positions being carried over would be destroyed without payment shortly after the sale opens. The underlying TBC remains recoverable from the old contract, which still holds more than 1.1 million TBC and whose withdrawal function is open to anyone, but the resale entitlement itself would be lost.

Three further items are worth singling out. The migration never assigns a sponsor to the first account it imports, and because the referral structure is a single tree, every sponsor that account could later name is necessarily one of its own descendants - so the moment the top of the tree makes an ordinary purchase, a permanent loop forms in the sponsor graph that nothing in the contract can undo. A measured purchase of one hundred units wrote twenty-five thousand six hundred units of monthly sales onto each of the two accounts involved and added a lasting surcharge of more than five times to the cost of every purchase beneath them. Separately, the old contract is still open for business and was observed taking on a further two thousand eight hundred and ninety-five units of deposits during this review, while the import runs across many transactions and reads it live, so it cannot capture a consistent picture. And an escape hatch in the supply check allows the smallest package to be bought without limit once a stage's allocation reaches zero, a condition that already holds for the first stage on chain today.

Ownership Privileges

The ownership of the contract has been retained by a single externally owned account, with a second externally owned account holding an independent and in several respects more powerful set of privileges. Neither is a multi-signature wallet; all five privileged addresses were confirmed on chain to have no contract code. There is no timelock on any privileged action, no role hierarchy and no two-step ownership transfer. The owner retains full privileges including:

  • Seeding arbitrary user balances, referral relationships and resale positions during migration, before the sale is opened.
  • Importing stage allocations, queue pointers and stage activation flags wholesale from the previous contract without validation.
  • Opening the sale, which is a one-way action that simultaneously and permanently closes every migration function.
  • Transferring or renouncing ownership outright, in one step and with immediate effect.
  • The funding wallet, which is a separate account, can withdraw the entire protocol-owned TBC pool at any time, sweep any excess native balance, and replace the validator, none of which the owner can override or undo.
  • That same funding wallet is also the owner of the AUSD settlement token, and can therefore block any participant, block the distribution contract itself, and destroy the settlement balance of anything it has blocked.
  • The funding, treasury and burn wallets cannot be changed after deployment, so a lost or compromised key among them cannot be replaced and would require a full redeployment and re-migration.
  • There is no pause and no emergency stop of any kind, so once the sale is open there is no way to halt activity while a problem is investigated.

Project Team Response

The project team reviewed the findings and replied to fourteen of them. Several replies were well founded and changed our assessment. Their explanation of the preferred-seller allocation model, of the validator pricing arrangement, of the one percent payout deduction and of the decision to carry only the active reward period across were each accepted, and the corresponding findings were reduced in severity or reclassified as documentation requirements. Their statement that no account can exist in the old contract without a completed purchase was tested against one hundred randomly chosen holders and held in every case.

Two positions we were unable to accept, and in both cases the evidence is straightforward to reproduce. The team expected the sell-queue pointer problem to disappear once the migration finishes; the old contract holds a pointer for a stage whose position list is empty, so there is nothing to import and finishing the migration cannot resolve it, while renouncing ownership afterwards would make it permanent. The team also understood the chain to support only one specific compiler version; the contract compiles unchanged on a current version when the target instruction set is pinned appropriately, producing a smaller runtime with no instruction the chain lacks. A remaining possibility is that the deployment tooling or the block explorer's source verifier imposes the limit, which would be a different problem with different remedies.

One proposal was implemented and tested rather than assessed on paper. The team's approach to the referral-root problem does prevent the defect it targets, but as described it leaves the root account unable to purchase beyond a low threshold, because a bonus payment is routed to an address the settlement token refuses. A single additional guard completes it. Two claims of our own were withdrawn in the course of this exchange, both after testing showed them to be overstated.

Security Features

The contract is not without deliberate defensive work, and several of the improvements made since the previous review are genuine:

  • A single reentrancy guard covers every value-moving entry point, and the two native transfer paths both check their return value rather than ignoring it.
  • The contract is not upgradeable and contains no proxy, no initializer and no reachable delegate call, which removes an entire class of upgrade and storage-collision risk.
  • Arithmetic is fully checked throughout - the contract contains no unchecked blocks at all - and the payout split, the royalty calculation, the stage pricing and the native deposit and withdrawal paths were each proved correct across their full input range.
  • Payment failures caused by a blocked burn wallet, a blocked treasury or an empty contract balance no longer abort a purchase; the earlier versions of these paths could freeze the protocol and now degrade instead.
  • The monthly reward claim was rebuilt to top up to the highest tier a participant reaches rather than locking in the first one claimed, which closes the front-running problem raised previously.
  • All fee and reward parameters are fixed in code with no setter of any kind, so no privileged account can raise a fee after launch. Note that this cuts both ways: the resale community deduction is fixed at forty to fifty percent and cannot be lowered either.
  • Every loop is bounded, and the batch entry points cap their input at fifty entries per transaction.

Note - This Audit report consists of a security analysis of the TBCDistributionPlan smart contract. This analysis did not include economic analysis of the contract's tokenomics. Moreover, we only audited the main contract for the TBCDistributionPlan team. Other contracts associated with the project were not audited by our team, although the AUSD settlement token and the previous version of the distribution contract were examined to the extent that their behaviour determines the security of the contract in scope. We recommend investors do their own research before investing.

Files and details

Findings and Audit result

critical Issues | 1 findings

Acknowledged

#1 critical Issue
Migration Imports Every Sell Position But Silently Drops The Deposited Balance
TBCDistributionPlan.sol
L763
L765-776
L788-809
Description

The migration routine unpacks the old contract's user record and skips the eleventh value, which is the deposited TBC balance. At the same time the position migration routine faithfully imports every single resale position. The result is that every migrated participant arrives with a fully populated set of positions backed by a zero deposit, which is precisely the state that triggers the uncompensated position wipe. This is not theoretical. The old contract currently holds 1,104,044.79 TBC on chain, its own accounting reports 1,101,715.29 TBC of that as user deposits, and the two figures reconcile exactly. The old contract does implement deposit and withdrawal of TBC, so the earlier explanation that it had no such flow and therefore nothing to migrate does not hold. The scale is large: 38,691 positions at stage 2, 37,351 at stage 3 and 38,715 at stage 4, which is 114,757 in total. Because the queue scan covers up to 512 entries per purchase and an unfunded entry never reduces the sell limit, a single purchase can destroy 512 positions at once. Every participant carried over from the old system therefore loses their whole resale entitlement shortly after launch.

high Issues | 6 findings

Pending

#1 high Issue
Under-Funded Sell Positions Are Erased In Full Without Compensation
TBCDistributionPlan.sol
L488-510
L328-346
Description

When the resale queue reaches a position whose owner has deposited less than the slice a buyer wants from it in that transaction, the contract pays for whatever deposit is left and then deletes the whole remaining position. The slot is set to zero and the seller's stage balance is reduced by the full remaining position, while payment covers only the part that was backed. The difference disappears from state with no payment, no record and no event, and once a slot has been zeroed it is skipped forever. The damage scales with the ratio rather than with the shortfall: a position of five thousand backed by one hundred loses four thousand nine hundred, while the same position backed by four thousand nine hundred and fifty loses only the fifty that was missing. A migrated account sits at a deposit of zero, which is the worst case. That this is a defect rather than a deliberate rule is clear from the preferred seller loop, which handles the same situation correctly by capping the fill and leaving the remainder in the queue - the two code paths disagree and only the general one destroys value. One clarification that an earlier issue of this report got wrong: a seller who backs the sum of all their positions is safe, because selling one position down reduces the deposit by exactly what was sold and leaves the others fully covered.

Pending

#2 high Issue
Smallest Package Bypasses The Per-Stage Supply Cap Entirely
TBCDistributionPlan.sol
L210-215
Description

The supply check contains an escape hatch for the smallest package. The intent is clearly to let a final buyer sweep up a leftover that is smaller than the minimum package size, but the condition never verifies that a leftover exists. Once the remaining allocation for a stage reaches zero, every purchase of the smallest package satisfies the condition and simply re-zeroes the counter, so the stage can be bought from without limit. This matters immediately. The old contract reports zero remaining allocation for stage 0 while still flagging it active, and the stage import copies both values across verbatim. From the moment migration completes, stage 0 - the cheapest stage at one AUSD per TBC - is permanently open to unlimited 100 AUSD purchases, bounded only by the protocol's own TBC pool and the resale queue. Stage 1 is in the same position, since its remaining allocation of five TBC is less than the ten TBC that even the smallest package buys there. The staged supply schedule, which is the core of the distribution model, is therefore not enforced at all, and each such purchase additionally creates referral, working, royalty and monthly reward liabilities.

Acknowledged

#3 high Issue
Migrated Queue Pointer Strands Every Newly Created Sell Position
TBCDistributionPlan.sol
L811-821
L469-475
Description

The stage import copies the old contract's queue pointer across without checking that the corresponding positions were actually imported. On chain the old contract reports a stage 1 queue pointer of 4,118 while its stage 1 position array is empty, so the new contract inherits a pointer of 4,118 over an empty queue. New positions created after launch are appended starting at index zero, and the queue loop begins at the inherited pointer, so while fewer than 4,118 positions exist the loop body never executes at all, and even after that the first 4,118 entries can never be reached. Buyers at stage 1 will therefore pay for a resale entitlement that the queue can never fill. The only remaining route to sell is to be nominated as preferred seller by another buyer, which is capped at twenty percent of a trade and depends entirely on someone else's goodwill.

Acknowledged

#4 high Issue
A Single Externally Owned Account Can Freeze The Protocol And Destroy Its Settlement Balance
TBCDistributionPlan.sol
L1-1027
Description

The settlement token applies its blocking check to the caller as well as to the sender and the receiver. The distribution contract is the caller of every settlement token movement it performs, so blocking the distribution contract makes purchases revert at the very first transfer and turns every payout into a silent no-op. The same owner can then use the burn function to destroy the contract's settlement balance outright. The account holding this power is a plain externally owned account with no code, verified on chain. It is simultaneously the settlement token owner, the distribution contract's funding wallet, the sole source of bonus liquidity, and the only address able to withdraw the protocol's TBC pool, sweep excess native balance and rotate the validator. The distribution contract provides no way to replace it. One compromised or coerced key is therefore enough to shut the protocol down completely and confiscate the settlement balance, with no recovery path, because the contract is not upgradeable and the wallet is not replaceable.

Acknowledged

#5 high Issue
Migrated Root Closes A Permanent Sponsor Cycle On Its First Purchase
TBCDistributionPlan.sol
L180-187
L573-582
L584-606
Description

The migration never assigns a sponsor to its first entry, so the root of the whole referral tree keeps an empty sponsor forever. The purchase function treats an empty sponsor as an unregistered buyer and assigns whatever sponsor the caller names, with no check that the candidate is not already below the buyer in the tree. Because there is exactly one tree and the root sits at the top of it, every valid sponsor the root could possibly name is by construction one of its own descendants. The consequence is that the root's first purchase, which is an entirely ordinary thing for it to do, closes a cycle in the sponsor graph. Nothing can undo it, because there is no function anywhere that rewrites a sponsor. The effects are immediate and permanent. The upline walks only stop at an empty sponsor or after five hundred and twelve iterations, so they now always run the full five hundred and twelve. A single purchase of one hundred units was measured writing twenty-five thousand six hundred units of monthly sales onto each of the two accounts in the cycle, an amplification of two hundred and fifty-six, which corrupts the figures that drive the monthly reward tiers and the working bonus qualification. Every later purchase anywhere beneath the cycle was measured costing seven hundred and sixty-four thousand gas more than the same purchase before the cycle formed, a permanent surcharge of more than five times. The referral distribution also revisits the same two accounts five times each instead of paying ten distinct uplines.

Acknowledged

#6 high Issue
Migration Reads A Moving Target Because The Old Contract Is Still Live
TBCDistributionPlan.sol
L737-786
L788-809
L811-821
Description

The three migration functions read the old contract live, and they must be called many times because there are close to one hundred and fifteen thousand positions to import. The old contract is still open for business: its sale flag is set, its ownership has been renounced so nobody can stop it, and its deposit function is available to anyone. Its user pool was measured growing by two thousand eight hundred and ninety-five units between the start of this review and its conclusion, so the growth is not theoretical. The migration therefore does not capture a consistent snapshot - early batches see one state and later batches see another, and there is no mechanism anywhere that detects or reconciles the difference. Two distinct problems follow. Balances and positions imported in different batches can be mutually inconsistent, for example a position imported before its owner topped up and a stage total imported afterwards. And every deposit made in the old contract after the final batch is simply never seen, leaving those participants with holdings in a contract the project has moved away from and no corresponding record in the new one.

medium Issues | 9 findings

Acknowledged

#1 medium Issue
Blacklisted Sellers Lose Their Deposited TBC Because The Payment Result Is Ignored
TBCDistributionPlan.sol
L344
L360
L452
L508
L526
L637-679
Description

The internal payment helper was deliberately rewritten to return a failure flag instead of reverting, which was the right answer to the liveness problems raised in the previous review. The problem is that every call site in the resale loops throws that flag away. By the time the payment is attempted the position has already been reduced, the sold total incremented and the seller's deposit decremented, and the caller is about to reduce the users pool and hand the matching native TBC to the buyer. The seller therefore loses their TBC unconditionally and gets paid only if the transfer happened to work. In the ordinary flow the buyer's own payment always covers the seller, so the practical trigger is the settlement token blacklist: once a participant is blocked, the next purchase that reaches their queue position takes their deposited TBC and pays nothing. All they are left with is an increase in their recorded sale proceeds, and the withdrawal function uses the same helper, so they cannot redeem it while the block is in place. If the block is never lifted the credit is worthless, and the TBC that was handed to the buyer is gone either way.

Pending

#2 medium Issue
Wipe Accounting Can Underflow The Stage Allocation And Permanently Brick A Stage
TBCDistributionPlan.sol
L494
L333
L213-214
L289
Description

The position wipe reduces the remaining stage allocation by the destroyed remainder while still inside the resale loop, before the caller performs its own subtraction for the size of the purchase. When a stage has a small remaining allocation but a long unfunded queue at its head, the in-loop reduction leaves less than the purchase requires and the caller's subtraction underflows, reverting the whole transaction. Because it reverts, the queue pointer is rolled back too, so the next purchase meets exactly the same positions and fails identically. The validator purchase path has the same shape: it validates the remaining allocation before calling the resale routine, which then reduces the very counter that was just validated. The practical effect is that a stage can become permanently unbuyable for every package except the smallest, and the smallest only works because of the separate supply cap bypass. The conditions arise naturally after migration, where the queue is long and unfunded.

Acknowledged

#3 medium Issue
Accrued Rewards Are An Unbacked Liability With No Reserve
TBCDistributionPlan.sol
L637-679
L920-931
L933-942
Description

Every bonus path credits the recipient's earnings before attempting payment and leaves that credit in place if the payment fails. The pending reward figure is simply the difference between the earnings buckets and the amount already claimed, and the withdrawal function pays it from the contract balance if there is one and otherwise pulls from the funding wallet. Nothing reserves settlement tokens against these claims, nothing tracks the aggregate outstanding balance, and nothing stops the treasury sweep at the end of each purchase from removing the very tokens that would have covered them. Solvency therefore rests entirely on the funding wallet voluntarily holding enough balance and maintaining an allowance. The exposure is sharpest at stage 0, where the community deduction is set to zero, meaning resellers receive the full sale price and the contract retains nothing at all to fund the fourteen and a half to nineteen and a half percent of referral bonuses that the same purchase creates. Users can therefore hold large, apparently valid balances that the protocol has no obligation and no on-chain means to honour.

Pending

#4 medium Issue
A Single Purchase Can Sweep 512 Queue Entries And Write 512 Upline Slots
TBCDistributionPlan.sol
L316-362
L475-528
L576-582
L587-605
Description

The loop bound of 512 governs four separate loops per purchase. Two of them do work proportional to the trade, but two do not. In the general resale loop an unfunded position takes the wipe branch with nothing sold, so the sell limit is never reduced and the loop cannot exit early - it runs the whole window every time. The monthly bonus distribution performs one storage write per upline, up to 512 of them, with no exit other than reaching the root. A measured single purchase at stage 2 over a 512-entry unfunded queue costs 3,310,721 gas and destroys all 512 positions, against a block gas limit of 30,000,000. During the period after migration the cost of buying is therefore dominated by clearing other people's dead positions - roughly seventy-five purchases per stage at over three million gas each just to work through the thirty-eight thousand entry queues. A deep referral chain adds up to 512 cold storage writes on top of that, so a purchase by a deeply nested buyer over a long unfunded queue can approach the block limit.

Pending

#5 medium Issue
Withdrawal Function Reports Success When It Pays Nothing
TBCDistributionPlan.sol
L920-931
Description

The withdrawal function wraps both its eligibility check and the transfer itself in a single condition. If the caller asks for more than they are owed, or if the transfer cannot be made because the recipient or the contract is blocked or because neither the contract balance nor the funding wallet can cover it, the function simply returns successfully. There is no revert, no event, no return value and no state change. Users and the interfaces built on top of them cannot tell a successful withdrawal from a failed one without comparing balances before and after. A wallet that reports a confirmed transaction while nothing actually moved is a direct support and trust problem, and any automated integration will mis-account.

Pending

#6 medium Issue
No Emergency Stop And No Way To Rotate The Payout Wallets
TBCDistributionPlan.sol
L32-34
L823-826
Description

The funding, treasury and burn wallets are declared as ordinary storage variables but no function ever writes to them, so they are immutable in practice while still paying the gas cost of storage. The validator is the only rotatable address, and only the funding wallet can rotate it. The sale flag is one-way, and there is no pause on any function. If the funding wallet's key is lost or compromised there is no recovery at all: bonus liquidity stops, the protocol TBC withdrawal, the excess sweep and the validator rotation all become unreachable, and the only remedy is to redeploy and re-migrate close to 115,000 positions. If any of the three wallets is blocked by the settlement token, the corresponding value stream stops permanently. And if a live problem is discovered after launch there is no way to halt the contract while it is investigated.

Acknowledged

#7 medium Issue
Validator Purchases Are Uncapped And Leave No Trace
TBCDistributionPlan.sol
L261-303
L134
Description

The validator purchase path prices the trade at the amount that is actually paid out to sellers rather than at the stage price. The project team has explained that this is the deliberate exclusion of an internal allocation rather than a preferential rate, and that explanation is accepted, so the pricing itself is no longer treated as a concern. What remains are the controls around it. There is no per-transaction cap, no cumulative cap and no cooldown, so the path can consume the remaining stage allocation and the protocol pool without limit. The event declared for validator purchases is never emitted, so the single most privileged purchase route in the contract leaves no protocol-level trace at all. And the validator address can be changed by the funding wallet alone, with no delay and no owner involvement. The last point matters more than it appears: the allocation that is skipped also funds referral, working, royalty, foreign tour and monthly payments to holders, and those have no recipient here only because the validator sits outside the referral tree. If the role were ever pointed at an address that does sit inside it, the accounting rationale would no longer hold.

Acknowledged

#8 medium Issue
Monthly Reward Tiers Can Be Farmed With A Self-Built Referral Tree
TBCDistributionPlan.sol
L828-893
L573-582
Description

Monthly sales accumulate the value of every purchase made anywhere in a sponsor's downline, up to 512 levels deep, and the reward tier is computed from the top sponsor's own sales plus their own purchases, measured against the user's total downline sales. Self-purchases count towards the qualification. The highest tier pays one million units for ten million on each of two legs. Nothing binds this volume to distinct participants, so one party controlling a set of addresses can generate the required volume by buying through its own tree and then recover a large share of the outlay through the referral bonuses, which run to fourteen and a half percent or nineteen and a half percent with the first-level doubling, plus the resale proceeds. Combined with the supply cap bypass, which allows unlimited buying at the cheapest stage price, the round-trip cost of manufacturing qualifying volume is a small fraction of the reward. The monthly reward budget can therefore be captured by a single well-capitalised participant at the expense of genuine sales teams.

Acknowledged

#9 medium Issue
Outdated Compiler Running An Experimental Code Generation Pipeline
TBCDistributionPlan.sol
L1
Description

The contract is pinned to compiler version 0.8.10 and, as confirmed by the experimental marker embedded in the deployed metadata, was built using the intermediate representation pipeline while that pipeline was still officially experimental. The published defect list records nine known issues for this compiler version, three of which are conditioned on exactly the settings in use here. One concerns unsound handling of local variables in mutually recursive functions when the intermediate representation pipeline is enabled, fixed only in a much later release. One concerns argument evaluation order not being preserved for inlined calls when the optimizer is enabled. One concerns corruption when re-encoding a tuple whose last component is a fixed-size array taken from call data, and this contract does accept a fixed-size array of five values in its purchase entry point. None of the three is currently reachable in this code - there is no mutual recursion, all the affected call sites pass simple values, and the array is never re-encoded into an external call. The concern is the position rather than a present exploit: the contract sits on a compiler whose code generation pipeline was explicitly labelled experimental, and three of its known defects match the build settings exactly.

low Issues | 9 findings

Acknowledged

#1 low Issue
Migration Guard Lets Accounts With No Recorded Purchase Be Imported Repeatedly
TBCDistributionPlan.sol
L749
L758-760
L784
Description

The guard that is supposed to stop an account being migrated twice uses the amount paid as its marker. For any account in the old system that registered but never completed a purchase, that value is zero, so the guard passes every single time. Each repeat pushes the address into the sponsor's direct team again, increases the sponsor's direct count again, and increases the migration counter again. The direct count is not cosmetic - three directs unlock referral levels one through nine, five directs double the first-level referral reward from five to ten percent, and three directs combined with 1,500 units of business grant permanent royalty status. A sponsor can therefore be handed referral standing and royalty status that no real participant ever earned. The function is owner-only and closes once the sale opens, so this is an operator-error and key-compromise risk rather than something an outsider can trigger.

Pending

#2 low Issue
Anyone Can Nominate Any Address As Preferred Seller
TBCDistributionPlan.sol
L153
L400-460
Description

The preferred seller is an unvalidated parameter supplied by whoever sends the purchase, and it grants the nominated address priority over twenty percent of the trade ahead of everyone waiting in order. Two cooperating parties can arrange this on every purchase, and a buyer watching pending transactions can also submit ahead of another buyer to change who gets filled. In a test with two queued sellers, the nominee sitting at the second queue position was filled for two hundred TBC while the queue head took three hundred, confirming that queue order can be reordered at will.

Pending

#3 low Issue
Deployed Bytecode Is Not Byte-Reproducible From The Delivered Source
TBCDistributionPlan.sol
L1
Description

Rebuilding the delivered source with the same compiler version, the same experimental pipeline, the optimizer enabled and a run count of one produces runtime code of exactly the same length as the deployed contract, 22,850 bytes excluding metadata, and an identical multiset of instructions and constants once immutable addresses and jump destinations are normalised. The two builds differ only in the ordering of basic blocks and in the metadata hash. The contract is therefore semantically the source that was delivered and the conclusions of this review apply to the deployed code, but a third party cannot confirm that with a simple byte comparison, which is what the standard verification tooling and every block explorer verification flow rely on.

Pending

#4 low Issue
Deferred Burn Balance Can Only Be Released By A Purchase
TBCDistributionPlan.sol
L716-725
L174
Description

The routine that releases deferred burn funds is invoked from exactly one place, the branch of the purchase fee handling that runs when the burn wallet is not blocked. If the burn wallet is blocked, settlement tokens accumulate in the deferred balance and are only ever released when somebody happens to make a purchase after the block is lifted. There is no administrative flush and no permissionless one, so in a quiet period the funds simply sit there.

Pending

#5 low Issue
Share Entries Below The Purchase Stage Are Unvalidated
TBCDistributionPlan.sol
L190-204
Description

When buying at stage 1 the sum check covers only entries one through four, and the first entry is neither validated nor used anywhere. The same pattern applies to the lower indices at every higher stage. A caller can pass arbitrary values in those slots with no effect today, but the silent tolerance hides genuine input mistakes from users and interfaces, and it would become a real problem if the index mapping were ever changed.

Pending

#6 low Issue
Sale Can Be Opened On A Partially Migrated State
TBCDistributionPlan.sol
L823-826
Description

Opening the sale performs no completeness check of any kind. Because the three migration functions are all gated on the sale not having started, calling it early permanently locks out whatever migration work remains. With close to 115,000 positions to import across many transactions, a mis-sequenced launch is a realistic operational risk, and the consequence is that a portion of the participant base is left without their positions and with no way to add them.

Pending

#7 low Issue
Ownership Can Be Renounced, Permanently Disabling Migration And Sale Start
Ownable.sol
L60-62
Description

The inherited renounce function is live and unmodified. Called before the sale is opened, it makes the contract permanently unusable: the sale can never be started and the migration can never be completed, with no way back because the contract is not upgradeable. This is not a hypothetical pattern for this project - the previous version's owner is already set to the zero address on chain.

Pending

#8 low Issue
State Is Written After The Native Transfer In The Purchase Function
TBCDistributionPlan.sol
L220-248
Description

The purchase function sends native TBC to the buyer with a call that forwards all remaining gas to an address the caller controls, and then writes the amount paid, the sponsor's total business, the royalty flag, the monthly direct business and the monthly purchase figures afterwards. The reentrancy guard blocks re-entry into every state-changing external function, and the plain receive path only increases the protocol pool, so no exploitable route was found. What remains is a read-only exposure: anyone integrating with the contract who reads the pending reward or the user record from inside that callback observes a half-updated state.

Pending

#9 low Issue
Unbounded Direct Team Getter, Overloaded With Its Paginated Replacement
TBCDistributionPlan.sol
L1007-1026
Description

The single-argument version of the direct team getter returns the entire array in one call. For a sponsor with a large team the call exceeds the node's gas ceiling for read-only calls and simply reverts, which breaks any interface or integration that relies on it. A correctly paginated version already exists directly beneath it, distinguished only by the number of arguments - an overload that code generators, block explorers and interface consumers frequently mishandle because they key on the name alone.

optimization Issues | 4 findings

Pending

#1 optimization Issue
Payment Context Struct Lives In Storage And Is Rewritten Every Call
TBCDistributionPlan.sol
L53-63
L691-714
Description

The payment context occupies four storage slots, three for the balance figures and one shared by the four flags. They are written at the start of every purchase, withdrawal and monthly claim and cleared again at the end. That is eight storage operations per call for data that never needs to survive the transaction, and it happens on the hottest paths in the contract.

Pending

#2 optimization Issue
Loop Bodies Re-Resolve State That Does Not Change Between Iterations
TBCDistributionPlan.sol
L316-362
L423-459
L475-528
L534-570
L576-581
L587-605
Description

Across the six loops in the contract there are more than a hundred instances of a state variable being read inside the loop body when its value does not change between iterations. The stage price, the stage incentive rate, the position array reference, the referral rate table and the team requirement table are all re-read on every pass. The same pattern appears at field level: inside the resale loops the user record is addressed field by field several times per iteration, and each access resolves the storage slot from scratch. All twelve loops additionally use a post-increment counter under the compiler's default overflow checking, which is provably unnecessary because the counter is bounded by the loop condition.

Pending

#3 optimization Issue
Revert Strings Instead Of Custom Errors
TBCDistributionPlan.sol
L92-137
L156-213
L264-292
L738-756
L829-898
L945-995
Description

There are seventy-three requirement statements carrying string messages, sixty-one in the main contract and twelve in the vendored libraries. Each string is stored in the deployed bytecode and encoded at runtime when it triggers, which costs both deployment size and execution gas compared with a custom error.

Pending

#4 optimization Issue
Direct Team Count Duplicates The Array Length
TBCDistributionPlan.sol
L120-121
L184
L760
Description

The number of direct referrals is held both as a dedicated counter and implicitly as the length of the direct team array, and the two are kept in step by hand at every place a member is added. That is an extra storage write per registration and an opportunity for the two to diverge.

informational Issues | 11 findings

Resolved

#1 informational Issue
Preferred Seller Allocation Model Is Undocumented
TBCDistributionPlan.sol
L400-460
L475-528
Description

A buyer may nominate any address as preferred seller and up to twenty percent of the trade is filled from that seller through a dedicated route before the general queue is touched. If the nominated seller also holds a position near the front of the general queue, they are filled again under the ordinary rules, so a single seller can account for up to half of a trade. The project team has confirmed that this is intended: the twenty percent bounds the dedicated route only, and participation in the general queue is the same right every other seller has. The total drawn from user positions stays bounded at half the trade either way, so no additional supply leaves the stage. Reclassified on that basis. Two properties of the model are worth stating publicly because they are not obvious from the outside: the dedicated route lets the nominated seller fill from queue positions the general pointer has already moved past, which no other seller can do, and any unused part of the twenty percent is added to the general quota, so a trade with no nomination makes more capacity available to the queue.

Resolved

#2 informational Issue
Payouts Book The Gross Amount But Transfer Ninety-Nine Percent
TBCDistributionPlan.sol
L644-651
L667-669
Description

The internal payment helper credits the recipient's claimed total with the full gross amount and then transfers the amount less one percent, sending the withheld portion to the burn wallet. The withheld part is not lost to the protocol, but the recipient's pending reward falls by the gross figure while their wallet rises by the net one. Anyone comparing the two will see a permanent one percent shortfall on every payout. A test confirmed the behaviour precisely: 1,400 units were booked against a sponsor while 1,386 units arrived in their wallet.

Resolved

#3 informational Issue
Only A Single Reward Period Is Migrated
TBCDistributionPlan.sol
L778-781
Description

The migration reads the monthly purchase, sale, claimed and direct business figures at exactly one key, the period cursor hardcoded in the constructor. Any history in the old system belonging to an earlier or later period is silently dropped. The two contracts currently report the same cursor value, so the keys align today, but the old contract's sale is still enabled and a purchase there after that timestamp would advance its own cursor and desynchronise the two, at which point the migration would read from the wrong period.

Pending

#4 informational Issue
State-Changing Functions Emit No Events, Including One That Is Declared But Never Used
TBCDistributionPlan.sol
L134
L149-151
L261-303
L737
L788
L811
L823
L944
L949
L970
L978
Description

The plain receive path, the three migration functions, the sale opening, the protocol pool deposit and withdrawal, and the user deposit and withdrawal all change state without emitting anything. An observer cannot reconstruct from logs how the contract was initialised, who was migrated, what positions were imported or when the sale was opened. The validator purchase path is the worst case of the same problem: an event is declared specifically for it and no code ever emits it, so the single most privileged purchase route in the contract produces no protocol-level log entry at all.

Pending

#5 informational Issue
Naming Collides On A Field That Carries A Different Unit
TBCDistributionPlan.sol
L44
L110
L305
L365
L400
L531
L573
L584
L608
L627
L637
L681
L691
L712
L716
Description

There is a field inside the user record called working bonus which holds an accrued settlement amount, and a separate top-level mapping with exactly the same name which holds a rate expressed in basis points. Same name, different unit, different meaning, both in constant use throughout the contract. This is the sort of collision that produces subtle mistakes during maintenance. Separately and less seriously, thirteen internal functions carry a double underscore prefix, which is not the established convention and reads as if the names were reserved by the language.

Pending

#6 informational Issue
Foreign Tour Bonus Divides Before Multiplying
TBCDistributionPlan.sol
L609
Description

The foreign tour bonus divides the qualifying business by three thousand and then multiplies by three hundred. Read as a milestone reward - three hundred units for every three thousand units of team business - the ordering is intentional and the behaviour is correct. Read as a ten percent rate, it under-pays by up to just under three hundred units at every threshold boundary. The previous review classified it as a precision defect; on balance it reads as a deliberate step function, but the intent is not documented anywhere so the ambiguity remains.

Pending

#7 informational Issue
No Documentation Comments On Any Public Entry Point
TBCDistributionPlan.sol
L1-1027
Description

None of the thirty-four public or external functions carries any documentation comment. For a contract with this much implicit business logic - a five-stage price ladder, a ten-level referral programme, four separate bonus schemes and a resale queue with two different fill policies - that is a significant cost to every future reviewer and maintainer, and it makes independent verification of intended behaviour considerably harder.

Pending

#8 informational Issue
Unreachable Code In The Vendored Dependencies, Including A Delegate Call Helper
Address.sol
L11-16
L38-58
Description

A substantial part of the vendored dependency code is never reached: the value-sending helper, the static call helpers and the delegate call helpers in the address library, the approve, increase allowance, decrease allowance and permit helpers in the safe transfer library, the message data helper in the context base, and the entire permit interface file. Roughly a third of the dependency code is dead. This does not affect the deployed size, because unreachable internal library functions are never emitted into the runtime - removing them was measured to produce a byte-identical result. The cost is to review and maintenance: every future reader has to work out which of these helpers are live. The delegate call helper is the most notable, since it is a powerful primitive sitting in the source of a contract that is explicitly not upgradeable.

Pending

#9 informational Issue
Two Ways To Fund The Protocol Pool With Different Protections
TBCDistributionPlan.sol
L149-151
L944-947
Description

The plain receive path and the explicit protocol deposit function both credit the protocol pool from the value sent, but only the explicit one carries a reentrancy guard and a zero-value check, and neither emits an event. Two entry points with the same effect but different protections invite confusion and inconsistent behaviour.

Pending

#10 informational Issue
Redundant Balance Pre-Check In The Purchase Function
TBCDistributionPlan.sol
L167
Description

The purchase function reads the buyer's settlement balance and compares it against the package price plus the fee before doing anything else. This duplicates what the subsequent transfer already enforces, at the cost of an extra external call, and because it does not check the allowance it gives a false impression of having validated the buyer's readiness to pay.

Pending

#11 informational Issue
Business Thresholds Are Scattered As Inline Numbers
TBCDistributionPlan.sol
L191-204
L238
L402
L462-463
L544
L555
L850-865
L887
L913
Description

The twenty, thirty and fifty percent split between priority seller, general queue and protocol supply, the fifteen hundred unit royalty and referral threshold, the five-direct rule that doubles the first-level referral reward, the eight monthly reward tiers with their sixteen threshold values, and the five hundred basis point working bonus rate are all written as inline numbers at their point of use. Some appear more than once. The economics of the contract cannot be read off the source without tracing every branch.