How Locksley works
Locksley is a savings and loan rebuilt as three smart contracts on Robinhood Chain: a treasury-backed savings vault, escrowed standing orders, and stock-collateralised loans. No contract has an owner, a pause switch, a fee, or an upgrade path. This is the technical reference for what they do and, just as importantly, what they cannot.
A bank with no banker
A bank does three things with your money: holds it and pays you something for the privilege, moves it on your instruction, and lends against what you own. Locksley does the same three, but every one of them is a contract you can read, and the only key that moves your balance is yours. There is no institution in the middle - not even us.
- Savings - your USDG buys SGOV, a token of short-dated U.S. treasury bills. It earns what the bills earn, in the vault, under your name.
- Standing orders - escrow USDG once and it pays out on a schedule. Rent, a salary, an allowance. Cancel any time and the remainder comes back.
- Collateral loans - post a tokenised stock, borrow USDG against up to half its value, never sell it. Lenders supply the reserve and earn the interest.
Everything on this page is enforced by the contracts, not the app. The interface is a window onto state anyone can read or write directly with a wallet.
Banking that cannot betray you
Vision
Most financial failure is not fraud. It is an institution doing something it was allowed to do: freezing a withdrawal, changing a rate, raising a fee, halting a product, being bought and shut down. The remedy is not a better institution. It is removing the seat the institution sits in. Locksley's vision is ordinary banking - save, pay, borrow - where that seat is empty by construction.
Mission
- Non-custody as a hard property. No address in any Locksley contract can move a balance that is not its own. This is verified in the source, not promised in a policy.
- Real yield only. The savings rate is whatever U.S. treasury bills pay. Locksley invents no rate, subsidises nothing, and prints nothing.
- Honest limits. Where a mechanism has a weakness - spot pricing, a locked term, liquidation - it is documented here, not hidden behind marketing.
- Immutable. What is deployed is final. A bug is permanent and so is every guarantee. We chose that trade deliberately.
Three contracts, zero shared state
The contracts do not know about each other. Each holds only the funds its own users deposited, tracks them per address, and talks to exactly one external system - a Uniswap v3 pool - to price or swap. There is no router, no registry, no shared treasury, and no proxy in front of any of them. If one were to fail, the other two would not notice.
Three contracts, no shared vault, no owner. Each holds only what its own users put in.
Savings backed by treasuries
deposit(usdgIn, minSgovOut) swaps your USDG for SGOV through the USDG/SGOV Uniswap v3 pool and credits shares[you]with the SGOV received. The vault is a share ledger; the SGOV itself sits in the contract. withdraw(sgovShares, minUsdgOut) reverses it. Both take a minimum-output floor you set, so a moved price reverts rather than fills badly.
Yield is not paid by Locksley. SGOV appreciates against USDG as the bills it holds accrue; the vault just holds your share of it.
Where the yield comes from
SGOV is a token of an ETF that holds 0-3 month U.S. treasury bills. As those bills accrue, SGOV's price against USDG rises. Your share count never changes; the USDG value of each share does. Locksley pays nothing, takes nothing, and cannot change the rate - the rate is the bill.
Locked deposits
depositLocked(usdgIn, minSgovOut, term) works identically but records unlockAt = now + term and keeps the shares in a separate lockedShares balance.withdrawLocked reverts until that timestamp. The term is capped at MAX_TERM = 730 days. A lock earns exactly what an open deposit earns - it is a commitment device, not a bonus.
value = (shares + lockedShares) × sgovPrice
# sgovPrice read from pool sqrtPriceX96, 6-decimal USDG per 18-decimal SGOV
Standing orders
create(token, recipient, amount, interval, payments, startDelay, expiry)pulls amount × payments into escrow and records the schedule. From then on, execute(id) pays one instalment to the recipient if nextDue has passed - and anyone may call it. The recipient can, a bot can, you can. The order does not depend on Locksley being online, because Locksley has no server in the loop.
- Cancel - only the owner. Every unpaid instalment returns immediately.
- Expiry - optional. Past it, execute reverts and cancellation is the only exit.
- Nothing is skipped - if nobody calls execute for two intervals, the next call pays one instalment and advances the clock by one interval. Missed periods queue; they do not vanish.
Because execution is permissionless, a recipient who wants their money on time has every incentive to trigger it themselves. The schedule is a right they hold, not a favour they wait for.
Loans against stock
Two sides share one contract. Lenders call supply(usdg)and receive reserve shares; redeem returns their USDG plus their portion of accrued interest. Borrowers call depositCollateral(token, fee, amount) with a tokenised stock that has a USDG pool, then borrow(usdg) up to MAX_LTV_BPS = 50% of the collateral's value.
How collateral is priced
_value() reads sqrtPriceX96from the stock's own Uniswap v3 pool at call time and converts it to USDG per share. This is the spot price, not a time-weighted average. It is honest about what the market says right now and it is the mechanism's biggest weakness - seeRisks.
Interest
Debt accrues per second at RATE_PER_SEC, about 8% a year, compounded through a global index so the contract never loops over borrowers. Everything a borrower pays in interest goes to the reserve, which is to say to the lenders. There is no spread and no treasury cut.
Borrowing stops at 50%. Between 50% and 60% you cannot borrow more but cannot be liquidated either. Past 60%, anyone may repay half your debt and take collateral at an 8% discount.
Liquidation, by anyone
A position is liquidatable once debt exceeds LIQ_THRESHOLD_BPS = 60%of collateral value. Anyone may then call liquidate(user, repayAmount): they repay up to CLOSE_FACTOR_BPS = 50% of the debt in USDG and receive collateral worth that amount plus an 8% bonus. The bonus is what makes it worth someone's gas to keep the reserve solvent; the close factor stops a single call from emptying a position that could have recovered.
seized = r × (1 + 0.08) / p
# the borrower keeps everything else and still owes the rest
The 10-point gap between the borrow cap and the liquidation line is deliberate. A borrower at exactly 50% is not one bad tick from liquidation - the stock must fall roughly 17% first.
Who can move what
The clearest way to state the custody model is as a permission table. Three actors exist: you, everyone else, and Locksley. The last column is empty on purpose.
The third column is the product. There is no address in any contract with more power than yours.
Concretely: no function in any of the three contracts is gated by an owner, admin, guardian or multisig role. There is no Ownable, no Pausable, no upgradeable proxy, no fee recipient variable. The deployer's key was used once, to deploy, and has no standing afterwards. You can confirm this by reading the source on Blockscout - it is short.
What the cryptography actually guarantees
Locksley adds no cryptography of its own. It rests entirely on the primitives of the chain, and it is worth being precise about which ones do what.
Authorisation: ECDSA over secp256k1
Every state change is a transaction signed by an Ethereum account. The contract checks msg.sender - the address recovered from that signature - against the ledger it keeps. Only the address that deposited can withdraw; only the order's owner can cancel; only the borrower can pull their collateral. Nobody, including us, can forge a signature for your key.
Integrity: the chain's consensus
Balances are storage slots in a contract whose bytecode is fixed at deployment and hashed into every block that follows. Altering a balance would mean altering Robinhood Chain's history. This is the same guarantee that protects USDG itself.
Re-entrancy and token safety
All three contracts inherit OpenZeppelin's ReentrancyGuardand every external state-changing function is marked nonReentrant, so a malicious token or pool callback cannot re-enter mid-operation. Token transfers go through SafeERC20, which reverts on the non-standard tokens that return nothing instead of true.
Price arithmetic
Uniswap v3 encodes price as sqrtPriceX96, a Q64.96 fixed-point square root. The contracts square it with Math.mulDiv (full 512-bit intermediate, no overflow) and rescale between USDG's 6 decimals and the stock's 18. Mixing those decimals is the classic way a vault silently misprices by 10¹²; the tests pin the conversion.
There is no zero-knowledge, no encryption, no off-chain signing service. What you see on-chain is the whole system. Anything that sounds more clever than that would be a place to hide something.
Risks and limits
These are the things that can go wrong. They are real, and knowing them is the price of using a system nobody can pause.
- Spot-price collateral. CollateralLoan prices collateral from the pool's current tick, not a TWAP. A large enough flash-loan swap can move that price within one block. The 50% cap, the 60% threshold and the 50% close factor limit the damage, but a manipulated liquidation is possible. Do not put your only copy of something in as collateral.
- SGOV is an ETF token. It carries the issuer's risk and the peg of the wrapper that brought it on-chain. Locksley cannot see or fix either.
- Pool liquidity. Deposits and withdrawals swap through Uniswap. Thin liquidity means slippage; your minOut floor is the only protection. Set it.
- Immutability cuts both ways. A bug found after deployment stays. The tests are thorough - 22 passing, including boundary and liquidation cases - but tests prove what was imagined.
- Not a bank. No deposit insurance, no regulator, no recourse. That is the design.
The loan contract is the highest-risk of the three by construction. Treat it as an experiment until it has been independently audited, and size positions accordingly.
Reference
Deployed contracts - Robinhood Chain
| Contract | Role | Address |
|---|---|---|
| Savings | USDG ⇄ SGOV vault, open + locked terms | 0xF28571Da91c7A8d3511A57f81b57098f9d1970b8 |
| StandingOrders | Escrowed scheduled payments | 0x9188572646DCa8460360267CCE10cB88a764743E |
| CollateralLoan | Lender reserve + stock-backed borrowing | 0x4b5181c539954b28cF69a05b9eC45161c6eC587A |
Protocol constants
| Constant | Value | Meaning |
|---|---|---|
| MAX_TERM | 730 days | Longest lock a savings deposit can choose |
| SGOV_FEE | 3000 (0.30%) | Uniswap v3 pool tier the vault swaps through |
| MAX_LTV_BPS | 5000 (50%) | Most you can borrow against collateral value |
| LIQ_THRESHOLD_BPS | 6000 (60%) | Debt-to-collateral at which a position can be liquidated |
| LIQ_BONUS_BPS | 800 (8%) | Discount a liquidator receives on seized collateral |
| CLOSE_FACTOR_BPS | 5000 (50%) | Share of debt one liquidation may repay |
| RATE_PER_SEC | 2,535,100,000 (1e18 scale) | Borrow interest, ≈ 8% APR, accrued per second |
Shared addresses
| Name | Role | Address |
|---|---|---|
| USDG | Quote asset, 6 decimals | 0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168 |
| SGOV | Savings backing, 18 decimals | 0x92FD66527192E3e61d4DDd13322Aa222DE86F9B5 |
| Uniswap v3 Factory | Pool lookup | 0x1f7d7550B1b028f7571E69A784071F0205FD2EfA |
| SwapRouter02 | Savings swaps | 0xCaf681a66D020601342297493863E78C959E5cb2 |