Everweek

Docs

Everweek buys Stock Tokens on Robinhood Chain on a schedule: one USDG deposit, then a buy every hour, day, week or month until it is spent. One router contract trades USDG and the 27 listed Stock Tokens through their Uniswap pools, and refuses any fill that lands too far from the Chainlink price of the stock. Next to recurring buys it runs market swaps, limit orders with brackets, stock to stock trades in one transaction and EIP-2612 permits instead of approvals.

Overview

Every Stock Token on Robinhood Chain has two prices: the price its Uniswap pool will pay right now, and the price Chainlink reports from the stock market. Most of the time they agree. When a pool is thin, has not been arbitraged since the last move, or is being sandwiched, they do not, and a normal swap fills at the pool's price anyway.

Everweek reads Chainlink inside the contract and turns it into a hard minimum for every leg of every trade. You keep the pool's liquidity and the pool's price when it is fair; you get a revert when it is not.

Recurring buys

A plan holds USDG in the contract and spends it on one Stock Token in equal slices, one slice per period.

Creating. createPlan(token, total, perBuy, every) moves total USDG into the contract. perBuy is the size of each buy, at least $2; every is the time between buys in seconds, at least one hour. The first buy is due at once. createPlanWithPermit does the same with a USDG permit signature instead of an approval.

Running. runPlan(id) may be called by anyone once the plan is due. It spends one slice: $0.05 goes to the caller for gas, 0.1% to the treasury, and the rest buys the stock on its pool with a minimum out of 1.5% under Chainlink. The stock goes straight to the owner's wallet, never stays in the contract. The next buy is due every seconds later. If the pool is too far from Chainlink, the call reverts and the plan keeps waiting for the next check.

The last slice. When what is left is smaller than two slices, the last buy takes all of it, so no dust is stranded. When nothing is left, the plan closes by itself.

Stopping. closePlan(id), from the owner only, closes the plan and sends every unspent USDG back at once. No fee, no waiting.

Reading. getPlan(id) returns the owner, the next due time, the period, whether it is open, the token, the slice and what is left. plansCount() and duePlans(from, count) list them for keepers.

Example. $500 into NVDA, $50 every week: ten buys over about nine weeks. If NVDA is $201 in week one and $188 in week two, the second buy gets more shares. That is the point of buying on a schedule: you do not have to guess the dip.

A market swap, step by step

Calling swap(tokenIn, tokenOut, amountIn, minOut, slipBps, to):

If any check fails, the whole transaction reverts. The router never keeps a balance between trades.

The Chainlink floor

For each pool leg the router computes the amount Chainlink says you should get, then takes off your band. Buying NVDA with 1,000 USDG at a Chainlink price of $217.07 and a 0.5% band:

The same check runs on sells (minimum USDG out from the Chainlink value of what you sell) and on each leg of a stock to stock trade. quote(tokenIn, tokenOut, amountIn, slipBps) returns the fair amount and the floor, so you can see both before you sign.

Choosing a band

The band is how far from Chainlink you accept a fill. You pick it per trade: 0.3%, 0.5%, 1% or 1.5%. It can never be looser than the router's cap, 1.5% at launch.

The pool fee is part of what the pool delivers, so a 1% fee pool cannot fill inside a 0.3% band. The app shows the live gap between each pool and Chainlink, which is the quickest way to pick.

Stock to stock

Rotating from TSLA to NVDA on a usual swap page takes two swaps through USDG and two approvals. Everweek does it in one call: the TSLA leg is sold with a Chainlink floor, 0.1% is taken from the USDG in the middle, and the NVDA leg is bought with its own floor. The floor returned by quote counts the band twice, once per leg.

Permit instead of approve

USDG and the Stock Tokens implement EIP-2612. swapWithPermit and placeOrderWithPermit take the allowance as a signature for exactly the amount of the trade, so nothing stays approved after it.

Orders and brackets

placeOrder(token, buy, amount, limit, stop, expiry) creates an order on one Stock Token with up to two triggers. Either price may be 0, not both:

The details of each side:

The fill. fill(id) checks Chainlink has reached the limit, then trades on the pool with the usual Chainlink floor and one more check: the price you actually get must be no worse than your limit. A buy of 500 USDG with a $195 limit must deliver at least (500 − fees) / 195 NVDA; a sell must deliver at least the amount times $195. If the pool cannot meet that yet, the fill reverts and the order keeps waiting.

Cancel and expiry. cancel(id) returns everything in the order to you, at any time, from the owner of the order only. Once an order passes its expiry, any fill call closes it and returns the funds instead of trading.

due(from, count) lists the open orders that can be filled or closed now. getOrder(id) and ordersCount() read the book.

The keeper

A Cloudflare worker checks every few minutes. It calls runPlan on every due plan and fill on every due limit order. It earns $0.05 per fill from the order, which pays its gas; it refuels its own ETH from that USDG. Anyone else may call fill too and earn the same fee, so orders do not depend on Everweek's keeper staying up.

Fees

Market swap0.1% of the USDG side, plus the pool fee and gas
Stock to stock0.1% once, on the USDG in the middle, plus both pool fees
Limit order0.1% of the USDG side plus $0.05 to whoever fills it
Cancel, expiryfree (gas only for a cancel)
Hard capsthe fee can never exceed 0.5%, the fill fee $0.50

Example: buying $1,000 of NVDA costs $1 to Everweek and about $0.50 to the 0.05% pool. A $500 limit buy costs $0.50 plus $0.05.

Pools and routes

Each Stock Token trades through its deepest Uniswap pool against USDG. COIN, MSTR and SPY route through WETH, because that is where their liquidity sits; each of their legs is still checked against Chainlink as a whole.

AAPLUSDG / AAPL, 0.05% pool
NVDAUSDG / NVDA, 0.05% pool
TSLAUSDG / TSLA, 0.3% pool
MSFTUSDG / MSFT, 0.3% pool
AMZNUSDG / AMZN, 0.3% pool
METAUSDG / META, 0.3% pool
GOOGLUSDG / GOOGL, 0.05% pool
COINUSDG / WETH 0.01%, then WETH / COIN 0.3%
AMDUSDG / AMD, 0.3% pool
TSMUSDG / TSM, 1% pool
MUUSDG / MU, 0.3% pool
INTCUSDG / INTC, 0.3% pool
PLTRUSDG / PLTR, 0.3% pool
DELLUSDG / DELL, 1% pool
SNDKUSDG / SNDK, 1% pool
MSTRUSDG / WETH 0.01%, then WETH / MSTR 1%
CRCLUSDG / CRCL, 0.3% pool
BABAUSDG / BABA, 0.3% pool
GMEUSDG / GME, 1% pool
SPCXUSDG / SPCX, 0.05% pool
USARUSDG / USAR, 0.3% pool
SPYUSDG / WETH 0.01%, then WETH / SPY 0.05%
QQQUSDG / QQQ, 0.05% pool
GLDUSDG / GLD, 0.3% pool
SLVUSDG / SLV, 0.3% pool
USOUSDG / USO, 0.3% pool
SGOVUSDG / SGOV, 0.3% pool

Market hours and weekends

Chainlink stock feeds update while the market is open and pause between sessions. The router accepts a Chainlink answer up to 3.5 days old, so it keeps working over weekends using the last close. Pools keep trading 24/7, so a pool that runs away from Friday's close is refused until Chainlink catches up on Monday. Limit orders likewise fill on Chainlink, not on weekend pool moves.

The app

For bots and integrators

Everything the app does is plain contract calls. A buy with viem:

const [fair, floor] = await client.readContract({ address: ROUTER, abi, functionName: "quote", args: [USDG, NVDA, 1_000_000000n, 50] });
await wallet.writeContract({ address: ROUTER, abi, functionName: "swap", args: [USDG, NVDA, 1_000_000000n, floor, 50, me] });

// sell 2.5 NVDA: target $230, stop $205, valid for 7 days
await wallet.writeContract({ address: ROUTER, abi, functionName: "placeOrder", args: [NVDA, false, 2_500000000000000000n, 23000000000n, 20500000000n, now + 7n * 86400n] });
// recurring buys: $500 into NVDA, $50 every week
await wallet.writeContract({ address: ROUTER, abi, functionName: "createPlan", args: [NVDA, 500_000000n, 50_000000n, 604800] });

The site serves /api/prices (Chainlink and 24h change), /api/pegs (pool price, address, liquidity and volume per stock) and /api/orders?a=0x… (the open book and one trader's orders) and /api/plans?a=0x… (one wallet's recurring plans).

Events

Owner limits

The owner of the router can list Stock Tokens and set their routes, change the price adapter, set the band cap (up to 5%), the fee (up to 0.5%), the fill fee (up to $0.50) and the treasury. There is no function that moves a trader's tokens or an order's funds anywhere except through a trade that passes the checks, or back to the trader.

Risks

FAQ

Does Everweek have its own liquidity? No. It routes through the existing Uniswap pools and adds the checks.

Why did my swap revert? The pool was outside your band of Chainlink, or the total was under minOut. Try a wider band, a smaller size, or wait for the pool to come back in line.

Can a limit order fill at a worse price? No. The contract checks the fill against your limit and reverts otherwise.

What happens to my order if the keeper stops? Nothing is lost. Anyone can fill it, and you can cancel at any time.

Token

The Everweek token launches on pons. Its contract address appears on the home page and here once it is live. Always check the address on this site before trading.

Contracts

Everweek routerOpening soon
TokenLaunching soon on pons
Chainlink adapter0xe9bBcd46F9B0Df04B418e0207876984F9f8336cb
USDG0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168
Uniswap SwapRouter020xcaf681a66d020601342297493863e78c959e5cb2
Uniswap QuoterV20x33e885eD0Ec9bF04EcfB19341582aADCb4c8A9E7