A technical whitepaper
IP-Liquidator is a web application for registering intellectual-property assets, tracking their pledged value against acquisition goals, and recording on-chain tokenizations of those assets on the Base network (chain ID 8453). It consists of three components:
The application moves no money, extends no credit, and creates no legal liens. It is a tracking and record-keeping tool — not legal, financial, or tax advice. GSMC2 has been tested on a disposable local chain only; it is not deployed to Base mainnet.
Owners of intellectual property — music catalogs, software, crypto holdings, patents — commonly lack a single place to:
Existing tools either hide their valuation assumptions, silently accept owner numbers as if they were appraisals, or combine tracking with custody of funds. IP-Liquidator separates these concerns: the app tracks and enforces pledge limits in its database; any on-chain action happens in the owner's own wallet, outside the app.
The system implements a six-stage asset lifecycle:
Leads → Valued → Vault → Pledged → Tokenized → Recorded
garcia-sounds/leads.html implements a native Firestore-backed intake pipeline with stages:
New → Under Review → Valued → Tokenized → Closed
Each lead carries per-lead valuations, and every stage transition is written to a write-once audit log that records the acting user's signed-in Google account email. A lead at the Valued stage can be promoted directly into the IP Vault as a registered asset.
A valuation is recorded on the lead or asset using one of five input paths: trailing royalties, stream counts, recurring revenue, a live crypto spot price, or the owner's own estimate. An optional in-form Appraise helper suggests a value computed from the reference formulas (Section 5). The owner may accept, edit, or ignore the suggestion. What is saved is always tagged with its source.
garcia-sounds/vault.html registers assets — music, apps/software, crypto, patents, and other IP — as collateral records. Assets may be promoted from leads or registered directly. Every value in the vault is stored with valueSource: "self-reported" and displayed with a self-reported tag, regardless of which input path produced it.
garcia-sounds/acquire.html lets the owner create acquisition goals and pledge registered assets toward them. The double-pledge guard (pledgeToGoal in js/store.js) runs inside a Firestore transaction: an asset's total pledged value across all goals can never exceed its registered value. The check is atomic against the database, so a hand-edited form or a second browser tab cannot bypass it. The reference engine enforces the same invariant off-chain (Section 6).
garcia-sounds/tokenization.html plus contracts/GSMC2.sol. The application itself never mints: it has no wallet connection and no blockchain RPC access. The owner mints a GSMC2 ERC-1155 token ID per asset in their own wallet on Base, then records the token ID and transaction hash in the app. The tokenization page links to basescan.org so any recorded hash can be verified independently. The contract's encumber/release functions mirror the application's pledge ledger on-chain (Section 7).
garcia-sounds/transactions.html. Every vault registration, pledge, tokenization, and goal event is written to a Firestore transactions collection. The security rules deny updates to this collection (allow update: if false), making the ledger append-only. Entries can be exported as CSV.
The application is a static ES-module site (no build step) deployed to Netlify, backed by Firebase Authentication (Google sign-in) and Cloud Firestore.
users/{uid}/...)| Collection | Purpose |
|---|---|
assets |
Registered vault assets: name, type, estValue, status, description, dateAdded |
goals |
Acquisition goals: name, targetValue, status, pledges[], dateAdded |
tokenizations |
Recorded mints: assetId, chain, tokenId, txHash, dateAdded |
transactions |
Append-only ledger: type, label, amount, date |
catalogTracks |
Music catalog entries: title, genre, estValue (nullable), filename, durationSec, format, source |
leads |
Intake pipeline records with stage and valuations |
auditLogs |
Write-once per-lead audit trail (actor email, transition, timestamp) |
There are no cross-account or public collections. No platform-wide aggregates exist in this build.
Per-account isolation is enforced by firestore.rules, not by application code alone:
users/{uid} subtree.transactions denies updates entirely; auditLogs is write-once.catalogTracks explicitly permits estValue: null, representing the "Unvalued" state — tracks imported without prices are not assigned invented values.netlify.toml sets response headers including Strict-Transport-Security, X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy, Permissions-Policy, and a Content Security Policy restricting scripts to self and gstatic.com, connections to Google/Firestore/Identity endpoints, and frames to accounts.google.com (Google sign-in) with frame-ancestors 'none'.
The valuation engine exists in two forms: a Node reference implementation (workspace/ip-liquidator/valuation.js, zero dependencies, with a pressure-test suite in test.js) and a browser port (garcia-sounds/js/valuation.js) used only as the advisory Appraise helper. Both implement the same formulas.
| Asset class | Formula |
|---|---|
| Music (royalties known) | trailing-12-month royalties × 8× catalog multiple |
| Music (streams only) | streams × $0.004/stream × 8× |
| App / software | monthly revenue × 12 × 2.5× ARR multiple |
| Crypto | live CoinGecko spot price × quantity, less 15% volatility haircut |
| Patent | owner estimate only — always flagged self-reported |
These multiples are exposed as tunables in the reference code. They are ordinary industry rule-of-thumb ranges, not certified appraisals. The paper states this plainly because it is true: the engine computes arithmetic on inputs; it does not appraise.
| Asset class | Max LTV |
|---|---|
| Music | 40% |
| App / software | 45% |
| Crypto | 65% |
| Patent | 25% |
The advertised platform maximum is 40% LTV. Worked example from the test suite: 13 music masters valued at $325,000 support up to $130,000 of credit at the 40% music cap.
The in-app engine is suggestion-only:
valueSource: "self-reported" and rendered with a SELF-REPORTED tag.The engine's code contains no Firestore write calls — it cannot persist anything on its own. It never overrides an owner-entered value and never presents an owner number as formula-derived. The reference implementation's own documentation states the rule: self-reported values are labeled everywhere they appear; the engine will not launder an owner's number into looking like a formula produced it.
This labeling is a core integrity feature, not a cosmetic one. Any downstream consumer of vault data — a pledge calculation, a token issuance record, a CSV export — can see exactly which values came from formulas and which came from the owner.
Two layers enforce the same invariant: one unit of collateral value backs at most one obligation.
pledgeToGoal(goalId, assetId, amount) in js/store.js:
estValue and the sum of its existing pledges across all goals.existing pledges + new amount > estValue.Because the check executes inside the transaction against current database state, concurrent tabs or hand-edited client forms cannot over-pledge. The UI additionally shows per-asset available amounts and clamps the pledge input, but the transaction is the enforcement point.
createVault() in valuation.js maintains an in-memory encumbrance ledger: registerAsset, pledge, and release operations, with pledge throwing when the requested amount exceeds unencumbered credit (maxCreditUsd − encumberedUsd). The ledger is append-only; entries are never edited or deleted. A verified test case: after pledging $100,000 against a vault, a $50,000 token-backing attempt is rejected because only $28,000 of credit remains unencumbered.
The GSMC2 contract's encumber/release functions (Section 6) provide the same guard for token units: encumbered units cannot be transferred until released.
GSMC2 ("Garcia Sounds Coin 2") is an ERC-1155 fractional royalty-unit contract:
ERC1155 + Ownable.issue(supply, valuationUsd, proofURI) mints the full supply to the contract owner and stores a valuation snapshot, a proof URI (IPFS or metadata identifying the underlying IP), and an encumbrance counter. Empty proof URIs are rejected; over-encumbrance is rejected._update hook. Non-allowlisted transfers revert.encumber(id, amount, label) locks units as loan backing; release(id, amount, label) unlocks them. Encumbered owner units cannot move until released. Events (Issued, Encumbered, Released, AllowlistSet) provide an on-chain audit trail mirroring the application's pledge ledger.uri(id) returns the stored proof URI for the token ID.This separation is deliberate and is restated here because it is the most commonly misunderstood point: the Garcia Sounds application has no wallet connection, no private keys, and no blockchain RPC access. It cannot mint, transfer, or encumber tokens. The Tokenization page is a form for recording the token ID and transaction hash of a mint the owner performed themselves, in their own wallet, on Base. The page links to basescan.org so each recorded hash is independently verifiable. The application itself has no way to confirm a hash — it records what the owner attests.
GSMC2 compiled cleanly with solc (8,258 bytes of bytecode, 38 ABI entries) and passed a six-check end-to-end suite on a disposable local chain (chain ID 31337): issuance, encumbrance, blocked over-transfer, allowlisted transfer, release, and blocked outsider transfer. It is not deployed to Base mainnet. Deployment requires the vault owner's explicit wallet signature — via a wallet-signing flow (MetaMask or Coinbase Wallet), never by transmitting a private key. The repository includes a WALLET_DEPLOY_CHECKLIST.md (network: Base 8453; owner address; proof URI; valuation; supply; gas estimate; explicit signature step). The script-based deploy path uses a DEPLOYER_KEY environment variable on the owner's own machine only.
The application ships with a real catalog: 12 uploaded audio files were measured and deduplicated to 6 unique tracks (files sharing a title and identical duration are the same recording in different container formats):
| # | Track | Duration |
|---|---|---|
| 1 | 100 Bars | 3:40 |
| 2 | 2 Bad Bitches (+ alt version) | 3:55 |
| 3 | 2 Bad (Game Time) | 3:03 |
| 4 | A Hoe Will Fuck Everybody | 5:04 |
| 5 | Anika Incorporated | 4:16 |
| 6 | Anilize | 2:43 |
The seed script (catalog/seed-tracks.mjs) writes one catalogTracks document per track — title, filename, duration, format, source "audio-upload" — with estValue: null. No values are invented. The owner prices every track on the Catalog page; until then, tracks display as "Unvalued" and are excluded from collateral totals. The script is idempotent (skips filenames already present) and runs with the owner's own Firebase service-account key, which never leaves their machine.
| Control | Mechanism |
|---|---|
| Authentication | Firebase Auth, Google sign-in provider; every page except login redirects unauthenticated users |
| Authorization | firestore.rules: per-uid subtree isolation, collection shape validation, no catch-all |
| Pledge integrity | Firestore transaction in pledgeToGoal; atomic against concurrent writes |
| Ledger integrity | Security rules deny updates to transactions; audit logs are write-once |
| Input hygiene | Client templates escape user-entered strings; numeric fields validated non-negative in rules |
| Transport | HSTS, CSP, frame-ancestors 'none' via Netlify headers |
| Secrets | No private keys, mnemonics, or service credentials exist in the codebase; Firebase config is a placeholder the owner fills from their own console |
| On-chain | Allowlist-gated transfers; encumbered units immobile; owner-only issuance/encumbrance |
Known limits: the pledge guard is enforced in application code against Firestore, not in security rules themselves — a compromised client SDK session could still write directly, which is why rules additionally validate document shape. The application cannot verify tokenization hashes; it links to basescan.org for independent verification.
| Claim | Status |
|---|---|
| Google sign-in, per-account Firestore data | Real — enforced by firestore.rules, not just app code |
| Double-pledge rejection | Real — atomic check in pledgeToGoal against the database |
| Append-only transaction ledger | Real — rules deny updates to transactions |
| Leads pipeline + write-once audit trail | Real — native Firestore collections |
| Valuation formulas | Real math, advisory only — suggestion; owner values always labeled self-reported |
| Self-reported value labeling | Real — valueSource stored on every record; SELF-REPORTED tag rendered in UI, ledger, and engine breakdowns |
| Music catalog metadata | Real — 6 tracks, measured durations, seeded documents |
| Music catalog values | Not set — estValue: null until the owner prices each track |
| On-chain minting from the app | Not present — no wallet, no RPC; tokenization records are manual entries of owner-performed mints |
| Money movement / legal liens | Not present — tracking only; not legal, financial, or tax advice |
| GSMC2 on Base mainnet | Not deployed — local-chain tests passed; mainnet awaits the owner's wallet signature |
| Lovable hosted app | Exists separately — "Anika Incorporated // Base Network — IP-LIQUIDATOR"; recent changes uninspected against this build |
DEPLOYER_KEY path.js/ data layer was authored to complete the uploaded HTML shells; it needs testing against a real Firebase project (auth flow, pledge guard under concurrency, rules publish) before it is trusted with real records.This paper, like the build it describes, uses technology information only. Anything not implemented is labeled roadmap, never implied as live.
The following categories of language are not used in this project's copy, docs, or UI:
If a future feature touches any of these domains, it ships as an explicit roadmap item only after answering: what technology exists today, and what is only planned? Copy is corrected to match the answer, not the aspiration.
End of whitepaper v1.0 — 2026-09-18.