Abstract: The Junk World Assets (JUNK) Protocol is an on-chain position escrow and randomized acquisition system deployed on Ethereum mainnet, with launch preparation ongoing. Depositors lock ERC-721 NFTs or ERC-20 token amounts into a shared escrow vault backed by committed ETH. Position weights are inversely proportional to backing, producing an integer approximation of harmonic-mean pool pricing. Chainlink VRF V2.5 makes the draw result unpredictable before fulfillment, reducing selection manipulation but not eliminating every form of MEV. Configurable acquisition and settlement paths can buy and burn $JUNK. On taxable Uniswap V2 buys and sells, the token charges 1%; 90% of that fee is sent to the dead address and 10% is retained for eventual treasury conversion. This document describes the implemented contract behavior, the deployed configuration, and its operational limits.
The Junk World Assets consists of four primary smart contract modules designed with strict single-responsibility principles, isolated storage domains, and gas-optimized Solady primitives:
+-----------------------------------------------------------------------------------+
| JUNK PROTOCOL |
+-----------------------------------------------------------------------------------+
| |
| +-----------------------+ +------------------------------+ |
| | JUNK.sol | <=== Calls ======> | JUNKRewards.sol | |
| | Core Escrow Vault & | | Emissions, Fee Splitting & | |
| | Binary Sum-Tree Engine | | Uniswap V2 Buyback Router | |
| +-----------------------+ +------------------------------+ |
| || || |
| Triggers VRF Interacts With |
| \/ \/ |
| +-----------------------+ +------------------------------+ |
| | JUNKVRFService.sol | | JunkWorldAssets.sol | |
| | Native VRF Sub & | | $JUNK ERC-20 Token with | |
| | Relayer Compensation | | 1% Tax: 90% Burn / 10% Retained | |
| +-----------------------+ +------------------------------+ |
| || || |
| Requests Randomness Sends Buy/Sell |
| \/ \/ |
| +-----------------------+ +------------------------------+ |
| | Chainlink VRF V2.5 | | Uniswap V2 Router & Pair | |
| +-----------------------+ +------------------------------+ |
| |
+-----------------------------------------------------------------------------------+
| Contract | Core Responsibility | Key Dependencies | Solady Utilities Used |
|---|---|---|---|
JUNK.sol |
Asset escrow, binary sum-tree selection, VRF settlement dispatch, listing lifecycle, standing bid settlement | JUNKRewards, JUNKVRFService, VRFCoordinatorV2Plus |
ERC721, ERC20, Ownable, ReentrancyGuard, SafeTransferLib |
JunkWorldAssets.sol |
Protocol incentive token ($JUNK, 1B initial supply), 1% V2 buy/sell tax, 90% fee-share burn, 10% fee-share treasury retention, visible dead-address burn function | IUniswapV2Router02, IUniswapV2Pair |
ERC20, Ownable, ReentrancyGuard |
JUNKRewards.sol |
Seven-day fixed-rate emissions, dynamic acquisition allocation, user allowance tracking, V2 token swaps | JunkWorldAssets, IUniswapV2Router02 |
Ownable, ReentrancyGuard, SafeTransferLib, FixedPointMathLib |
JUNKVRFService.sol |
Purchaser VRF fee escrow, native Chainlink subscription top-up, relayer gas reimbursement | IVRFCoordinatorV2Plus, JUNK |
Ownable, ReentrancyGuard, SafeTransferLib, FixedPointMathLib |
Core deployed; launch preparation in progress. As of September 20, 2026, the four Uniswap V2 JUNK contracts are deployed on Ethereum mainnet and exact-verified on Etherscan. The fresh Chainlink VRF subscription is configured with both consumers and funded with 0.155 ETH. Trading and acquisitions remain disabled.
0xa88fc01053f0c28dfadafb05c4705fa7c2ed79540xcb4ef27f26808c23e94592b2da642f5ead56052d0x2c0bac7c9e1caa3401fbe4377b1d8d0028e2ee350xa4acf991777099804631b274b76639ca081c23a8The core deployment transferred 350,000,000 $JUNK to rewards (175,000,000 each for depositors and purchasers) and 650,000,000 $JUNK to the protocol recipient. Fee-vault deployment is reserved for manual execution; liquidity and protocol launch are separate pending steps.
The Junk World Assets operates a permissionless floor vault for compatible contracts. Depositors lock an asset—either an ERC-721 NFT or an ERC-20 token amount—accompanied by an ETH deposit known as Backing ($V_i$). Listings must pass the contract's collection checks, transfer successfully, and meet the minimum backing (0.01 ETH by default).
$$\text{Minimum Backing Requirement: } V_i \ge V_{\min} = 0.01 \text{ ETH}$$
When depositing, the committed ETH backing stays in contract escrow and funds the settlement alternatives available after selection. It is not an unconditional depositor right to reclaim the position at any time: the purchaser controls the settlement choice during the 24-hour window, after which the depositor has two reclaim paths with different payouts.
To align economic incentives and ensure low-backed positions carry a proportional chance of being drawn while high-backed positions act as high-value anchors, selection probability is inversely proportional to position backing $V_i$.
For a listing $i$ with ETH backing $V_i$, its integer selection weight $W_i$ is computed as:
$$W_i = \left\lfloor \frac{10^{36}}{V_i} \right\rfloor$$
The acquisition price for any pool pull is the contract's current integer-weighted EV of active positions plus the owner-configured surcharge (10% by default).
The total pool selection weight $W_{\text{total}}$ and weighted backing total $V_{\text{weighted}}$ are defined as:
$$W_{\text{total}} = \sum_{i=1}^{N} W_i$$
$$V_{\text{weighted}} = \sum_{i=1}^{N} (W_i \cdot V_i)$$
The Pool Expected Value ($\text{EV}$) represents the expected backing of a randomly drawn position:
$$\text{EV} = \frac{V_{\text{weighted}}}{W_{\text{total}}} = \frac{\sum_{i=1}^{N} (W_i \cdot V_i)}{\sum_{i=1}^{N} W_i}$$
In an idealized real-number model, substituting $W_i = \frac{\Xi}{V_i}$ (where $\Xi = 10^{36}$) gives:
$$\text{EV} = \frac{\sum_{i=1}^{N} \left( \frac{\Xi}{V_i} \cdot V_i \right)}{\sum_{i=1}^{N} \frac{\Xi}{V_i}} = \frac{N \cdot \Xi}{\Xi \sum_{i=1}^{N} \frac{1}{V_i}} = \frac{N}{\sum_{i=1}^{N} \frac{1}{V_i}} = H(V_1, V_2, \dots, V_N)$$
This is the harmonic mean in the idealized model. The deployed code uses $W_i = \left\lfloor \Xi/V_i \right\rfloor$ and integer division for weightedBackingTotal / totalWeight, so the live EV is a truncated, integer-weighted approximation rather than an exact harmonic mean.
The gross ETH required from a purchaser to trigger an acquisition pull is, at the default 10% surcharge:
$$P_{\text{acq}} = \text{EV} \cdot \left( 1 + \frac{\gamma_{\text{surcharge}}}{10000} \right) = \text{EV} \cdot 1.10$$
where $\gamma_{\text{surcharge}} = 1000$ bps ($10\%$).
To maintain scalable on-chain selection without iterating over arrays, JUNK.sol implements a 32-depth static Binary Sum-Tree structure.
Node 1: Total Weight [W1 + W2 + W3 + W4]
/ \
/ \
Node 2: Left Sum [W1 + W2] Node 3: Right Sum [W3 + W4]
/ \ / \
Node 4 [W1] Node 5 [W2] Node 6 [W3] Node 7 [W4]
node = 1.tree[left_child].node = left_child).node = left_child + 1).node >= CAPACITY).To make the draw result unavailable at request time, acquisition settlement is split into request and fulfillment/processing phases. VRF does not by itself eliminate all front-running, block reorganization, or validator/MEV risks:
[ Purchaser ] --( 1. acquire() )--> [ JUNK Core Vault ] --( Request VRF )--> [ Chainlink VRF V2.5 ]
| |
(Escrows Fee) (Emits Random Word)
| |
[ Relayer / User ] --( 2. processAcquisitions() )<------------------------------------+
|
+--> [ Binary Tree Selection ] ---> [ Allocates Listing to Purchaser ]
acquireWithSlippage):
Pending.processAcquisitions):
rawFulfillRandomWords, caching the random word and marking status as Ready.JUNK.processAcquisitions(maxCount). The optional JUNKVRFService wrapper is restricted to configured operators and can reimburse processing gas within its caps.Allocated, sets allocatedAt = block.timestamp, and triggers surcharge fee distribution.JUNKVRFService.sol provides an optional operator-gated processing wrapper and VRF subscription funding path; it does not guarantee seamless settlement or remove the need for a separate processing transaction.
$$P_{\text{vrf}} = \text{serviceGasEstimate} \cdot P_{\text{gas}} \cdot \left(1 + \frac{\text{serviceMarginBps}}{10000}\right) + \text{flatWei}$$
(Defaults: $\text{gasEstimate} = 800,000$, $\text{margin} = 30\%$).JUNKVRFService checks the Chainlink VRF subscription native ETH balance during request preparation and operator/top-up calls. If the balance falls below the required threshold:
$$\text{Required Balance} = \text{buffer} + (N_{\text{unfulfilled}} + N_{\text{new}}) \cdot \text{maxFulfillmentCost}$$
The service contract calls fundSubscriptionWithNative as part of those calls, subject to its available balance.
Configured operators calling the service wrapper may receive capped gas reimbursement from JUNKVRFService:
$$\text{Reimbursement} = \min \left( \text{GasUsed} \cdot \min(P_{\text{gas}}, P_{\text{cap}}), \text{maxReimbursementWei} \right)$$
acquisitionRefundCredit for later withdrawal.selectionTimeoutBlocks (default 30 blocks), the request transitions to Expired and full refunds are unlocked.When a position $i$ with backing $V_i$ is allocated to a purchaser, the purchaser may act during the default 24-hour Settlement Window (settlementWindow = 86400s). The owner can configure this window subject to the contract's bounds. The purchaser has three mutually exclusive resolution choices:
+-----------------------------------+
| Allocated Position (Backing V) |
+-----------------------------------+
|
+---------------------------------+---------------------------------+
| | |
v v v
[ 1. Keep Asset ] [ 2. Accept ETH Bid ] [ 3. Accept $JUNK Bid ]
- Takes NFT/Token Bag - Receives 0.85 * V (ETH) - Swaps 0.85 * V for $JUNK
- Depositor gets 0.99 * V - 0.15 * V buys/burns JUNK - 0.15 * V buys/burns JUNK
- 0.01 * V team fee - Depositor recovers asset - Depositor recovers asset
keepNFT)acceptDepositorBid)$$\text{Payout}_{\text{ETH}} = V_i \cdot 0.85$$
JUNKRewards.buyFor and, when the configured swap succeeds, the resulting $JUNK$ is sent to DEAD_ADDRESS (0x...dEaD). Swap failure is caught by the core contract, so this is an attempted burn path rather than an unconditional guarantee.acceptBidAsTokens)JUNKRewards.buyFor.If the purchaser takes no action within 24 hours, the settlement lock expires:
depositorReclaimBacking (recovers backing minus 1% protocol fee; NFT delivered to purchaser).depositorReclaimNFT (pays purchaser 85% payout; recovers NFT; 15% discount burned).The 15% settlement discount is an implemented burn path when the rewards module, router, and liquidity are configured and the buy succeeds. The core then calls IJunkWorldAssets.burn(), which transfers the purchased tokens to the visible dead address. This reduces circulating availability; it does not reduce the ERC-20 totalSupply value because the token's burn function is a dead-address transfer.
$$\text{ETH Swapped & Burned} = V_i \cdot 0.15$$
$$\text{Tokens Burned} = \text{UniswapV2\_Swap}\left( V_i \cdot 0.15 \text{ ETH} \longrightarrow \$JUNK \right) \longrightarrow \text{DEAD\_ADDRESS}$$
The protocol derives a purchaser allocation from the 10% acquisition surcharge ($\text{Surcharge} = P_{\text{acq}} - \text{EV}$) based on transaction velocity. The allocation is stored as an ETH-denominated allowance and is converted to $JUNK$ only when the purchaser claims it through the rewards module.
Let $\Delta t = t_{\text{curr}} - t_{\text{last\_acq}}$ be the time gap since the last acquisition pull.
$$\text{Purchaser Share Bps } \sigma(\Delta t) = \begin{cases} 0 & \text{if } \Delta t \le \text{hotGap } (60\text{s}) \\ 10000 & \text{if } \Delta t \ge \text{coldGap } (3600\text{s}) \\ 10000 \cdot \frac{\Delta t - 60}{3600 - 60} & \text{otherwise} \end{cases}$$
Purchaser Allowance Share %
100% | +--------------------- (Cold: >= 3600s)
| /
| /
| /
0% +----------------------------------+ (Hot: <= 60s)
+------------------------------------------------------------> Time Gap (seconds)
For an escrowed fee $F$, the contract computes the EV component $E = F \cdot 10000/(10000+\text{surchargeBps})$ and purchaser slice $S = (F-E)\cdot\sigma(\Delta t)$. It then applies the following percentages to the remaining amount $F-S$, not only to the surcharge:
accFeePerEV, or accrued to the protocol if there are no fee-share listings.Consequently, the current implementation is not a simple 1%/2%/7% split of the surcharge alone; the exact amounts depend on the purchaser share and the remaining fee base.
The current implementation has three protocol-generated dead-address burn paths, plus a retained treasury share of the token trade tax:
+-----------------------------------------------------------------------------------+
| $JUNK BURN PATHS & TREASURY RETENTION |
+-----------------------------------------------------------------------------------+
| |
| [ Burn path 1: Acquisition fee cut ] |
| 2% of the post-purchaser-allocation fee base is swapped and burned when possible. |
| |
| [ Burn path 2: Settlement discount ] |
| 15% of position backing is swapped and burned when the configured buy succeeds. |
| |
| [ Burn path 3: Token trade tax ] |
| Taxable V2 buys/sells pay 1%; 90% of that fee is sent to the dead address. |
| |
| [ Treasury retention ] |
| 10% of each 1% trade fee is retained and later swapped to ETH for treasury. |
| |
+-----------------------------------------------------------------------------------+
The trade-tax split is therefore equivalent to 0.90% of a taxable trade being burned and 0.10% being retained for treasury, subject to integer rounding. Fee-excluded addresses do not pay this tax. The public burn(amount) function also permits direct dead-address burns outside these three protocol-generated categories.
JunkWorldAssets.totalBurned() returns the token balance held at 0x000000000000000000000000000000000000dEaD. It includes acquisition burns, settlement-discount burns, the burned 90% share of token trade taxes, direct calls to burn(), and tokens transferred directly to the dead address. Because burning is implemented as a transfer to the dead address, the nominal ERC-20 totalSupply remains unchanged.
$JUNK$JUNK, minted once to the protocol address; no public mint function.0x000000000000000000000000000000000000dEaDJUNKRewards—175,000,000 for depositors and 175,000,000 for purchasers—and transferred the remaining 650,000,000 $JUNK (65%) to the protocol recipient for liquidity and custody. This split is a deployment action, not a permanent allocation rule enforced by JunkWorldAssets.sol.+-----------------------------------------------------------------------------------+
| $JUNK INITIAL ALLOCATION |
+-----------------------------------------------------------------------------------+
| |
| [=========================================== 65% ============================] |
| Protocol Recipient for Liquidity & Custody (mainnet deployment) |
| |
| [====================== 35% ======================] |
| 7-Day Rewards: 17.5% Depositors + 17.5% Purchasers (mainnet deployment) |
| |
+-----------------------------------------------------------------------------------+
JUNKRewards.sol executes a configured seven-day fixed-rate emission program once the JUNK owner enables acquisitions and the rewards module starts emission. The mainnet deployment is configured for 175,000,000 $JUNK in depositor emissions and 175,000,000 $JUNK in purchaser emissions. As of the deployment snapshot above, emission has not started.
$$\text{Emission Duration: } T_{\text{emission}} = 7 \text{ days} = 604,800 \text{ seconds}$$
Emissions are split into two parallel incentive pools:
Depositor emissions stream continuously based on the square root of position backing ($\sqrt{V_i}$):
$$\text{Rate per second: } R_{\text{dep}} = \frac{\text{DepositorTotal}}{604,800}$$
$$\text{Accrual Accumulator: } \text{accTokenPerSqrt} \leftarrow \text{accTokenPerSqrt} + \frac{R_{\text{dep}} \cdot \Delta t \cdot 10^{36}}{\sum \sqrt{V_i}}$$
$$\text{Depositor } i \text{ Pending Tokens} = \sqrt{V_i} \cdot \text{accTokenPerSqrt} - \text{tokenDebt}_i$$
The contract distributes the configured depositor rate pro-rata by $\sqrt{V_i}$; this is an allocation rule, not a guarantee against manipulation or economic loss. Rewards are claimable through the rewards contract rather than automatically transferred to a wallet.
Purchaser emissions are partitioned into 7 daily epochs ($1 \text{ epoch} = 86,400\text{s}$):
$$\text{Daily Pot} = \frac{\text{PurchaserTotal}}{7}$$
At epoch close, purchasers claim tokens pro-rata based on their acquisition pull count:
$$\text{Purchaser Reward} = \text{DailyPot} \cdot \frac{N_{\text{user\_acquisitions}}}{N_{\text{total\_epoch\_acquisitions}}}$$
A primary vulnerability in traditional NFT escrow contracts is "griefing via revert" (e.g., a malicious recipient contract rejecting NFT transfers in onERC721Received).
JUNK.sol implements a Best-Effort Delivery Strategy (_deliverAsset):
try ERC721(collection).transferFrom(address(this), recipient, amountOrId) {
// Delivery succeeded cleanly
} catch {
stuckNFTRecipient[listingId] = recipient;
emit NFTDeliveryFailed(listingId, recipient, collection, amountOrId);
}
If an asset transfer fails due to pausable collections, blacklisting, or fallback reverts:
stuckNFTRecipient[listingId] = recipient.recoverStuckNFT(listingId).JUNK.sol features a staging queue, but the source does not encode a 24-hour pre-launch timer:
acquisitionsEnabled starts emissions but does not itself drain the queue.ReentrancyGuard where applicable (nonReentrant).acquisitionRefundCredit, feeCredit), eliminating block denial-of-service risks.JUNK.sol Core Interfaceinterface IJUNK {
// --- Listing & Management ---
function listNFT(address collection, uint256 tokenId) external payable returns (uint256 listingId);
function listTokenBag(address tokenAddress, uint256 tokenAmount) external payable returns (uint256 listingId);
function withdrawListing(uint256 listingId) external;
function updateBacking(uint256 listingId, uint256 newBacking) external payable;
// --- Acquisition ---
function acquisitionFee() external view returns (uint256);
function acquire(uint256 maxAcquisitionFee, uint256 minWeightedValue) external payable returns (uint256 requestId);
function acquireWithSlippage(uint256 maxAcquisitionFee, uint256 minWeightedValue, uint256 maxNegativeSlippageBps) external payable returns (uint256 requestId);
function acquireBatch(uint256 count, uint256 maxAcquisitionFee, uint256 minWeightedValue) external payable returns (uint256[] memory requestIds);
function processAcquisitions(uint256 maxCount) external returns (uint256 processedCount);
// --- Settlement Choices ---
function keepNFT(uint256 listingId) external;
function acceptDepositorBid(uint256 listingId) external;
function acceptBidAsTokens(uint256 listingId, uint256 minTokensOut) external;
function relistNFT(uint256 listingId) external payable returns (uint256 newListingId);
function depositorReclaimBacking(uint256 listingId) external;
function depositorReclaimNFT(uint256 listingId) external;
// --- Earnings & Fail-Safe ---
function claimListingFees(uint256[] calldata listingIds) external returns (uint256 total);
function withdrawEarnings() external returns (uint256 total);
function withdrawAcquisitionRefund() external returns (uint256 amount);
function recoverStuckNFT(uint256 listingId) external;
}
JunkWorldAssets.sol Core Interfaceinterface IJunkWorldAssets {
function burn(uint256 amount) external;
function totalBurned() external view returns (uint256);
function StartTrading(address pair) external;
function setTreasury(address newTreasury) external;
function setSwapThresholdEth(uint256 newThreshold) external;
}
JUNKRewards.sol Core Interfaceinterface IJUNKRewards {
function tokenShareBps(uint256 gap) external view returns (uint256);
function claimAccruedTokens(uint256 minOut) external returns (uint256 tokenOut);
function claimDepositorTokens(uint256[] calldata listingIds) external returns (uint256 total);
function claimEpochTokens(uint256[] calldata epochs) external returns (uint256 total);
function buyFor(address recipient, uint256 minOut) external payable returns (uint256 tokenOut);
}
The Junk World Assets (JUNK) Protocol provides a configurable framework for randomized position acquisition and yield distribution. It combines inverse-backing selection weights, an integer approximation of harmonic-mean pricing, Chainlink VRF V2.5 draw fulfillment, acquisition and settlement buy-and-burn paths, and a token trade tax whose fee is split 90% to the dead address and 10% to treasury retention. The resulting behavior depends on activation state, configuration, liquidity, and successful external swaps; these are not unconditional guarantees.
End of Technical Whitepaper.