{"rewardSnapshot":null,"merkleRoot":null,"claims":null,"id":"10aca822-5003-4a53-89b2-f15f770befcb","launchNumber":877,"kind":"evm_contracts","status":"live","chainId":4663,"sourceRepoUrl":"https://github.com/identity-md-launches/launch-877-basket","sourceCommit":"3b1fe81cab5e4d6b148399ce2af5d84ebefeacb4","parkedReason":null,"artifactCount":1,"manifestHash":"84b7eff9f5e73ed35d3baf3f9bf30278d2e215e9d47c0204be6984f789181b52","attestationHash":"3371b249dd28ce1b45ae1624f9d05faec680105995fcdd46318155892ba49723","attestation":{"treeHash":"e1bea7ee27f1292a97c5e5f9847bafa26ac149ed","verifierVersion":"0.1.0+be003835","verifierKey":"68249df1f422fa72f61ca7f0ddaf9b62043959c5c134498441d5e552a9921782","toolchain":{"solc":"0.8.26","forge":"forge Version: 1.8.3","viaIR":false,"optimizer":true,"evmVersion":"cancun","bytecodeHash":"none","optimizerRuns":200},"contracts":[{"name":"BaskMath","path":"src/BaskMath.sol","abiHash":"5ff5499febb7d544e4e1909348158dd92a5c67d231bfbd8960fdd2f087d4fc45","opcodes":{"callcode":false,"delegatecall":false,"selfdestruct":false},"metadataHash":"36a012aee99a372d62e6b87df8591b7a7351ddac18b37e521edeb0800ca5e9b5","creationCodeHash":"03f00af6a2c1e216c5142290f5a7c5a73b7dca9ff4182f298fb7a6b46fc82bef","deployedCodeHash":"324d2f77e170e519647f21af4dd0b9d0c4677a0d6fe8cd1d41c195a62780eeba","creationCodeBytes":94,"deployedCodeBytes":44},{"name":"BaskVault","path":"src/BaskVault.sol","abiHash":"a544e47473b63007f79a156bb1126ddd87d72cc1d59605b2d8ce8161780c8161","opcodes":{"callcode":false,"delegatecall":false,"selfdestruct":false},"metadataHash":"24c00872350b11f192d1aace70976736a9644fd6a364cbae463199a019029415","creationCodeHash":"541ec2ed756441069160a7524785276ff63d26f5e23f9e8c9860d9a0cff73175","deployedCodeHash":"efc36bd14ee8f31dc308dd4217f6fe245187f80f756937c82e83c7a797d92407","creationCodeBytes":21338,"deployedCodeBytes":20951}],"manifest":{"kind":"evm_contracts","notes":"Basket Protocol index vault for Stock Tokens on Robinhood Chain (chain id 4663). BaskVault is the Basket (BASK) ERC-20 share: 18 decimals, zero supply at deployment, no supply cap; deposits mint and redemptions burn. The constructor takes the explicit owner and guardian literals in that order, rejects zero or equal addresses, and makes no external calls. STOCK_FACTORY is the source constant 0x4783C67b63dE2B358Ac5951a7D41F47A38F3C046. All views are in BaskVault; BaskMath functions are internal and require no separate deployment. Assets start empty, are append-only and limited to 64. Before deposits, the owner directly lists at least three verified token/feed pairs and calls finalizeGenesis once; the opening delay is 72 hours. These are later owner operations, not launch initialization calls. Deposits require the weekday 15:30-19:30 UTC gate, three unretired feeds updated within four hours, valid banded prices no more than 26 hours old, healthy balances, and exact incoming transfers. NAV uses managed balances only; direct donations are excluded. NAV_CAP starts at USD 1,000,000 and cannot exceed USD 10,000,000,000; asset concentration, 30-day probation for later listings, and the decaying global deposit bucket also limit deposits. Deposit and redemption fees are fixed at 50 basis points, rounded up. FeeRecipient starts unset and the owner may set it once to a nonzero address other than the vault; it is never called. Until set, deposit fee shares are not minted and redemption fee shares are burned. The first deposit locks 1e15 shares at address(0xdEaD). Ownership transfers in two steps with no renounce. The owner proposes listings, feed changes, band changes, reopening, retirement, guardian replacement and NAV-cap increases; anyone may execute after seven days and before fourteen days. Listing and feed replacement share a 24-hour execution cooldown. Both roles may pause deposits, close assets and cancel proposals, except the guardian cannot cancel guardian replacement. Only the owner may unpause or immediately lower NAV_CAP. Later closes cancel earlier reopening proposals; cap reductions cancel pending raises. Redemption reads no prices and ignores deposit pauses, market gates, asset closure and retirement. Redemption availability reads have a 50,000-gas allowance; unreadable balances fall back to managed amounts. Payments use self-only calls capped at 250,000 gas, with exact outgoing balance checks; failed legs become owed claims. A claimant may choose a receiving address, and claim payments have no fixed gas cap. Anyone may flag a larger deficit and recognize the smaller of recorded and current shortfall after seven days; successful deposits clear unretired deficit records. No role can block redeem or claim, mint outside deposit, change fees, upgrade, rescue or sweep. Accepted design risks: deposit-then-redeem can profit when a feed lags more than the 1% round-trip fee; the owner must pair each Stock Token with its true feed; an untransferable asset retains its feed value until deposits are paused; a retired asset contributes zero NAV while remaining in the redemption basket.","contracts":[{"contract":"BaskVault","constructorArgs":["0x30B57ECf51D19ABcED7F6f70974e6fBb6f3b9Da3","0x5ed39AF86f2C00ad99913B5d727bD68f2A904B68"]}]},"manifestError":null},"attestationFailure":null,"deployFailure":null,"policyVersion":28,"economics":null,"poolFee":null,"requester":"0x30b57ecf51d19abced7f6f70974e6fbb6f3b9da3","admissionChecks":[{"name":"provenance","detail":"8 node(s) accepted at 3b1fe81c","status":"passed"},{"name":"findings","detail":"8 accepted submission(s), no unresolved blocking findings","status":"passed"},{"name":"independent_review","detail":"1 independent review(s)","status":"passed"},{"name":"bytecode","detail":"2 contract(s) clean and reproducible","status":"passed"},{"name":"manifest","detail":"1 application contracts; no protocol token or pool","status":"passed"},{"name":"protected_invariants","detail":"invariants-11aebc2aca1e: Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 15.10ms (14.44ms CPU time)","status":"passed"},{"name":"economics","detail":"policy explicitly selects no on-chain contributor rewards","status":"passed"}],"assurances":[],"logo":null,"seeded":null,"createdAt":"2026-10-07T06:23:13.468Z","updatedAt":"2026-10-07T06:23:32.757Z","jobs":[{"id":"9d7bffba-141b-4e33-be9c-1bfa450d9384","objective":"Basket Protocol vault: an index vault for Stock Tokens on Robinhood Chain (chain id 4663). Contracts only: no launch token, pool or website. BASK is the vault's own ERC-20 share (18 decimals). Write \"Stock Tokens\", never \"tokenized\"; no Robinhood name, logo or ticker beyond the chain's name.\nToken name: Basket\nToken symbol: BASK\nTotal supply: 0 at deployment, no cap: deposit mints, redeem burns\n\nBUILD RULES\n- Simplest code that satisfies this text: add no feature, role, setting or safeguard.\n- solc 0.8.26, optimizer on, 200 runs, evm cancun, bytecode_hash none; custom errors.\n- If BaskVault exceeds 24,000 bytes of runtime, move views into BaskLens(address vault = $contract:BaskVault); never drop a check.\n- Constructors call no other contract. Time is block.timestamp, never block.number.\n- No proxy, delegatecall, selfdestruct, rescue or sweep. User-facing state changes are nonReentrant and emit events.\n\nMANIFEST\n1. BaskVault(address owner_, address guardian_): owner_ = 0x30B57ECf51D19ABcED7F6f70974e6fBb6f3b9Da3, guardian_ = 0x5ed39AF86f2C00ad99913B5d727bD68f2A904B68, written as these literals. Reverts if either is zero or they are equal.\nSTOCK_FACTORY = 0x4783C67b63dE2B358Ac5951a7D41F47A38F3C046 is a source constant.\n\nOutside contracts (on chain 4663 only; tests mock exactly these functions under test/; no fork tests, no vm.env):\n- Stock Token: ERC-20, 18 decimals, uid() returns bytes32, oraclePaused() returns bool.\n- STOCK_FACTORY.tokenAddress(bytes32 uid) returns address.\n- Feed: Chainlink proxy: decimals() is 8, aggregator() returns address, latestRoundData(); answer = USD per whole token.\n\nASSETS: a list of (token, feed, open, retired, minAnswer, maxAnswer, listedAt), at most 64, empty at deployment, never removed. managed[token] is the accounting balance: value never uses balanceOf and tokens sent directly are ignored.\nListing checks, at proposal and again at execution: token not listed; token.decimals() == 18; STOCK_FACTORY.tokenAddress(token.uid()) == token; feed.decimals() == 8; feed.aggregator() != 0; feed not used by another asset; answer > 0. On listing open = true, minAnswer = answer / 4, maxAnswer = answer * 4.\nGenesis: until the owner calls finalizeGenesis() (once, needs 3 or more assets), proposeAsset(token, feed) and proposeAssets(tokens[], feeds[]) list at once and deposits are impossible. Deposits open 72 hours after finalizeGenesis().\nOwner proposals (genesis listing is direct): list an asset; replace an asset's feed (feed checks and new answer inside the band, both times); re-centre a band on the answer at execution, under 26 hours old; reopen an asset (cancelled by any later close); retire an asset (closed both times); replace the guardian; raise NAV_CAP. A proposal waits 7 days, then anyone may execute it; it lapses 7 days later; the owner may cancel it, as may the guardian unless it replaces the guardian. One listing or feed replacement executes per 24 hours. An asset listed after genesis is on probation for 30 days. A retired asset is closed for good, skipped by every deposit check, 0 in NAV.\n\nPRICE is valid only if the feed read succeeds, answer > 0, minAnswer <= answer <= maxAnswer, updatedAt <= now, now - updatedAt <= 26 hours, and token.oraclePaused() returns false. value(amount) = amount * answer / 1e8, rounded down (USD, 18 decimals). USD limits below are dollars times 1e18.\n\ndeposit(token, amount, receiver, minSharesOut, deadline) requires:\n- deposits open and not paused; token listed and open, vault balance >= totalOwed[token]; receiver not the vault;\n- market gate: (now / 86400 + 4) % 7 is 1 to 5 (0 = Sunday) and 55800 <= now % 86400 < 70200; and 3 or more listed assets have feed updatedAt within the last 4 hours;\n- a valid price for this token and every asset with managed > 0; no asset short or unreadable (see LOSSES).\nPull the tokens; the vault balance must rise by exactly amount. NAV = sum of value(managed) before the deposit; v = value(amount).\ngross = v if totalSupply is 0, else v * totalSupply / NAV rounded down (revert if NAV is 0). fee = gross * 50 / 10000, rounded up: minted to feeRecipient, or not minted while that is unset. The receiver gets gross - fee; on the first deposit 1e15 of that goes to address(0xdEaD) instead. The receiver's amount must be > 0 and >= minSharesOut.\nCaps after the deposit, with NAV2 = NAV + v:\n- NAV2 <= NAV_CAP (starts 1,000,000; the owner lowers it at once, cancelling pending raises, raises it by proposal, never above 10,000,000,000);\n- value(managed[token]) <= max(NAV2 * 5 / 100, 25,000), or max(NAV2 / 100, 5,000) on probation;\n- bucket <= max(NAV2 * 25 / 100, 100,000): one bucket for all deposits, which first decays (bucket -= bucket * elapsed / 86400, floor 0), then adds v.\n\nredeem(shares, minAmountsOut[], deadline) reads no price, ignores every pause and gate, and never reverts because of an asset. fee = shares * 50 / 10000 rounded up: transferred to feeRecipient, or burned with the rest while unset. net = shares - fee is burned. Per asset: available = balanceOf(vault) - totalOwed[token], floor 0 (low-level static call, 50,000 gas, copying 32 bytes; any other outcome: unreadable, available = managed); leg = min(managed, available) * net / totalSupplyBeforeBurn, rounded down; require leg >= minAmountsOut[i] (missing entry = 0); managed -= leg. Each leg is paid to msg.sender by an external function only the vault itself may call, given 250,000 gas, which reverts unless the transfer succeeds, returns nothing or true, and the vault balance falls by exactly leg. If it fails, owed[msg.sender][token] and totalOwed[token] grow by leg. claim(token, to) pays min(caller's owed, vault balance) by the same function with no gas limit.\n\nLOSSES. An asset is short when available < managed. Nothing lowers managed automatically. flagDeficit(token), by anyone, records shortfall and time if larger than recorded. recognizeLoss(token), by anyone 7 days or more later, lowers managed by min(recorded, current shortfall) and clears the record. A deposit clears unretired records.\n\nWho can call what:\n- Owner (two-step transfer, no renounce): the proposals; cancel; close an asset to deposits at once; pause and unpause deposits; lower NAV_CAP; setFeeRecipient(address) once, not zero or the vault, final. The vault never calls feeRecipient.\n- Guardian: pause deposits, close an asset, cancel proposals as stated.\n- Nobody can move assets, block redeem or claim, mint outside deposit, change a fee or upgrade.\nUpgrades and pausing: none except the deposit pause and per-asset close.\nNumbers the contracts enforce: all constants except NAV_CAP.\n\nVIEWS: all assets with feed, answer, updatedAt, band, open, retired, probation, managed, short, totalOwed; previewDeposit; previewRedeem; depositStatus(token): a reason code and the asset at fault, as in deposit's revert; pending proposals.\n\nREVIEW. Accepted design, note only, add no mechanism: (1) deposit-then-redeem profit when a feed lags more than the 1% round-trip fee; (2) the owner pairs each token with its true feed; (3) an untransferable asset keeps its feed value until deposits are paused; (4) a retired asset counts 0 in NAV. MUST ATTACK: redeem with paused, blocked or upgraded tokens (64 assets in any state: under 28,000,000 gas); any way a role blocks redeem.","state":"completed","attachedAt":"2026-10-07T06:23:13.468Z"}],"artifacts":[{"role":"other","name":"BaskVault","address":"0x518aa023c1b982a0a64b207b7d3a19bf973796e1","creationCodeHash":"541ec2ed756441069160a7524785276ff63d26f5e23f9e8c9860d9a0cff73175","txHash":"0xfa90aa2b987ccb79374dbe1d07281be3377e8ad953de5183dceceeb759b8e90e","blockNumber":82259501,"verifiedAt":null,"verifyFailure":null}],"allocations":[]}