--- eip: 8376 title: Token Launch Abuse Detection and Remediation description: Attested detection of rug pulls and other deployer abuse, with escrowed proceeds enabling pro-rata refunds and bonded restitution. author: Leigh Cronian (@cybercentry) , Chris Johnson discussions-to: https://ethereum-magicians.org/t/erc-8376-token-launch-abuse-detection-and-remediation/29359 status: Draft type: Standards Track category: ERC created: 2026-08-07 requires: 20, 165, 214 --- ## Abstract This ERC defines a standard for detecting abuse by token deployers and refunding their buyers while the money is still reachable. It specifies three parts. **Detection**: a taxonomy of eleven deployer abuse patterns, each with a reference profile, scored from a versioned twelve-signal base vector, extensible per pattern, into an `abuseScore` of 0-100 and published as a bonded report committing to chain-verifiable evidence. Every signal describes an action the deployer took; price decline is excluded by rule. **Escrow**: the venue holds sale proceeds and releases them on a schedule, so they remain reachable while abuse typically occurs. **Remediation**: a bonded claim and adjudication process that, on an upheld claim, refunds buyers pro rata by pull and draws any shortfall from a bond posted before launch. The specification is addressed to the venue: the launchpad, bonding curve or sale contract that lists the token, stands between the deployer and the buyer, and holds the proceeds at full conformance. It provides a way to consult detection before listing, to disclose what was found, and to return money that has not yet left. It protects buyers only at venues that adopt it. A deployer who launches outside such a venue is outside its reach. ## Motivation A launchpad that lists a token which turns out to be a honeypot does not lose money. It loses the users who bought it, and the next hundred deployers who would rather launch somewhere that has not been in that headline. The deployer is pseudonymous and finished; the venue is named, still trading, and holds the only record of who bought what. That asymmetry is why the venue is the right place to intervene, and why this proposal asks the venue to act rather than asking the token to be reversible or the buyer to be careful. Most token buyers are not harmed by an anonymous trading cohort. They are harmed by the person who created the token. The pattern is well worn. A deployer mints a supply, keeps most of it at zero cost, seeds a liquidity pool, promotes the launch, and sells into the resulting bids or withdraws the liquidity outright. Variants differ only in mechanics: the honeypot that accepts buys and blocks sells, the retained mint function used to dilute after the raise, the allocation quietly distributed to wallets the deployer funded, the coordinated exit timed to a vesting unlock. The common structure is that one identifiable party controls the asset, the float, and the timing, and extracts value from people who cannot see any of it. Three gaps keep this unaddressed: 1. **Deployer conduct is invisible at the moment it matters.** Whether liquidity is locked, how much supply the deployer retains, which privileged functions survive deployment, and how much of the raise is already withdrawn are all knowable from chain state, but are published in no comparable form. A buyer deciding in the first minutes has no way to consult them, and a venue has nothing to gate on. Where analysis exists, it sits in proprietary dashboards, with no way to compare two analysts or hold either accountable. 2. **Proceeds settle instantly.** A venue that forwards a buyer's payment in the same transaction makes the outcome final before abuse could be detected. Nothing forces a delay, and nothing lets a venue hold proceeds briefly without becoming an unaccountable custodian. 3. **Recourse does not exist.** Buyers have no remedy beyond social pressure against a pseudonymous deployer. Nothing obliges someone raising money from strangers to have collateral at stake, and nothing routes it to the people who funded them. These losses are small in aggregate and large in number, and that shape is the reason to standardize here. Public incident data for 2026 to date puts token-level deployer abuse at roughly one per cent of value lost to on-chain incidents, against protocol logic at about a third and compromised web surfaces at about a half. The case does not rest on the size of the number. It rests on three properties the larger categories do not share. The loss is distributed across many small buyers, so per-victim recourse costs more than it recovers and nobody pursues it. The frequency is constant, where protocol exploits are rare and idiosyncratic. And the money is still reachable: an exploit sends funds to an attacker who is already gone, while a launch abuse leaves proceeds sitting at a venue that recorded every purchase and can still return them. This proposal addresses the losses that can be undone. ## Specification The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174). ### Overview The following diagram illustrates detection, escrow and remediation end to end: ![ERC-8376 Token Launch Abuse Detection and Remediation - Flow Diagram](../assets/eip-8376/20260830-ERC_8376_Token_Launch_Abuse_Detection_and_Remediation_Flow_Diagram-v0.1.svg) | Role | Definition | | --- | --- | | **Adjudicator** | The entity resolving contested claims for a deployment | | **Buyer** | A purchaser at the venue | | **Deployer** | The party launching the token, and the respondent in any claim against it | | **Detector** | An entity that analyzes launches and publishes reports | | **Venue** | The launchpad, bonding curve, or sale contract through which buyers purchase | | Interface | Purpose | | --- | --- | | `ILaunchAbuseRegistry` | Publication and query of detection reports | | `ILaunchDetector` | Assembly of a signal vector from chain state and off-chain findings | | `ILaunchDirectory` | Per-chain resolution from a token or deployer to its launches | | `ILaunchEscrow` | Purchase recording, scheduled release of proceeds, and freezing | | `ILaunchGuard` | A single non-reverting call returning the containment action, score and report for a launch | | `ILaunchRemediation` | Bonds, claims, adjudication, and pro-rata refund | Three conformance levels are defined, so that partial adoption is well defined. **Consumer conformance** requires no deployed contract. A venue at this level calls `ILaunchGuard.checkLaunch` for the launch a buyer is purchasing, and discloses the `abuseScore`, the `confidence` and the report's `evidenceURI` at the point of purchase, without requiring the buyer to query a contract. Where no live report exists it MUST present that as unknown and MUST NOT present it as safe. A consumer-conformant venue MUST NOT describe itself as offering refunds or restitution. **Detection conformance** adds `ILaunchDirectory` and `ILaunchAbuseRegistry`. A venue at this level lists its launches, so that detectors can publish bonded reports against them rather than only against launches someone else listed. It still holds no proceeds and offers no remedy: a detection-conformant deployment MUST NOT describe itself as offering refunds, and MUST make clear that a low score carries no restitution behind it. **Full conformance** adds `ILaunchEscrow` and `ILaunchRemediation`, and is the only level at which a buyer can be refunded. Any implementation of `ILaunchEscrow` MUST list its launches in a directory: an unlistable launch is unreachable by consumers and unreportable by detectors. An implementation claiming full conformance MUST implement all six interfaces and MUST return `true` from `supportsInterface` for each corresponding interface ID as defined in [ERC-165](./eip-165.md). ### What a Venue Must Do Everything required of a venue, by level. Nothing else in this specification is addressed to venues; [Part 1](#part-1-detection) is addressed to detectors and [Part 3](#part-3-remediation) to adjudicators. | | Consumer | Detection | Full | | --- | --- | --- | --- | | Call `checkLaunch` before a purchase | MUST | MUST | MUST | | Disclose score, confidence and evidence URI to the buyer | MUST | MUST | MUST | | Present a missing report as unknown, never as safe | MUST | MUST | MUST | | List launches in the directory | MAY | MUST | MUST | | Hold proceeds and release on a schedule | MUST NOT claim | MUST NOT claim | MUST | | Record every purchase | n/a | n/a | MUST | | Record sales made at the venue | n/a | n/a | MUST | | Honor a freeze from the remediation contract | n/a | n/a | MUST | | Require a deployer bond before launch | n/a | n/a | MUST | A venue MUST NOT claim a level it does not meet in full, and MUST NOT describe a lower level in language implying a higher one. "Verified" and "protected" imply restitution; only full conformance provides it. ### Part 1: Detection A venue requires three facts from this part: a report carries an `abuseScore` from 0 to 100 and a `confidence` from 0 to 100; the two are read together, never separately, through the containment ladder in [Part 3](#part-3-remediation); and a report is a bonded claim by an accountable party rather than an established fact. Everything after this point specifies how a detector produces those numbers and what it is accountable for. It is normative for detectors and informative for venues. #### Conduct, Not Outcome Scoring price decline would classify every unsuccessful launch as abusive, since most launches decline without abuse having occurred, penalising legitimate launches and removing the score's value. Implementations MUST NOT include price decline, drawdown, market capitalization, holder losses, or any other measure of buyer outcome as a scored signal. Every signal below describes an action the deployer took or a power they hold. A buyer's loss establishes standing to claim; it never establishes that abuse occurred. Detectors MAY report outcome measures as context in `evidenceURI` but MUST NOT weight them. #### Pattern Taxonomy Patterns are identified by a `bytes32` derived from a namespaced string, so the taxonomy extends without a central registry. Implementations MUST use the following identifiers for the patterns they describe: | Constant | Derivation | Description | | --- | --- | --- | | `PATTERN_HARD_RUG` | `keccak256("erc.launch.hard-rug")` | Withdrawal of pool liquidity after buyers have funded it. | | `PATTERN_SOFT_RUG` | `keccak256("erc.launch.soft-rug")` | Distribution of the deployer's retained allocation into buyer bids, without removing liquidity. | | `PATTERN_INSIDER_ALLOCATION` | `keccak256("erc.launch.insider-allocation")` | Undisclosed pre-allocation of supply to wallets the deployer funded or controls. | | `PATTERN_SNIPER_COORDINATION` | `keccak256("erc.launch.sniper-coordination")` | Acquisition of float in the opening blocks by addresses linked to the deployer. | | `PATTERN_HONEYPOT` | `keccak256("erc.launch.honeypot")` | A launch that accepts purchases but prevents or penalizes selling. Not scoreable from the base vector: requires the sellability extension schema. | | `PATTERN_MINT_DILUTION` | `keccak256("erc.launch.mint-dilution")` | Post-launch supply expansion diluting buyers. | | `PATTERN_RETAINED_CONTROL` | `keccak256("erc.launch.retained-control")` | Retention of privileged powers contrary to what was disclosed at launch. | | `PATTERN_WASH_LAUNCH` | `keccak256("erc.launch.wash-launch")` | Fabricated launch volume to obtain venue ranking or visibility. | | `PATTERN_UNLOCK_EXIT` | `keccak256("erc.launch.unlock-exit")` | Coordinated exit timed to a liquidity or vesting unlock. | | `PATTERN_SERIAL_DEPLOYER` | `keccak256("erc.launch.serial-deployer")` | Deployer linked to prior launches with upheld claims. | | `PATTERN_IMPERSONATION` | `keccak256("erc.launch.impersonation")` | Deployment of a token presenting the identity of an established project, by name, symbol or metadata. Not scoreable from the base vector: requires the impersonation extension schema. | The `erc.` prefix is reserved for patterns defined in an ERC. Implementations MAY define additional patterns, which MUST be namespaced under a prefix the definer controls, such as a domain name they own, and MUST NOT use `erc.`. Consumers MUST treat unrecognized identifiers as informational and MUST NOT apply automated containment on their basis. #### Signal Vector A conformant detector MUST compute the following twelve base signals and MUST publish them alongside any score. Values are in basis points (0-10000) unless stated. A detector that cannot compute a signal MUST report `type(uint16).max` (or `type(uint32).max` for `lpLockRemaining`) as an explicit unavailability sentinel rather than zero. The base vector is version 1. A report MUST declare the version it was computed under, so that a consumer can reject a vector it cannot interpret rather than misread it. | Field | Type | Units | Definition | Polarity | | --- | --- | --- | --- | --- | | `deployerSupplyShare` | `uint16` | bps | Share of total supply held by the deployer and addresses it funded, at window end. | Adverse | | `insiderAllocationShare` | `uint16` | bps | Share of supply transferred to deployer-funded addresses before public trading opened. | Adverse | | `sniperConcentration` | `uint16` | bps | Share of float acquired within the first `openingBlocks()` by addresses sharing a funding ancestor with the deployer. | Adverse | | `lpLockedShare` | `uint16` | bps | Share of pool liquidity held in a lock or burn address. Where the pool mints a fungible liquidity token this is the share of its supply; where a position is non-fungible it is the share of liquidity those positions represent. | Protective | | `lpLockRemaining` | `uint32` | seconds | Time remaining at window end on the lock securing the liquidity counted by `lpLockedShare`. Where several locks apply, the shortest. | Protective | | `liquidityRemoved` | `uint16` | bps | Fall from the pool's peak holding of the paired asset to its holding at window end, as a share of the peak. | Adverse | | `deployerSellRatio` | `uint16` | bps | Share of the deployer's allocation sold or transferred out during the window. | Adverse | | `proceedsWithdrawnShare` | `uint16` | bps | Share of the raise withdrawn by the deployer during the window. | Adverse | | `privilegedPowers` | `uint16` | bitmask | Privileged functions callable by the deployer at window end. | Adverse | | `priorUpheldClaims` | `uint16` | count | Upheld claims against launches by addresses linked to this deployer. | Adverse | | `supplyInflation` | `uint16` | bps | Increase in total supply between window start and window end, as a share accruing to the deployer and addresses linked to it. | Adverse | | `washTradeRatio` | `uint16` | bps | Share of window volume returning to the cohort that originated it. | Adverse | `supplyInflation` MUST be scaled by the share of supply held by the deployer and by addresses sharing a funding ancestor with it, where either is established. Gross supply growth is not dilution: new supply distributed to stakers and liquidity providers inflates as hard as supply minted into the deployer's wallet, and only the destination distinguishes them. Where neither share is established the gross figure stands. `liquidityRemoved` MUST be measured from the paired asset the pool holds and MUST NOT be measured from the supply of a liquidity token. Where a token is listed in more than one pool, a detector MUST measure the pool holding the most of the paired asset, and MUST NOT select by the amount of the token a pool holds. An emptied pool holds nearly all of the token and none of the paired asset, so selecting by token holdings prefers an abandoned pool over the launch's actual market, and then reports that market's liquidity as gone. A detector MUST also consider pools that mint no fungible liquidity token, since a concentrated-liquidity pool holds no reserves to read and is nonetheless where a launch's liquidity may sit. Burning or withdrawing a liquidity token empties a pool, and so does selling supply into it, and only the first changes that token's supply. A detector measuring supply therefore reports that nothing was removed from a pool that has been emptied, which is the reading most rugged launches produce. What a holder meets when trying to sell is the paired asset, so that is the quantity. Where `liquidityRemoved` is established and at or above its activation threshold, liquidity demonstrably left, the claim is contradicted by what happened, and a detector MUST report `lpLockedShare` and `lpLockRemaining` as the unavailability sentinel rather than scoring the lock as protection. This applies only where a lock was claimed: where `lpLockedShare` is zero, the zero is a measurement rather than a pretence and MUST be kept. Burning the liquidity token prevents withdrawal alone: a deployer still holding supply empties the pool by selling into it. `lpLockedShare` is computed from a fungible liquidity token where the launch has one and from supplied liquidity amounts where it does not. A detector MUST prefer the fungible route where a liquidity token is named, MUST report the unavailability sentinel where neither route is available, and MUST report the sentinel rather than zero where the pool holds no liquidity at all, since zero asserts that liquidity was measured and none of it was locked. `privilegedPowers` bits are assigned as follows, and unassigned bits MUST be zero: | Bit | Power | | --- | --- | | `0x0001` | Mint | | `0x0002` | Pause or freeze transfers | | `0x0004` | Blacklist addresses | | `0x0008` | Set transfer fee or tax | | `0x0010` | Upgrade implementation | | `0x0020` | Seize or transfer balances arbitrarily | | `0x0040` | Set transaction or wallet limits | | `0x0080` | Exempt addresses from restrictions | The **observation window** runs from launch to `windowEnd`. Detectors MUST publish `launchedAt` and `windowEnd` so a third party can reproduce the computation. #### Extension Signals The twelve base signals cannot express every abuse. A pattern that can be named but not scored is an identifier rather than a detection, so an extensible taxonomy requires an extensible vector. A pattern MAY therefore declare an extension schema, identified by a `bytes32` derived from a namespaced string, under `erc.launch.schema.` where the schema is defined in an ERC and under a prefix the definer controls otherwise. A schema MUST publish, at a stable URI, for every field it adds: name, type, units, definition, polarity, and activation threshold. Those are exactly the columns the base table carries, and for the same reason: without them a third party cannot recompute the score. Extension signals participate in `abuseScore` on identical terms to base signals. They carry weights in the pattern's profile, they normalize against their published thresholds, they invert where marked protective, and they are excluded from both sums when reported as unavailable. A report using an extension MUST set `extensionSchema` to the schema identifier and `extensionSignals` to the ABI encoding of the schema's fields in declared order. A report using no extension MUST set `extensionSchema` to zero and `extensionSignals` to empty. Consumers MUST treat a report whose `extensionSchema` they do not recognize as informational, exactly as they treat an unrecognized `patternId`, and MUST NOT apply automated containment on its basis. A consumer MUST NOT score a report whose `vectorVersion` it does not implement. #### Reference Extension: Impersonation `PATTERN_IMPERSONATION` cannot be scored from the base vector: a deployer may retain no supply, lock liquidity, hold no privileged powers and read clean on all twelve signals, because the abuse is entirely in presentation. The reference schema `keccak256("erc.launch.schema.impersonation")` version 1, its three fields, their thresholds and its weights are published as [Impersonation Extension Schema v0.1](../assets/eip-8376/20260830-ERC_8376_Impersonation_Extension_Schema-v0.1.md). A detector reporting the pattern MUST follow it, and MUST NOT report `nameSimilarity` from a measure a third party cannot reproduce. #### Reference Extension: Sellability `PATTERN_HONEYPOT` cannot be scored from the base vector either. A launch on Base holding 5.8 ETH of paired liquidity, with more than fifty purchases out of its pool, scored zero on it: `privilegedPowers` 0 because the token exposes none of the eight functions the bit table names, `liquidityRemoved` 0 and `lpLockedShare` 0 because its pool is intact. Fourteen of fourteen externally owned accounts holding it could not transfer any amount of it to that pool. Every signal in the base vector describes the token, the pool's balance, or an action by the deployer. Whether a holder can leave is none of those three, and it is the defining property of this pattern. The reference schema `keccak256("erc.launch.schema.sellability")` version 1, its two fields, their thresholds and its weights are published as [Sellability Extension Schema v0.1](../assets/eip-8376/20261001-ERC_8376_Sellability_Extension_Schema-v0.1.md). A detector reporting the pattern MUST follow it. Two of its requirements are repeated here. `blockedHolderShare` MUST be reported as the unavailability sentinel where fewer than three holders could be sampled, since one refusal is a blacklist and a blacklist is a different claim from a trap. And sampled holders MUST be externally owned accounts, because the recipient of a transfer out of a pool is frequently the router that routed the swap, and sampling one reports a property of the router. A deployment MUST NOT treat a clean reading of this schema as evidence that a position can be exited. It establishes that sampled holders could sell at the time of sampling, through the venue sampled. #### Score Computation `abuseScore` is a `uint8` in the range 0-100, where 0 means no evidence of abuse and 100 means conclusive evidence. It MUST be computed as a weighted mean of per-signal normalized contributions: ``` abuseScore = round( 100 * sum(w[i] * s[i]) / sum(w[i]) ) ``` Where `w[i]` is the pattern's weight for signal `i` and `s[i]`, in the range 0 to 1, is signal `i` normalized against its activation threshold. The division MUST be performed once, on the scaled numerator, and MUST round half up, so that two implementations of the same vector cannot differ by the point that decides a band. For signals marked **Adverse**, `s[i]` rises as the value rises. For signals marked **Protective**, `s[i]` MUST be inverted, so that absent protection contributes to the score and present protection reduces it. Signals reported as unavailable MUST be excluded from both sums rather than treated as zero. Where a report declares an extension schema, `i` ranges over the base signals and the schema's fields together. `fieldId` values for extension signals MUST be derived as `keccak256(abi.encode(extensionSchema, fieldName))`, so that an evidence leaf for an extension field cannot collide with one for a base signal. Every pattern has a reference weight profile, since a pattern that can be reported but not scored provides an identifier without a detection. Weights sum to 100 in each. Deployments MAY tune them but MUST publish the profile used. A signal absent from a profile carries no weight for that pattern and is excluded from its mean. Activation thresholds are shared across profiles, except where a profile overrides one in the Activation Exceptions of the published profiles: `deployerSupplyShare` 3000 bps, `insiderAllocationShare` 1000 bps, `sniperConcentration` 2000 bps, `lpLockedShare` 8000 bps, `lpLockRemaining` 30 days, `liquidityRemoved` 2000 bps, `deployerSellRatio` 3000 bps, `proceedsWithdrawnShare` 5000 bps, `supplyInflation` 1000 bps, `washTradeRatio` 3000 bps, `priorUpheldClaims` 1, and `privilegedPowers` any power the profile's mask names, as follows. `privilegedPowers` is categorical rather than proportional: its activation value is the mask the profile publishes, and the signal contributes fully when the token holds any power that mask names and nothing otherwise. A power outside the mask contributes nothing however many bits are set, so a token whose only privileged function pauses transfers adds nothing to a pattern about withdrawing liquidity. The reference profile for each of the eleven patterns, and the `privilegedPowers` mask that activates it, are published as [Reference Weight Profiles v0.1](../assets/eip-8376/20260830-ERC_8376_Reference_Weight_Profiles-v0.1.md). A detector reporting a pattern under this specification MUST score it against the published profile or publish the profile it used instead. Not every signal describes an action. `privilegedPowers` describes a capability, a protective signal reading zero means no protection was arranged, and neither is a thing anybody did. Three rules follow. A pattern whose established signals are all categorical MUST NOT be scored, and a detector MUST report it as unavailable. A categorical signal contributes fully or not at all, so one retained power would otherwise carry the pattern alone and report 100. A pattern whose established signals carry less than half its profile's total weight MUST NOT be reported above the Elevated band. Renormalising over whatever is readable would otherwise report one signal's reading as the whole pattern's score. A pattern established without any signal describing conduct MUST NOT be reported above the Elevated band. The finding is still reported, and the Conclusive band instructs a venue to freeze proceeds and admit claims. A launch MUST NOT be presented as conclusively abusive because the only thing measured was what its code can do. For this purpose conduct means `insiderAllocationShare`, `sniperConcentration`, `liquidityRemoved`, `deployerSellRatio`, `proceedsWithdrawnShare`, `supplyInflation`, `washTradeRatio`, `priorUpheldClaims`, and any extension signal. An upheld claim is adjudicated conduct established by another party. Extension signals describe choices made at deployment, which is why impersonation is established by them and nothing else. `confidence` is a separate `uint8` in 0-100 expressing statistical certainty and MUST be reported independently. A high score at low confidence MUST NOT trigger automated containment. Confidence counted across all twelve signals describes the launch rather than the pattern reported: a profile drawing on three signals carries certainty earned by nine it never consults. A detector SHOULD also report the share of the scored pattern's own profile weight that was established. Deployments SHOULD interpret `abuseScore` in the following bands: | Band | Range | Suggested response | | --- | --- | --- | | None | 0-20 | No action. | | Weak | 21-40 | Record only. | | Elevated | 41-60 | Flag; extend the release schedule. | | Strong | 61-80 | Suspend release of proceeds. | | Conclusive | 81-100 | Freeze proceeds and admit claims. | #### Report Structure and Registry ```solidity // SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.24; struct SignalVector { uint16 deployerSupplyShare; uint16 insiderAllocationShare; uint16 sniperConcentration; uint16 lpLockedShare; uint32 lpLockRemaining; uint16 liquidityRemoved; uint16 deployerSellRatio; uint16 proceedsWithdrawnShare; uint16 privilegedPowers; uint16 priorUpheldClaims; uint16 supplyInflation; uint16 washTradeRatio; } struct AbuseReport { bytes32 patternId; bytes32 launchId; // launch identifier, as listed in `ILaunchDirectory` address token; address deployer; address[] linkedAddresses; uint8 abuseScore; uint8 confidence; uint16 vectorVersion; // 1 for the base twelve signals uint64 launchedAt; uint64 windowEnd; SignalVector signals; bytes32 extensionSchema; // zero where no extension is used bytes extensionSignals; // ABI-encoded, in schema-declared order bytes32 evidenceRoot; string evidenceURI; } interface ILaunchAbuseRegistry { event AbuseReported( bytes32 indexed reportId, bytes32 indexed launchId, bytes32 indexed patternId, address detector, uint8 abuseScore, uint8 confidence ); event ReportRetracted(bytes32 indexed reportId, string reason); event DetectorBonded(address indexed detector, uint256 amount); event SubmitterSet(address indexed detector, address indexed submitter); event SubmitterAccepted(address indexed detector, address indexed submitter); event DetectorSlashed(address indexed detector, uint256 amount, bytes32 claimId); /// @notice Publish a report. MUST revert unless the caller holds a bond /// of at least `minDetectorBond()`. /// @dev reportId MUST equal keccak256(abi.encode(report, principal)), /// where `principal` is `principalOf(msg.sender)`. Deriving it from /// the caller would give a detector a different identifier for the /// same report depending on which of its keys submitted it. function submitReport(AbuseReport calldata report) external returns (bytes32 reportId); /// @notice Nominate a hot key to submit on the caller's behalf, or revoke /// with the zero address. Rotation retires a compromised key without /// moving the bond or discarding the detector's record. /// @dev The nomination MUST NOT take effect until the nominee accepts it. /// A binding written by the detector alone would let it name an address /// that has not yet bonded and take everything that address later /// publishes: the reports attributed to the nominator, the rewards paid /// to it, and the address unable to retract even its own work. /// Revocation is one-sided, so a detector can always retire a key it no /// longer trusts. function setSubmitter(address submitter) external; /// @notice Accept a nomination to submit on `detector`'s behalf. /// @dev MUST revert unless `detector` has nominated the caller. An address /// that holds a detector bond of its own MUST NOT become a submitter, /// since its own bond would stop being the one at risk for what it /// publishes. function acceptSubmitter(address detector) external; /// @notice The detector a caller submits as: itself, or whoever authorized it. function principalOf(address caller) external view returns (address); /// @notice The only party that may take a detector's bond. /// @dev Named once, and never a venue's remediation contract. See "Who May /// Act on the Registry". function detectorAdjudicator() external view returns (address); /// @notice Permit or refuse a contract publishing reports in the caller's /// name, for the atomic submit-and-claim path. /// @dev One-sided by design: the caller's own bond answers for whatever the /// relay publishes, so the grant is the caller's alone to make and to /// withdraw. It MUST NOT be inferred from a venue's role in a launch. function approveRelay(address relay, bool permitted) external; /// @notice Submit on behalf of `detector`, for the atomic submit-and-claim /// path where the remediation contract is the immediate caller. /// @dev Caller MUST be `detector`, a submitter `detector` has nominated, or a /// relay `detector` has approved. /// The bond checked and recorded MUST be the named detector's: /// attributing an atomically submitted report to its transport would /// put the wrong bond at risk, slash the wrong party, and make every /// atomic claim corroborate as the same single detector. function submitReportFor(AbuseReport calldata report, address detector) external returns (bytes32 reportId); /// @dev MUST revert if any claim referencing the report has been adjudicated. function retractReport(bytes32 reportId, string calldata reason) external; function getReport(bytes32 reportId) external view returns (AbuseReport memory report, address detector, uint64 submittedAt); /// @notice Highest-scoring live report for a launch. /// @dev MUST ignore retracted reports and reports older than `maxReportAge()`. /// MUST consider every live report, not a recent subset of them. function activeScore(bytes32 launchId) external view returns (uint8 abuseScore, uint8 confidence, bytes32 reportId); function minDetectorBond() external view returns (uint256); function maxReportAge() external view returns (uint64); function openingBlocks() external view returns (uint32); } ``` Detectors MUST post a bond of at least `minDetectorBond()` before submitting, and that bond MUST be slashable on a proven false report. A registry MUST NOT restrict who may post that bond or submit under it: accountability comes from the bond rather than from admission. A report is a claim by an accountable party rather than an established fact. #### Who May Act on the Registry A registry serves every venue on its chain. Reports about one deployer belong in one place: corroboration is a count of how many accountable parties agree, and a guard is only useful if it can answer about any launch a buyer is looking at. A registry bound to a single venue would split both. Three powers are exercised on a registry, and each is authorised by the party it concerns. **Publishing in a detector's name.** `submitReportFor` MUST be callable only by the named detector, by a submitter that detector has nominated and that has accepted, or by a relay that detector has approved through `approveRelay`. A report is a bonded claim, so the only party entitled to make one in a detector's name is that detector. The atomic submit-and-claim path needs the approved relay, and cannot be served by a submitter nomination: a nomination binds nothing until the nominee accepts it, and a remediation contract has no reason to hold accept logic for every detector reporting at its venue. An approval is many to one in both directions, because a venue relays for every detector that reports there and a detector reports at every venue it watches. It is safe one-sided where a nomination is not, because it rewrites nothing about the relay: it permits the passing through of one detector's reports and confers nothing else, so the only stake exposed belongs to the detector granting it. A relay MUST NOT be approved implicitly by the venue's role in the launch being reported on; the detector whose bond is at risk MUST grant it, and MUST be able to withdraw it. **Taking a detector's bond.** Slashing MUST be callable only by a single detector adjudicator, named when the registry is deployed, and the slash MUST name the report it is over: the detector is read from that report, so a bond answers for the reports it backed and for nothing else. The adjudicator MUST NOT be a venue's remediation contract. Deploying an escrow and a remediation contract is permissionless, by design, so a venue-resolved slashing authority would let any address take any bonded detector's whole stake, and would let the party a report accuses punish the detector who wrote it. The adjudicator MUST NOT be an address that submits reports to the same registry, and a registry MUST refuse a detector bond from its adjudicator. An adjudicator that is also a detector would never slash itself, so its own bond could never be taken and its reports would be accountable in form rather than in fact. Where a registry has one detector and that detector holds the role, no bond on it is slashable at all. Whether a report was false is a judgement about the detector, not about a launch, and it belongs to a party with no interest in the answer. A venue's remediation contract MAY publish a finding that a report was false, for that adjudicator to act on. It MUST NOT execute the slash itself. **Drawing forfeited claim bonds.** Bonds forfeited by rejected claims MUST be accounted to the remediation contract that paid them in and drawable only by it. Value leaves the way it arrived. #### Identifying the Deployer The deployer is the party the venue declares through `ILaunchDirectory`, read as `deployerOf(launchId)`. A detector MUST take it from there and MUST NOT derive it from the transaction that created the token. At most venues a factory creates the token on the applicant's instruction, so the creating address is the venue for every launch it lists, and deriving the deployer from it would attribute every launch to the venue. A report MAY be published before a launch opens, and most of the vector cannot exist yet when it is. Eight of the twelve signals describe conduct during or after the sale: liquidity removed, the deployer's sell ratio, proceeds withdrawn, supply minted after launch. A detector publishing before those events MUST report them as unavailable and MUST NOT report them as zero. Where a launch is not listed in a directory, or the directory records no deployer, a detector MUST report every deployer-derived signal as unavailable. It MUST NOT substitute the creating address, and MUST NOT report those signals as zero. Venues MUST declare the applicant rather than their own factory, since a venue naming itself as deployer puts its own bond behind conduct it did not choose and makes the detection worthless to its buyers. Reads MUST NOT depend on a report's position among the reports for a launch. A registry that answers from the most recent entries alone can be silenced by whoever writes the most: one bonded address publishing padding against its own launch pushes every genuine report out of the window, after which the score reads clean and corroboration reads unanimous at one. Implementations SHOULD keep per-launch aggregates, such as the highest score published and the set of detectors that have published, and MAY cap the live reports one detector holds on one launch, which bounds the work without bounding what is read. Where corroboration is counted, each detector MUST count once however many reports it has published, and a detector whose bond no longer meets `minDetectorBond()` MUST NOT count at all. Corroboration is a statement about how many accountable parties agree, so a party with nothing left at stake is not one of them, and a party who agrees with itself repeatedly is still one. `activeScore` is deliberately not filtered this way: it feeds disclosure at the point of purchase, and a warning already published SHOULD reach a buyer whether or not its author was slashed afterwards. #### Evidence `evidenceRoot` MUST be a Merkle root over leaves that are each independently verifiable against chain state. Every leaf MUST take the form: ``` keccak256(abi.encode(0x00, chainId, blockNumber, txHash, logIndex, fieldId, value)) ``` A commitment to data that cannot be re-derived from chain state establishes internal consistency only, not accuracy. Requiring chain-anchored leaves allows any third party to recompute the signal vector from public data and demonstrate a false report, which is what makes the detector bond enforceable. Where a signal is derived rather than read directly, such as funding-ancestry clustering, the leaves MUST include the transactions from which the derivation was made. #### The Detector A detector turns chain history into a `SignalVector`. Four of the twelve signals need a funding graph or cross-chain claim history and cannot be computed by a contract. Detectors MUST derive on-chain whatever can be derived on-chain, and MUST NOT substitute an asserted value for a readable one. | Signal | Source | Verifiable by anyone | | --- | --- | --- | | `privilegedPowers` | token bytecode, following proxies | yes | | `lpLockedShare`, `lpLockRemaining` | liquidity attributed to lock or burn addresses | yes | | `liquidityRemoved` | pool reserves across the window | yes | | `deployerSupplyShare`, `deployerSellRatio` | deployer balances against allocation | yes | | `proceedsWithdrawnShare` | the escrow named by the directory | yes | | `insiderAllocationShare`, `sniperConcentration` | funding-ancestry clustering | no | | `priorUpheldClaims` | claim history, per chain | partially | | `supplyInflation` | total supply across the window | yes | | `washTradeRatio` | round-trip volume within a cohort | no | `proceedsWithdrawnShare` MUST be read from the escrow directory names, never from the deployer or venue, since the party under examination cannot serve as the source of evidence against it. Signals that a detector could not establish MUST be reported as the unavailability sentinel, never as zero. A detector's contracts are the smallest part of it. The indexing pipeline, the endpoint, the submitting key and heuristic accuracy are covered by the requirements below. #### Detector Obligations **Data integrity.** A detector MUST NOT include a block in a window before it is final. `windowEnd` MUST correspond to a finalized block, and a report MUST NOT depend on a log from a block later reorganized out. Where a reorg invalidates committed evidence, the detector MUST retract the report: a vector computed over an orphaned block is on-chain indistinguishable from a correct one. **Publication.** Anything a detector serves over HTTP is advisory; only an on-chain submission from the bonded identity counts. Seizing the endpoint alone MUST NOT be sufficient to place a report in the registry. **Key management.** The holder of the submitting key publishes under a bond posted by another party. A detector SHOULD separate that key from the one holding the bond, and implementations MUST allow the submitting key to be rotated without moving the bond or discarding the detector's history. A detector that suspects compromise SHOULD revoke the submitting key before retracting any reports made under it, so the attacker cannot republish while the cleanup is in progress. **Detection quality.** No security guide establishes whether a heuristic is accurate, and false positives are the primary risk here. A detector SHOULD validate against labeled launches and publish the resulting precision and recall with its profile. `confidence` MUST reflect measured uncertainty rather than a constant. Deployments MUST NOT enable automated containment above `Flag` on a detector whose accuracy they have not measured, and MUST NOT treat conformance with any security guide as evidence that its findings are correct. #### Detector Interface ```solidity interface ILaunchDetector { /// @param lpToken the fungible liquidity token whose lock is measured, or /// the zero address where positions are non-fungible and /// `lockedLiquidity` and `totalLiquidity` are supplied instead /// @param lockedLiquidity pool liquidity attributed to the lock sinks, /// where positions are non-fungible /// @param totalLiquidity pool liquidity in total, where positions are /// non-fungible /// @param lockSinks addresses treated as locks or burns /// @param deployerWallets wallets attributed to the deployer /// @param deployerAllocation supply originally allocated to the deployer /// @param initialSupply total supply at window start, for dilution /// @param peakLiquidity highest pool liquidity observed in the window /// @param currentLiquidity pool liquidity at window end struct ChainInputs { address lpToken; uint256 lockedLiquidity; uint256 totalLiquidity; address[] lockSinks; address[] deployerWallets; uint256 deployerAllocation; uint256 peakLiquidity; uint256 currentLiquidity; uint256 initialSupply; uint32 lpLockRemaining; } /// @dev Each MUST be the unavailability sentinel where the service could not /// establish it. struct OffChainInputs { uint16 insiderAllocationShare; uint16 sniperConcentration; uint16 priorUpheldClaims; uint16 washTradeRatio; } /// @notice Assemble the full vector for a launch. function observe( bytes32 launchId, address token, ChainInputs calldata chainInputs, OffChainInputs calldata offChainInputs ) external view returns (SignalVector memory); /// @notice The `fieldId` an extension signal's evidence leaf commits to. /// @dev Derived from the schema and the field name, so that a leaf for an /// extension field cannot collide with one for a base signal. function extensionFieldId(bytes32 extensionSchema, string calldata fieldName) external view returns (bytes32); /// @notice The canonical evidence leaf. function evidenceLeaf( uint256 blockNumber, bytes32 txHash, uint256 logIndex, bytes32 fieldId, bytes32 value ) external view returns (bytes32); /// @notice Fold ordered leaves into the root a report commits to. function evidenceRoot(bytes32[] calldata leaves) external pure returns (bytes32); } ``` A detector implementation MUST derive on-chain every signal marked recomputable above, and MUST read `proceedsWithdrawnShare` from the escrow the directory attributes the launch to. It MUST NOT accept those values as inputs, since a figure supplied by the party under examination cannot serve as evidence. `lpLockedShare` on a pool whose positions are non-fungible is the single case in which a supplied figure enters a recomputable signal. No supply exists to divide, so `lockedLiquidity` and `totalLiquidity` reach the detector as inputs, as `peakLiquidity` and `currentLiquidity` already do, and a supplied figure that the pool contradicts constitutes a false report and is subject to the detector's bond. The exception follows from the pool type: where a fungible liquidity token exists, the share MUST be derived from balances. #### Evidence Commitment Evidence leaves, and the internal nodes of the tree above them MUST be domain separated by prefixing leaf preimages with `0x00` and node preimages with `0x01`. Both are otherwise bare 32-byte hashes, and an internal node could be presented as a leaf: a detector could then prove membership of evidence that was never in the set. Where the leaf count is odd, the unpaired leaf MUST be promoted to the next level rather than duplicated, since duplication admits a distinct forgery of the same root. Implementations MUST bound the number of leaves folded in a single call. #### Disclosure Timing A report is public once mined and visible in the mempool before that. A deployer watching the registry can withdraw proceeds or pull liquidity between a report's submission and any action on it. Implementations MUST therefore provide `submitAndClaim`, registering the report and freezing the launch in a single transaction. That path MUST attribute the report to the detector rather than to the contract relaying it, so that the bond at risk, the party a slash reaches, and the identity corroboration counts are all the detector. Detectors MUST NOT submit a report through `submitReport` ahead of a claim they intend to bring against a launch whose proceeds are still escrowed. Deployments MUST NOT rely on off-chain confidentiality of pending reports. ### Part 2: Launch Escrow Refunds are possible only while the venue still holds the money. This part defines the escrow a venue operates, and the identity scheme that makes a launch addressable. #### Launch Identity and Discovery Every interface in this proposal is keyed on `launchId`, which is independently derivable and resolvable from a token address. `launchId` MUST be derived as: ``` launchId = keccak256(abi.encode(block.chainid, escrow, token, deployer, nonce)) ``` where `escrow` is the address of the `ILaunchEscrow` holding the launch, and `nonce` counts prior launches of the same `token` by the same `deployer` at that escrow. Including `block.chainid` binds the identifier to one chain. Implementations MUST NOT use a derivation that omits any of these fields. Resolution is provided by a directory, one per chain: ```solidity interface ILaunchDirectory { event LaunchListed( bytes32 indexed launchId, address indexed token, address indexed deployer, address escrow, address venue ); /// @notice List a launch. Caller MUST be the escrow named in the identifier. /// @param nonce the escrow's launch counter, so the identifier can be /// recomputed and checked against the caller. Without that check, the /// identifier is predictable from public inputs and can be squatted /// before the launch it belongs to is registered. function list( bytes32 launchId, address token, address deployer, address venue, uint256 nonce ) external; /// @notice Every launch recorded for a token, oldest first. /// @dev A token MAY appear more than once: relaunches and multi-venue /// listings are both legitimate, and both are of interest to a detector. function launchesOf(address token) external view returns (bytes32[] memory); /// @notice Every launch by a deployer, oldest first. /// @dev Supports the `priorUpheldClaims` signal and `PATTERN_SERIAL_DEPLOYER` /// without requiring off-chain linkage of a deployer to its history. function launchesBy(address deployer) external view returns (bytes32[] memory); function escrowOf(bytes32 launchId) external view returns (address); function venueOf(bytes32 launchId) external view returns (address); function deployerOf(bytes32 launchId) external view returns (address); function tokenOf(bytes32 launchId) external view returns (address); } ``` Escrows MUST list a launch on registration. Consumers MUST treat an unlisted token as having no launch record, and MUST NOT present that absence as evidence of safety: it means the token is outside the standard's coverage, which is the condition under which buyers are least protected, not most. A directory MUST NOT gatekeep listing beyond requiring that the caller is the escrow named in the identifier. A directory able to refuse a listing constitutes a censorship point, and a launch that cannot be listed cannot be reported against. A consumer holding only a token address MUST resolve it to the launch it is purchasing at, by matching `escrowOf` or `venueOf` against the venue it is transacting with. Where it cannot, it MUST check every launch returned by `launchesOf` and take the highest `abuseScore` among live reports, and MUST NOT select one arbitrarily. A token with a clean relaunch and an abusive prior launch is not clean, and a consumer that picks the first entry can be made to read the wrong one by ordering. #### Directory Deployment The directory MUST be permissionless, immutable, and have no owner. A consumer must locate the directory without being told where by the venue under examination. It MUST therefore be deployed with `CREATE2` through the deterministic proxy at `0x4e59b44847b379578588920cA78FbF26c0B4956C` using salt `0x00`, so it occupies the same address on every chain. Consumers MUST use that address and MUST NOT accept one supplied by a venue, escrow or deployer. Deployment is permissionless: where no directory exists, anyone MAY deploy one through the same proxy. Each directory records only its own chain's launches. This proposal defines no cross-chain aggregation: a detector examining a deployer active on several chains MUST query each directory and combine off-chain, and MUST NOT assume an address is the same principal across chains. ```solidity enum LaunchState { None, Active, Releasing, Frozen, Settled, Refunding } interface ILaunchEscrow { event LaunchRegistered( bytes32 indexed launchId, address indexed token, address indexed deployer, uint256 bond, uint64 releaseStart, uint64 releaseEnd ); event PurchaseRecorded( bytes32 indexed launchId, address indexed buyer, uint256 paid, uint256 tokens ); event SaleRecorded(bytes32 indexed launchId, address indexed buyer, uint256 realised); event ProceedsReleased(bytes32 indexed launchId, uint256 amount); event LaunchFrozen(bytes32 indexed launchId, bytes32 reportId, uint64 frozenUntil); event LaunchSettled(bytes32 indexed launchId); event RefundOpened(bytes32 indexed launchId, uint256 pool, uint256 totalNetPaid); event RefundClaimed(bytes32 indexed launchId, address indexed buyer, uint256 amount); event LinkedAddressExcluded(bytes32 indexed launchId, address indexed account, uint256 removed); event RefundSwept(bytes32 indexed launchId, address indexed to, uint256 amount); /// @notice Register a launch. The deployer MUST have posted `requiredBond`. /// @param asset settlement asset for both proceeds and bond, or address(0) /// for native value. Venues that price in a project token cannot use /// native settlement, so this MUST be supported. function registerLaunch( address token, address deployer, address asset, uint256 bondAmount, uint64 releaseStart, uint64 releaseEnd ) external payable returns (bytes32 launchId); /// @notice Exclude a deployer-linked buyer from the refund pool. /// @dev Caller MUST be authorized by the remediation contract. The excluded /// address leaves the denominator as well as the numerator, so the /// remaining buyers are made whole rather than merely undiluted. function markLinked(bytes32 launchId, address account) external; /// @notice Convenience form for native settlement, passing `msg.value` as /// the bond. function registerLaunchNative( address token, address deployer, uint64 releaseStart, uint64 releaseEnd ) external payable returns (bytes32 launchId); /// @notice Record a purchase and deposit its proceeds. Caller MUST be the venue. /// @dev `msg.value` MUST equal `paid`. Recording an amount the escrow does /// not hold would leave refunds unpayable. function recordPurchase( bytes32 launchId, address buyer, uint256 paid, uint256 tokens ) external payable; /// @notice Record value a buyer realised by selling purchased tokens. /// @dev Caller MUST be the venue. Required so that `netContributionOf` can /// discount buyers who have already exited. function recordSale(bytes32 launchId, address buyer, uint256 realised) external; /// @notice Buyer's net contribution: paid, less value already realised /// by selling the purchased tokens. function netContributionOf(bytes32 launchId, address buyer) external view returns (uint256); /// @notice Release the vested portion of proceeds to the deployer. /// @dev MUST revert while Frozen. MUST release no more than the schedule allows. function releaseProceeds(bytes32 launchId) external returns (uint256 amount); /// @notice Halt release pending adjudication. Caller MUST be authorized by /// the remediation contract. MAY be called again on a frozen launch /// to renew the window. function freezeLaunch(bytes32 launchId, bytes32 reportId) external; /// @notice Return the caller's residual bond once the launch is finished /// with and no buyer can still reach it. /// @dev Bond that can leave only through an upheld claim is bond that an /// honest launch never recovers. function returnBond(bytes32 launchId) external returns (uint256 amount); /// @notice Buyer pulls their pro-rata share of an opened refund pool. function claimRefund(bytes32 launchId) external returns (uint256 amount); function stateOf(bytes32 launchId) external view returns (LaunchState); function escrowedProceeds(bytes32 launchId) external view returns (uint256); function maxFreezeDuration() external view returns (uint64); } ``` Implementations MUST enforce the following invariants: 1. `Settled` is terminal. Once proceeds are fully released and the release period has ended, a launch MUST NOT re-enter `Frozen` or `Refunding`. 2. `releaseProceeds` MUST NOT release more than the linear schedule between `releaseStart` and `releaseEnd` permits, and MUST revert while `Frozen`. 3. `freezeLaunch` MUST be callable only by the remediation contract or an address it authorizes, and only while `Active`, `Releasing` or `Frozen`. A frozen launch MUST accept renewal, because the window is bounded while adjudication is not: a decision reached after the window has lapsed would find the proceeds already released, and could refund only from the bond. 4. A frozen launch MUST return to `Releasing` if no claim is adjudicated within `maxFreezeDuration()` measured from the most recent renewal. Implementations MUST renew the window on every claim opened against the launch and again on an upheld decision, and MUST NOT renew it for any other reason. Renewal tied to nothing a claimant paid for is indefinite freezing, which is a censorship vector and MUST NOT be permitted. 5. The release period MUST NOT exceed 90 days. A longer period constitutes indefinite custody of a deployer's funds rather than settlement of a sale. 6. `recordPurchase` MUST be callable only by the venue, and MUST be called for every purchase. A launch whose purchases are not fully recorded cannot be refunded correctly. 7. Residual bond MUST be returnable to the party that posted it, once the launch is `Settled` and no buyer can still open a claim or pull a refund against it. A deployment where bond can leave only through an upheld claim asks every honest deployer to forfeit collateral for having behaved, which is an argument against posting it at all. Implementations holding bond from more than one party MUST apportion what survives a slashing in the proportions it was posted, and MUST record who posted it: an escrow that knows what it holds and not whose it is cannot return anything. A launch that recorded no purchases MUST also be able to return its bond, since settlement is defined by proceeds released and there were none. Deployments SHOULD set the release schedule so that a meaningful share of proceeds remains escrowed through the period in which abuse typically occurs. A `releaseStart` at launch with `releaseEnd` at 30 days is RECOMMENDED. #### Refund Computation On an upheld claim, the implementation MUST open a refund pool consisting of all escrowed proceeds plus any amount drawn from the deployer's bond. Each buyer's entitlement is: ``` entitlement(buyer) = pool * netContributionOf(buyer) / totalNetPaid ``` Refunds MUST be distributed by pull, never by iteration over buyers. A launch may have thousands of buyers, and a push distribution is unbounded in gas and fails as a result. `netContributionOf` MUST subtract the value the buyer already realised by selling. A buyer who sold at a profit before the abuse occurred has not been harmed, and refunding that buyer from a pool shared with buyers still holding would transfer value from the harmed to the unharmed. Unclaimed refunds MUST remain claimable for at least 180 days. After that, implementations MAY sweep the remainder, and MUST disclose where it goes. ### Part 3: Remediation This part is addressed to adjudicators and to venues at full conformance. A venue at consumer or detection conformance has no obligations here, and requires only the containment ladder below. ```solidity enum ClaimStatus { None, Open, Contested, Settled, Upheld, Rejected, Executed, Expired } enum ContainmentAction { None, Flag, ExtendSchedule, SuspendRelease, Freeze, Refund } interface ILaunchRemediation { event BondPosted(bytes32 indexed launchId, uint256 amount); event BondReleased(bytes32 indexed launchId, uint256 amount); event BondSlashed(bytes32 indexed launchId, uint256 amount, bytes32 claimId); event ClaimOpened(bytes32 indexed claimId, bytes32 indexed launchId, address claimant, uint256 bond); event ClaimContested(bytes32 indexed claimId, address respondent, string evidenceURI); event ClaimSettled(bytes32 indexed claimId, uint256 amount); event SettlementOffered(bytes32 indexed claimId, uint256 amount); event SettlementWithdrawn(bytes32 indexed claimId, uint256 amount); event ClaimAdjudicated(bytes32 indexed claimId, ClaimStatus outcome, uint256 award); event RemedyExecuted(bytes32 indexed claimId, uint256 fromEscrow, uint256 fromBond); event ContainmentApplied(bytes32 indexed launchId, ContainmentAction action, uint64 until); event DetectorRewarded(bytes32 indexed claimId, address indexed detector, uint256 amount); /// @notice Add collateral to a launch that is already registered. /// @dev The bond is opened by `ILaunchEscrow.registerLaunch`, whose /// `bondAmount` becomes the initial balance; this tops it up. Both /// accumulate into one balance held by the escrow, which is the only /// contract that moves it. `requiredBond` states what a venue demands /// before opening a launch; it does not itself hold or transfer value. /// The balance MUST remain locked until the release period ends plus /// `bondCooldown()`. function postBond(bytes32 launchId) external payable; /// @notice Minimum bond for a stated target raise. function requiredBond(uint256 targetRaise) external view returns (uint256); /// @notice Open a bonded claim against a launch. function openClaim(bytes32 launchId, bytes32 reportId, string calldata evidenceURI) external payable returns (bytes32 claimId); /// @notice Atomically register a report and open a claim, so the deployer /// cannot act in the gap between submission and freeze. function submitAndClaim( AbuseReport calldata report, string calldata evidenceURI ) external payable returns (bytes32 reportId, bytes32 claimId); /// @notice Contest a claim. MUST be callable only within `contestWindow()`. function contest(bytes32 claimId, string calldata evidenceURI) external; /// @notice Offer to close a claim by agreement, without adjudication. /// Callable by the deployer while status is Open or Contested. /// @dev An offer MUST NOT settle a claim on its own, and `amount` MUST be /// greater than zero. A deployer able to close a claim unilaterally /// could answer every claim against it with a settlement worth /// nothing, and no claim would ever reach an outcome it did not choose. function settle(bytes32 claimId, uint256 amount) external payable; /// @notice Accept a standing offer. Caller MUST be the claimant. /// @param expected the offer being agreed to. Implementations MUST reject /// the call where the standing offer differs, so that an offer /// cannot be replaced in front of the acceptance. function acceptSettlement(bytes32 claimId, uint256 expected) external; /// @notice Withdraw an offer the claimant has not accepted. Caller MUST be /// the deployer. An offer MUST NOT survive adjudication or expiry. function withdrawSettlementOffer(bytes32 claimId) external; /// @notice Resolve a claim. Caller MUST be the adjudicator. function adjudicate(bytes32 claimId, ClaimStatus outcome, uint256 award) external; /// @notice Open the refund pool from escrowed proceeds, drawing any /// shortfall up to `award` from the deployer's bond. function executeRemedy(bytes32 claimId) external returns (uint256 fromEscrow, uint256 fromBond); function getClaim(bytes32 claimId) external view returns (bytes32 launchId, address claimant, ClaimStatus status, uint256 award); function bondOf(bytes32 launchId) external view returns (uint256); function contestWindow() external view returns (uint64); function bondCooldown() external view returns (uint64); function feeBps() external view returns (uint16); /// @notice Share of a successful restitution paid to the detector whose /// report supported the claim. MUST NOT exceed feeBps(). function detectorFeeBps() external view returns (uint16); /// @notice Pull the detector's share of an executed remedy. /// @dev MUST revert unless the claim is Executed. MUST pay the detector /// recorded against the report the claim referenced, never the caller /// and never the party that relayed an atomic submission. /// Where the share is reserved out of a bond rather than moved, the /// reservation MUST be netted off every later payout from that bond, /// or a subsequent upheld claim will spend it. function claimDetectorReward(bytes32 claimId) external returns (uint256 amount); } ``` #### Containment Ladder Automated response MUST be proportionate to score and confidence jointly: | Score band | Confidence >= 80 | Confidence 50-79 | Confidence < 50 | | --- | --- | --- | --- | | 81-100 | `Freeze` | `SuspendRelease` | `Flag` | | 61-80 | `SuspendRelease` | `ExtendSchedule` | `Flag` | | 41-60 | `ExtendSchedule` | `Flag` | `None` | | 0-40 | `Flag` | `None` | `None` | `Refund` MUST NOT be reachable automatically. It MUST require an upheld claim. Detection alone MUST NOT be sufficient to take a deployer's proceeds; that step MUST pass through adjudication with a right to contest. #### Claim Lifecycle 1. A claimant opens a claim referencing a live report with `abuseScore >= 61`, posting a bond. A buyer at the launch MAY open a claim, and so MAY a detector or the venue. A buyer receives a refund without opening one. 2. The implementation freezes the launch, halting further release of proceeds. 3. The deployer MAY contest within `contestWindow()`, RECOMMENDED to be 72 hours. 4. At any point before adjudication, the deployer MAY offer a settlement, which the claimant MAY accept. Implementations MUST offer this path, since most disputes can be resolved bilaterally at lower cost, and routing every claim through an adjudicator makes that body both a bottleneck and more powerful than the role requires. Settlement MUST require both parties: the offer MUST come from the deployer and the acceptance from the claimant, and an offer MUST be for more than zero. A deployer able to close a claim unilaterally could discharge every claim without payment, which would nullify the remedy. 5. If uncontested, the claim MAY be upheld by default after the window. If contested, the adjudicator MUST resolve it. 6. On `Upheld`, `executeRemedy` opens the refund pool from escrowed proceeds and draws any shortfall up to `award` from the bond. The claimant's bond is returned. Buyers then pull their entitlements. A claim MAY be opened against a launch that is already `Settled`, and a deployment MUST NOT refuse one on that ground alone. Its proceeds are beyond reach, which is the cost of a lapsed window, but its bond is not, and refusing the claim would put that beyond reach as well. 7. On `Rejected`, the launch MUST return to `Releasing`, and the claimant's bond MUST be forfeited, in part to the deployer and in part to the detector pool defined by `detectorFeeBps`. The pool MUST have a defined route to detectors, since value taken from claimants and payable to no party serves no purpose. 8. If no adjudication occurs within `maxFreezeDuration()`, the claim MUST become `Expired`, and the launch MUST return to `Releasing`. #### Funding Adjudication has a cost, and a dispute system without revenue depends on volunteers, which does not scale with volume. The same applies to detection, on which every other part of this proposal depends: a detector is asked to post slashable collateral, operate an indexing pipeline, commit to chain-anchored evidence and publish measured accuracy, and none of that is free. Implementations MUST expose `feeBps` and `detectorFeeBps`, where `detectorFeeBps` is the share of a successful restitution paid to the detector whose report supported the upheld claim, and MUST NOT exceed `feeBps`. Both SHOULD be funded from restitution rather than from protocol subsidy or from detector bonds, so that the cost falls on the process that consumes it. Restitution-linked payment alone rewards only detection that arrives after harm. Venues MAY therefore pay detectors directly for reports on launches they list, and implementations MUST NOT prohibit it. Such payment MUST NOT be conditioned, in contract or in agreement, on the score a report returns. Payment conditioned on the score purchases the outcome rather than the analysis. #### Error Codes ```solidity error UnknownReport(bytes32 reportId); error ReportAlreadyRetracted(bytes32 reportId); error ReportStale(uint64 windowEnd, uint64 maxAge); error InsufficientScore(uint8 score, uint8 required); error InsufficientConfidence(uint8 confidence, uint8 required); error OutcomeSignalNotPermitted(); error InvalidSignalVector(); error UnsupportedVectorVersion(uint16 declared, uint16 supported); error UnknownExtensionSchema(bytes32 extensionSchema); error InvalidPattern(bytes32 patternId); error DetectorNotBonded(address detector, uint256 held, uint256 required); error UnknownLaunch(bytes32 launchId); error LaunchNotFreezable(bytes32 launchId, LaunchState state); error LaunchSettledAlready(bytes32 launchId); error FreezeExpired(bytes32 launchId, uint64 frozenUntil); error ReleaseScheduleExceeded(uint256 requested, uint256 available); error NotVenue(address caller); error NotRemediation(address caller); error PurchaseAlreadyRecorded(bytes32 launchId, address buyer); error NothingToRefund(bytes32 launchId, address buyer); error RefundWindowClosed(bytes32 launchId, uint64 closedAt); error ClaimNotOpen(bytes32 claimId, ClaimStatus status); error ContestWindowClosed(bytes32 claimId, uint64 closedAt); error NotAdjudicator(address caller); error InsufficientBond(uint256 held, uint256 required); error BondLocked(bytes32 launchId, uint64 unlockAt); error ContainmentNotPermitted(ContainmentAction requested, ContainmentAction maximum); ``` ### Integration Hook Wallets, aggregators, and venues that wish to consult detection without operating escrow MAY implement or call a guard: ```solidity interface ILaunchGuard { /// @notice Non-reverting advisory check on a launch. function checkLaunch(bytes32 launchId) external view returns (ContainmentAction action, uint8 abuseScore, bytes32 reportId); } ``` `checkLaunch` is declared `view` and MUST NOT modify state. Consumers MUST invoke it with `STATICCALL` as defined in [EIP-214](./eip-214.md), so the read-only guarantee is enforced by the EVM rather than by implementer discipline. Because the `STATIC` flag propagates to sub-calls, a guard cannot mutate state through delegated or proxied logic either. Consumers MUST treat a guard that reverts, runs out of gas, or returns malformed data as `ContainmentAction.None` and MUST NOT propagate the failure. A guard invoked inside a purchase path that can revert is a censorship primitive: any party able to make it fail could block every purchase that consults it. Consumers SHOULD forward a bounded gas stipend. ## Rationale ### The Deployer as Subject Buyers at a launch are harmed by the party that created the asset, not by an anonymous cohort. That gives one identifiable respondent instead of a statistical cluster, one who can be required to post collateral, reachable through a venue that is a natural enforcement point. "Created the asset" means the party that brought the launch, not the address that signed the deployment. Those are usually different: most venues deploy the token themselves from a factory, so the applicant never appears as a creator anywhere on chain. The subject of detection is therefore declared by the venue rather than inferred, which is also the only reading under which detection tells a buyer anything: a signal every launch at a venue shares cannot separate one launch from another. ### Exclusion of Price Decline This is the constraint the rest of the design rests on. Scoring outcome would flag every honest failure as fraud, and would be gameable in reverse, since a deployer who rugs a rising token would score well. Restricting the vector to deployer actions makes the score answer "what did this person do", which is the only question a remedy can rest on. ### Custody of Proceeds A deployer will not voluntarily adopt reversibility, so an opt-in reversible token protects nobody from the party it targets. The venue already sits between buyer and deployer and wants launches that do not destroy its users. Adoption becomes a decision by the party with the incentive to adopt. ### Disclosure as a Requirement A venue that consults detection and does not repeat it to buyers has protected itself and nobody else, which inverts the purpose of the level. Disclosure is also the mechanism by which this standard spreads: a buyer who can see a score at one venue and not at another has a reason to prefer the first, and that preference is the only pressure on venues to adopt at all. ### A Level Requiring No Deployment A standard adopted by nobody protects nobody, and a tier that requires three contracts asks too much of the venues most likely to need it. The venues most likely to list a rug are the least likely to deploy anything. A level that costs one view call and a line of interface reaches them, and it is the level from which every other one becomes reachable later. The cost of that is that consumer conformance cannot be verified on-chain. A venue at this level deploys nothing, so there is no `supportsInterface` to interrogate and no way for a third party to distinguish a venue that consults the guard and discloses what it finds from one that says it does. This proposal states the obligation and does not attempt to enforce it: any mechanism that made the claim checkable would put a deployment back into the one level defined by not having one. Consumers and aggregators MUST therefore treat a claim of consumer conformance as a claim, and SHOULD verify it by observing whether a score is actually presented at the point of purchase. Only full conformance is verifiable from chain state. ### Detector Payment An earlier draft funded adjudication and left detection unfunded, which made the only detector revenue a share of forfeited bonds from false claims: a detector that was never wrong would have earned nothing. Paying from restitution aligns the detector with upheld findings. Permitting venues to pay directly is what funds the reports that prevent harm rather than document it, and forbidding score-conditioned payment is what keeps that from becoming a market in clean opinions. ### Pull-Based Refunds A launch may have thousands of buyers, so push distribution is unbounded in gas. Netting off realized gains stops a buyer who exited profitably from drawing on a pool shared with buyers still holding. ### Refunds Without a Claim The venue recorded every purchase, so entitlements come from data it already holds. This is why the design works at a launch and would not for open-market manipulation, where attacker and victims never transact with each other, and there is no bilateral transfer to reverse. ### Scheduled Release Immediate release makes the outcome final before detection is possible; indefinite withholding makes the venue a custodian. A linear schedule capped at 90 days keeps a balance reachable while abuse occurs and still guarantees the deployer a defined path to their money. ### Chain-Anchored Evidence A root over arbitrary detector-supplied data proves self-consistency, not truth. Requiring `(chainId, blockNumber, txHash, logIndex)` lets anyone recompute the vector and prove a report false, which is the precondition for slashing a bond. Without it, the detector is an unaccountable oracle. ### Account Recovery Excluded Reversibility designs often bundle recovery of lost accounts, which founders on verifying that a claimant owns an account they say they lost. Here ownership is never in question: entitlements derive from the venue's purchase records, not from a claimant's assertion. ### The Fee on Restitution Chargebacks work in card networks because those networks levy fees that fund the dispute machinery. A dispute process with no revenue depends on unpaid adjudicators and does not survive volume. ### Settlement by Agreement Requiring settlement keeps the adjudicator from being both a bottleneck and the only route to resolution, which would concentrate power in the role this proposal already identifies as its weakest point. Requiring the claimant to accept is what keeps the same path from becoming a veto: a respondent who can close a claim by naming a figure would name zero, and every freeze, adjudication and refund in this proposal would end at the discretion of the party they were built to reach. ### Alternatives Considered A reversible token standard was rejected because the deployer chooses the token and would not adopt it. A detection registry with no remedy reproduces the current situation, where rug pulls are legible after the fact and unactionable. Requiring venues to hold proceeds indefinitely is indistinguishable from custody. ## Backwards Compatibility This ERC introduces new interfaces and modifies none. It requires no changes to [ERC-20](./eip-20.md) tokens; the launched token need not know the standard exists, which matters because the deployer controls that contract and cannot be relied on to cooperate. Buyers hold ordinary tokens with no transfer restrictions. A refund entitlement is a claim against the escrow, not an encumbrance on the token, so secondary trading is unaffected. `netContributionOf` accounts for buyers who sold. A venue MAY set `releaseEnd` equal to `releaseStart`, in which case proceeds release immediately, and the escrow behaves as a pass-through. This provides a migration path and lets a venue adopt detection before adopting escrow. For a venue, the cost of adoption by level is as follows. **Consumer conformance** changes nothing on-chain. One view call in the purchase path, guarded by `STATICCALL` and a bounded gas stipend, and a disclosure in the buying interface. No contract to deploy, no custody, no change to settlement. **Detection conformance** adds a directory listing per launch. Proceeds still settle as they do today. **Full conformance** changes one externally visible behavior: proceeds reach the deployer on a schedule rather than immediately, capped at 90 days. Deployers integrating with such a venue MUST NOT assume funds are available at launch. This is the only change in this proposal that alters what a deployer receives, and venues SHOULD expect it to be the one they negotiate over. ## Test Cases Conformance tests MUST cover at minimum the thirty-four cases published in [Conformance Test Cases v0.1](../assets/eip-8376/20260830-ERC_8376_Conformance_Test_Cases-v0.1.md), which carry the same force as if inlined here. They cover score reproducibility and protective polarity, exclusion of unavailable signals, the release schedule and freeze bounds, pro-rata and net-contribution correctness, identifier derivation and chain binding, disclosure at the point of purchase, the return of residual bond, a registry's resistance to being silenced by volume, attribution of a launch to the applicant rather than to the factory that deployed it, a honeypot established by sellability rather than by bytecode, and the three authorities on a shared registry. ## Reference Implementation [ReferenceDetector.sol](../assets/eip-8376/ReferenceDetector.sol) derives the chain-readable signals, scores a vector against a pattern profile with unavailable signals excluded rather than counted as zero, and returns the containment action a venue acts on. It follows proxies when scanning for privileged powers, and sets the upgrade bit for a delegating token whether or not its implementation can be resolved. This derives the chain-readable signals, scores a vector under a pattern profile, and returns the containment action a venue acts on. It is not audited and is not intended for deployment as it stands. A venue holding buyers' proceeds SHOULD commission a review of any escrow and remediation implementation before operating one. ## Security Considerations ### Distinguishing Failure From Fraud This is the central difficulty the standard faces. Most launches decline because nobody wanted the token. The conduct-only rule is the primary defense, but it is not complete: a deployer can sell an allocation for legitimate reasons, and an unlocked pool is careless rather than dishonest. Deployments MUST NOT treat any single adverse signal as dispositive, and SHOULD require corroborating signals before admitting claims. A standard that mislabels honest failure as fraud will be abandoned by the deployers it needs to adopt it. ### Publication Races the Remedy A report names its subject publicly, and a deployer watching the registry learns it has been detected before anything freezes. In the worst case, the detector's transaction is visible in the mempool, and the deployer withdraws with higher priority in the same block. `submitAndClaim` exists to close this window, and detectors MUST use it. Deployments SHOULD evaluate whether their sequencing exposes even the atomic call. ### The Venue Is Trusted and Conflicted The venue records purchases, holds proceeds, and may operate or select the adjudicator, while also earning fees on launches. A venue can under-record purchases, mis-set the schedule, or decline to freeze a launch it profits from. This standard does not remove that trust; it makes the venue's behavior observable through events so that misconduct is at least detectable. Buyers MUST understand that adopting this standard does not make a venue trustworthy. ### Adjudicator Capture The adjudicator can uphold a fabricated claim and redirect proceeds, or reject a valid one. It is the most concentrated trust in this proposal, and the requirements below are the minimum that make it accountable. The adjudicator address MUST be readable on-chain and MUST NOT be changeable after initialization: a role that can be repointed can be captured without anyone observing the moment. Every adjudication MUST reference published reasoning through the claim's evidence URI, so a decision can be argued with rather than merely obeyed. An adjudicator who is also the venue, a detector, a claimant, or otherwise interested in the launch MUST be disclosed before it acts. Deployments SHOULD NOT use a single externally owned account. Two designs are recommended: an n-of-m committee whose membership and replacement procedure are published, or an optimistic scheme in which a proposed outcome executes only after a challenge window during which any bonded party can escalate. A committee SHOULD bind each approval to the exact outcome and award it is for, so that a vote cast for one decision cannot be counted toward another. Either bounds the damage a single compromised key can do, which a single address does not. Deployments SHOULD provide an appeal path, and where none exists MUST say so, since buyers and deployers price that absence differently. ### The Detector Adjudicator Cannot Be the Detector A bond is what separates a report from an opinion, and it separates them only while somebody unconflicted can take it. A registry whose adjudicator is its own detector satisfies every interface in this proposal and none of its intent: the calls exist, the bond is posted, and nothing can ever remove it. Refusing a detector bond from the adjudicator address catches the blunt form and no more. An adjudicator that is a multisig one of whose signers operates a detector is indistinguishable on-chain from an independent one, as is an adjudicator acting for a detector off-chain. `detectorAdjudicator()` is therefore readable, and consumers relying on a registry SHOULD read it and SHOULD treat reports as unbonded where it resolves to the detector that published them, or to a party controlling that detector. Single-operator deployments MUST NOT present their reports as bonded or slashable, and this is a common case rather than an edge one: an operator running the only detector on a registry it deployed has no unconflicted party available and cannot obtain one by rearranging addresses. Such a deployment is conformant at the consumer level, which requires no detector of its own. Claiming more is the failure this section exists to name. ### Claim Spam and Griefing Freezing halts a deployer's funds, so opening claims is an attack if it is cheap. Claimant bonds, `maxFreezeDuration()`, and mandatory resumption on expiry bound the damage, but a well-capitalized adversary can still impose cost on a competitor's launch. Deployments SHOULD scale claimant bonds with the amount frozen and SHOULD rate-limit claims per claimant per launch. ### Detector Collusion A detector colluding with a claimant can manufacture the score needed to open a claim. Chain-anchored evidence makes fabrication provable after the fact, and bonding prices it, but deployments SHOULD require corroboration from independent detectors before admitting high-value claims. ### Bond Sizing The bond determines whether the remedy is real. Once proceeds are released, the bond is the only source of restitution, so a bond smaller than the raise leaves buyers uncompensated in exactly the cases that matter most. `requiredBond` MUST scale with the target raise rather than sitting at a nominal floor, and SHOULD NOT be less than 25 percent of it. A venue MUST publish the bond it requires before a launch opens and MUST keep the posted amount readable on-chain throughout, so a buyer can price the uncovered remainder rather than discovering it after a claim. Venues competing on volume will be tempted to set this low; one that does is transferring risk to its buyers and SHOULD say so plainly. ### Sybil Deployers `priorUpheldClaims` is trivially reset by launching from a fresh address. It is weighted lowest in the reference profile for that reason, and deployments MUST NOT treat its absence as evidence of good faith. Linking deployers across addresses is a heuristic, and false linkage is the most damaging error this proposal can make: it brands a deployer a repeat offender on evidence they cannot rebut, and `PATTERN_SERIAL_DEPLOYER` exists to act on exactly that. Implementations SHOULD carry linkage uncertainty in `confidence` rather than in `abuseScore`, so that a weak identification limits the response rather than strengthening the accusation. ### Reputation Signals Start Empty `priorUpheldClaims` is the only signal whose value depends on this proposal already having been adopted and exercised. Before any claim has been upheld anywhere, every deployer scores zero on it, honest and abusive alike, while still consuming weight in the profile. A detector MUST report `priorUpheldClaims` as unavailable, rather than as zero, until the chain it is reporting on has a claim history large enough for the absence of claims to carry information. Reporting zero from an empty registry excludes nothing and silently lowers every score by the weight of a signal that was never evaluated. Cross-chain history compounds this: a directory covers one chain, so a deployer's record elsewhere is invisible without off-chain aggregation, which this proposal does not define. ### Silencing by Volume A registry that answers from its most recent reports can be silenced by whoever writes the most. One bonded address publishing padding against its own launch pushes every genuine report out of the window: the score then reads clean, the guard advises no containment, and corroboration reads unanimous at one, which blocks the high-value claims that require it. The flood is repeatable, including as a front-run of the claim it blocks, and it costs a single bond. Bounding a read by position is what creates this, because position is the one thing a submitter controls. Implementations MUST read every live report, and SHOULD hold per-launch aggregates so that doing so is cheap. Capping the live reports one detector may hold on one launch bounds the work honestly, since it limits what a single party can write rather than what anybody can read. ### Evasion Publishing the signals tells deployers exactly what is measured. A deployer can lock liquidity for the minimum period and exit at unlock, distribute an allocation across many addresses before launch to suppress `deployerSupplyShare`, or renounce privileged powers after positioning. `PATTERN_UNLOCK_EXIT` and `insiderAllocationShare` exist to catch two of these, but the general point stands: this raises the cost of abuse and does not eliminate it. Deployments SHOULD vary thresholds and MUST NOT treat a low score as evidence of legitimacy. ### Attacks on the Refund Pool A deployer who anticipates a claim can buy their own launch through fresh addresses to dilute other buyers' pro-rata shares. `markLinked` exists for this: an excluded address is removed from `totalNetPaid` as well as from the payout, so honest buyers are restored to the share they would have had rather than merely stopped from losing more. Adjudicators SHOULD treat late self-purchase as an aggravating signal. The mechanism depends on identifying the linkage, which is a heuristic, and a wrong exclusion takes a legitimate buyer's refund: implementations SHOULD require the same evidentiary standard for exclusion as for the claim itself. ### Realized Value Is Visible Only at the Venue `netContributionOf` subtracts what a buyer realized by selling, and `recordSale` may be called only by the venue. A venue observes sales made through it and no others. On a bonding curve that holds while the curve is the only market, and stops holding the moment liquidity graduates to an external pool, which is the ordinary end state of a successful launch and where most selling occurs. After graduation, a buyer who exited profitably on an external market retains a net contribution equal to their full purchase price and draws the same pro-rata share as a buyer still holding. The pool is finite, so that share is taken from buyers who did lose money. The failure is silent: the refund completes and is wrong. Implementations SHOULD bound refunds to the period in which venue records are complete, and SHOULD document where that period ends. An implementation MAY instead permit realizations on external markets to be proven against chain state and netted off, at the cost of requiring claimants to produce that proof. Implementations MUST NOT present a pro-rata refund as equitable without stating which of these it does. ### Extraction Outside the Token Every signal in the base vector describes the token, the pool balance, or an action by the deployer. A restriction imposed by the mechanism that trades the token is described by none of them. A token observed on Base mainnet held no privileged roles, attached no transfer policy and paused nothing, while the single pool trading it ran a hook returning approximately 0.1 percent of the value of a round trip to ordinary callers and approximately one thousand times that proportion to the deployer for the identical sell. Establishing this required no transaction against the token. The base vector cannot express it, and neither half of the sellability schema reaches it on its own: `blockedHolderShare` reads zero, because the transfer succeeds, and a restriction held in a pool sets no bit in `privilegedPowers`, which is read from token bytecode. `proceedsRetainedShare` is the field it belongs to, and establishing that needs the amount out compared against the pool's reserves rather than a transfer attempt, which is why the schema specifies the two separately. Deployments MUST NOT treat a clean vector, or a clean reading of that schema, as evidence that a position can be exited, and SHOULD examine the mechanism trading a launch separately from the token. A detector reporting on that mechanism SHOULD distinguish an operation that reverts from one that succeeds and returns a fraction of the expected value, since an uninitialised curve or unopened trading reverts in volume at legitimate venues, while a successful call returning a fraction is a measurement. ### Scope This standard protects buyers only at venues that adopt it in full. A deployer who launches directly to an AMM is entirely outside its reach, and detection reports about such a launch carry no remedy at all. Implementations MUST NOT present a low score for an unescrowed launch as any form of protection. ### Privacy Reports name deployers and publish behavioral analysis permanently. A retracted report remains in event history, and an accusation is visible whether or not it is upheld. Detectors SHOULD publish the minimum necessary on-chain and disclose detailed analysis only in adjudication. ## Copyright Copyright and related rights waived via [CC0](../LICENSE.md).