Abstract
Pivot is a compact application ledger that replaces smart-contract bloat with a tiny set of deterministic system calls (verbs). Users onboard with OAuth/Passkeys; wallets are non-custodial by default. Token identity is bound to DNS - every token pairs a domain with a tokenId—so clones can’t masquerade as the original. Apps deploy as small declarative manifests and call audited verbs like bank.transfer
or token.create
. A simple PoA consensus achieves sub-second finality; DPoS is a clean upgrade path.
Introduction
General-purpose smart-contract platforms created power and complexity at once. Builders wrestle with VMs, toolchains, fees, and audits; users wrestle with seed phrases and opaque approvals. Pivot’s thesis: most consumer apps need a ledger, balances, and a few safe verbs — not a Turing-complete VM. Constrain the surface → ship faster, safer apps.
Design Principles
- Minimal surface. Prefer a few stable verbs over an unbounded VM.
- Non-custodial UX. OAuth/Passkeys unlock local keys; users hold custody.
- Determinism. Verbs are pure, bounded, and auditable.
- Domain identity. Token identity =
(domain, tokenId)
. - Progressive decentralization. PoA → DPoS when usage warrants.
- Builder-first. REST endpoints + SDK, not contract languages.
Identity & Non-Custodial Wallets
Goal: users own their assets without seed-phrase pain.
OAuth + Passkeys
- On first login (Google/Apple/Discord), the client generates a local keypair (Ed25519/WebAuthn).
- The private key stays on device (Secure Enclave/Keystore). OAuth proves identity to use the key; the key is not stored by Pivot.
- Power users can export keys; most never need to.
Recovery
- New device: re-login via OAuth → derive or rebind a new key (prior key can be revoked).
- Optional guardians: a small set of addresses approve recovery; enforced by the account module.
Domain-Verified Tokens
To defeat copycat tickers, Pivot ties token identity to domain ownership.
Binding Flow
- Challenge:
POST /v1/domain/request_challenge {domain}
→{nonce}
. - Prove: author sets
TXT _pivot-verify.<domain> = <nonce>
. - Verify:
POST /v1/domain/verify {domain}
→ on success, writedomain/<domain> = { owner: <address> }
. - Create:
POST /v1/token/create { tokenId, domain, ... }
allowed only to the verified owner.
UX rule: wallets/explorers display TICKER @ domain
with a ✅ badge if a binding exists. Clones lack the badge.
State & Transactions
account/<addr>/balance
— native cointoken/<id>/balances/<addr>
— fungible balancesapp/<id>/manifest
— declarative methods (≤ 8–16 KB)app/<id>/storage/<key>
— app-scoped KV (bounded)domain/<domain>
— domain ownership record
{ "from": "ADDR", "nonce": 42, "ttl": 60, "calls": [ { "module": "bank", "fn": "transfer", "args": {"to":"ADDR2","amount":"1000"} } ], "signature": "ed25519..." }
System Modules (v0.1)
- bank:
transfer(to, amount)
- token:
create(tokenId, decimals, cap?)
,mint(tokenId, to, amount)
,transfer(tokenId, to, amount)
,burn(tokenId, amount)
- app:
register(appId, manifest)
,call(appId, method, args)
,emit(event, payload)
- storage:
put(appId, key, value)
,get(appId, key)
(bounded) - domain:
request_challenge(domain)
,verify(domain, nonce)
- curve (reference DEX):
create
,quote_buy
,quote_sell
,buy
,sell
,status
Security Model
- Scoped approvals: each
app.call
carries limits (tokenId, maxDebit, TTL). No infinite allowances. - Readable intents: gateway renders human text (e.g., “Send 1.0 NATIVE to receive 8,623 ZOOMER”).
- Determinism: verbs are pure, bounded; no reentrancy.
- Rate limits: daily free-ops cap + per-IP throttles as circuit breakers.
Consensus & Decentralization
Phase 1 — PoA
- 3–5 validators, static keys in
genesis.validators[]
. - Rotating leader; block time 250–500 ms; sub-second finality.
Phase 2 — DPoS (upgrade)
- Stake module (
delegate
,create_validator
). - Top-N validators per epoch; >⅔ signatures finalize.
Fees & Native Token
- Per-byte fee for tx bytes; storage rent for new data.
- Free tier (e.g., 100 ops/day/account) to keep UX smooth.
- Native token (
PVT
) for fees and staking; fixed supply or light inflation (e.g., 2%/yr) to pay validators.
Reference App — Bonding-Curve DEX
One audited module provides a “pump-simple” experience without custom contracts.
- Price:
P(S) = a + b·S
(linear). - Buy: integrate P over supply; mint ΔS; add native to reserve.
- Sell: reverse integral; burn ΔS; release native from reserve.
- Guards: cap supply, feeBps limit, minOut checks.
Bridge & Ownership Proofs
Pivot keeps bridging simple and auditable while staying non-custodial for users. The core idea is: (1) prove a deposit happened on the origin chain by a specific 0x key, and (2) prove the mint on Pivot goes to a Pivot address the user controls (they sign the claim tx with their Pivot key; OAuth only unlocks that key).
Design Stages
- Stage 0 — Gateway bridge: centralized operator proves UX. Not recommended long-term.
- Stage 1 — Attester bridge (recommended): N-of-M signers co-sign deposits/burns. Pivot verifies threshold signatures in a tiny
bridge
module. - Stage 2 — Light-client proofs: advanced, out of scope for MVP.
Ownership Confirmation (Two Clean Options)
Option A — Lockbox Contract (origin chain)
The deposit event embeds the pivotAddr
(the recipient on Pivot). Attesters mirror that to Pivot — no extra account linking.
/** Minimal lockbox for ERC-20 deposits */ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; interface IERC20 { function transferFrom(address,address,uint256) external returns (bool); } contract PivotLockbox { event Deposit( address indexed token, address indexed from, // 0x owner who authorized bytes pivotAddr, // Pivot address bytes (ed25519/bech32) uint256 amount, bytes32 depositId // unique (txHash|logIndex or a caller nonce) ); function deposit(address token, uint256 amount, bytes calldata pivotAddr, bytes32 depositId) external { require(IERC20(token).transferFrom(msg.sender, address(this), amount), "transferFrom fail"); emit Deposit(token, msg.sender, pivotAddr, amount, depositId); } }
Attested message → Pivot:
type: "deposit" chain: "eth-mainnet" token: "0xA0b8…" // origin token or lockbox from: "0xUser…" // depositor pivotAddr:"pivot1q…" // bytes/bech32 of Pivot address amount: "1000000" depositId:"eth:0xTX:logIndex"
Option B — SAFE + EIP-712 Bind Signature
No contract required on origin. User deposits into a Gnosis SAFE; then signs an EIP‑712 message binding that deposit to their pivotAddr
. Attesters check both the deposit and the signature.
// EIP-712 schema (example) domain = { name: "PivotBridge", version: "1", chainId: 1, verifyingContract: SAFE_ADDR } types = { BindDeposit: [ { name: "token", type: "address" }, { name: "from", type: "address" }, { name: "amount", type: "uint256" }, { name: "depositId", type: "bytes32" }, { name: "pivotAddr", type: "bytes" } ] } message = { token, from, amount, depositId, pivotAddr } signature = signTypedData(domain, types, message) // with the 0x wallet
Pivot Bridge Module (tiny, deterministic)
State
bridge/attesters/{setId}
→{ pubkeys[], threshold }
bridge/assets/{assetId}
→{ originChain, originAddr, decimals, attesterSet, wrappedTokenId }
bridge/seen/{depositId}
,bridge/seenBurn/{burnId}
→ replay protection
Verbs
set_attesters(setId, pubkeys[], threshold)
bind_asset(assetId, originChain, originAddr, decimals, attesterSet, wrappedTokenId)
claim({assetId, depositId, to, amount, signatures[]})
→ verify threshold sig; mint wrappedburn({assetId, amount, to, targetChain})
→ burn wrapped; emitBridgeBurn
API (Gateway)
POST /v1/bridge/bind_asset
POST /v1/bridge/claim
POST /v1/bridge/burn
GET /v1/bridge/status?assetId=...
Security Levers
- Replay protection with
depositId
/burnId
sets; strict canonical serialization for signed messages. - Per‑asset/day caps; time delays for large releases; attester set rotation with cooldowns.
- All claim txs are signed by the user’s Pivot key (OAuth only unlocks the key), preserving non‑custodial ownership.
UX Flow
- Inbound: user deposits on origin (Option A event embeds
pivotAddr
or Option B attaches EIP‑712 bind). Attesters co‑sign → user callsbridge.claim
on Pivot. - Outbound: user calls
bridge.burn
on Pivot → attesters co‑sign SAFE transfer → release on origin.
Developer Experience
- Gateway REST:
/v1/signup
,/v1/token/*
,/v1/app/*
,/v1/domain/*
,/v1/curve/*
. - SDK compiles flows → manifests; clients generated from schemas.
- Single-binary devnet for local testing.
Roadmap
- POC: single-node devnet, domain binding, DEX module, OAuth prototype.
- MVP: 3 PoA validators, hosted gateway, indexer + events, daily free-ops.
- Beta: DPoS staking, fee switch to PVT, parameter governance.
Conclusion
Pivots trims blockchain to essentials: non-custodial web-native wallets, domain-verified identity, and a handful of safe verbs. It’s enough to unlock real apps for real user- without the VM baggage.
© 2025 Pivot — pivot.money