Protocol documentation

How Rentnode works

Rentnode is a marketplace for rented infrastructure - GPUs, CPUs, disks and databases - reduced to the one thing a chain can actually do: hold money and meter it out per second. One contract on Robinhood Chain, no owner, no fee, no arbiter. This is the technical reference for what it does and, just as importantly, what it cannot.

Chain Robinhood (EVM 4663)Unit USDG · 6 decimalsGranularity 1 secondAdmin none
Overview

A meter, not a middleman

Renting a machine from a stranger normally needs someone in the middle: to hold the deposit, to decide who was right when the box went down, to take a cut for the trouble. Rentnode removes that seat. A renter escrows USDG against a listing, the contract pays it out to the provider one second at a time, and either side can stop the clock whenever they like. Every unspent cent goes back to the renter in the same transaction.

  • List - a provider publishes a machine and an hourly price. No deposit, no application, no approval queue.
  • Escrow - a renter funds however many hours they want. The USDG sits in the contract; nobody can move it but the metering.
  • Meter - payment accrues to the provider per second. They may withdraw the earned part at any moment.
  • Stop - either side closes. Earned to the provider, the remainder to the renter, one transaction.

The contract does not run, verify or vouch for any machine. A listing is a claim its provider makes. Your protection is not a judge - it is that leaving costs you nothing but the seconds you used.

Vision & mission

Compute priced like electricity

Vision

Idle hardware is everywhere: a gaming rig at night, a lab's cluster between papers, a startup's over-provisioned box. What stops it being rented is not the hardware, it is the paperwork - accounts, minimums, invoices, disputes. Rentnode's vision is a market where anyone can plug a machine in, anyone can draw from it, and the bill is settled by the clock rather than by a company.

Mission

  • Per-second, no minimum. A lease can be five seconds long. The contract meters from the hourly price; it never rounds you up to an hour.
  • Exit is free. Closing a lease costs one transaction and returns everything unspent. That right belongs to the renter and cannot be revoked.
  • No arbiter by construction. The worst outcome for a renter is the seconds between a machine dying and them noticing. That is small enough that nobody needs to judge it.
  • Honest supply. Machines on the shelf are real or they are not there. The relay that mirrors Vast.ai says so in every listing's spec.
  • Immutable. No owner, no pause, no fee, no upgrade path. What deployed is what runs.
Architecture

One contract, one token

ComputeMarket holds two arrays - listings and leases - and one token reference, USDG. It talks to nothing else: no oracle, no router, no registry, no proxy. The console is a window onto that state; anyone can read or write it directly with a wallet, and a relay can act as a provider without any special role.

Renterescrows USDG, holds the only refund keyProviderlists, keeps the endpoint currentComputeMarketescrow · per-second meter · settleUSDGthe only token it touchesThe machineoff-chain · never seen by the contractssh, http, whateverthe listing says

One contract, one token, no owner. The machine is on the right and the chain never looks at it - that is the design, not a gap.

Mechanism

Listing a machine

list(kind, pricePerHour, spec, endpoint) pushes a listing owned by msg.sender. kindis one of GPU, CPU, Storage, Database and only sorts the shelf; specis free text like RTX 4090 / 24GB / eu-central; endpoint is where a renter reaches the machine once paid.

  • No deposit. A deposit only gates entry unless someone can judge when to seize it, and there is no someone. Reputation is the public lease history instead.
  • Reprice any time with updateListing. New leases take the new rate; a running lease keeps the rate it started at.
  • Endpoint is public. It is stored in the clear. Publish a hostname or a relay URL, never a key, a token or a password.
// a listing, as stored
struct Listing { address provider; Kind kind; uint96 pricePerHour; bool open; string spec; string endpoint; }
// pricePerHour is USDG with 6 decimals: 0.50 USDG/hr = 500000
Mechanism

Escrow and the second-hand

rent(listingId, amount) pulls amount USDG into the contract and opens a lease with startAt = block.timestampand the listing's price frozen into it. From that block on, the provider's earnings are a pure function of time:

// what the provider has earned so far
earned = min(pricePerHour × (now − startAt) ÷ 3600, funded)
// multiply before dividing, so sub-cent seconds never round to zero
FUNDED ESCROW, SECOND BY SECONDearned · to the providerrefundable · to the renterstartAtnow · close()runway = 0earned = pricePerHour × elapsed ÷ 3600, capped at funded. A lease never goes into debt.Price is frozen at rent(). A provider repricing the listing cannot touch a live lease.claim() moves the lime part any time; close() moves both parts at once and stops the clock.

Two numbers describe every lease: what has been earned, and what is left. Both are one read on the contract.

Top-ups

topUp(leaseId, amount) adds funding to a running lease. Anyone may pay - a team can keep a colleague's box alive - but the refund always goes to the renter of record. A lease that runs out of funding simply stops earning; it never goes into debt, and the renter is never billed past what they escrowed.

Claiming

claim(leaseId) lets the provider draw down earned − claimed at any moment without ending the lease. Nothing forces them to wait; nothing lets them take more than the clock has counted.

Mechanism

Closing, by either side

close(leaseId) may be called by the renter or the provider - nobody else. It stamps closedAt, computes the final split, and moves both halves in one transaction. Settlement is identical whoever called it:

// at close()
owed = earned − claimed → provider
refund = funded − claimed − owed → renter
// contract balance for this lease after: 0
  • Renter closes because the box stopped working, or because the job finished early. Every unspent cent returns immediately.
  • Provider closes to take the machine back. They keep only what the clock counted; they cannot keep the remainder.
  • Nobody closes and the funding runs out - the lease idles at runway = 0, earning nothing more, until someone settles it.

This is the whole dispute mechanism. There is no "the box was down" ticket because the renter's remedy - stop paying, now - does not need anyone's agreement.

Mechanism

Real supply through a relay

A marketplace with no machines is a contract with no purpose. Rentnode ships a relay - an ordinary provider process, open source, running under its own key - that mirrors a curated set of Vast.ai machine types onto the shelf, priced at Vast's live rate plus a margin, and fulfils leases with real instances.

  • Sync - every hour it asks Vast for the cheapest verified offer of each type and lists, reprices or closes accordingly. Every one of its listings says via Vast.ai in the spec.
  • Watch - every 15 seconds it polls leaseCount. A new lease on one of its listings rents a matching instance and attaches a fresh ssh key generated for that lease alone. If Vast has nothing, it closes the lease at once so the renter loses nothing.
  • Serve - its endpoint hands over ssh access to whoever can prove they are the renter (see Cryptography).
  • Settle - it claims what has accrued and destroys the instance when the lease closes or its runway hits zero.
Renter's walletsigns one message, no gasRelayrecovers signer · reads lease.renterssh accesshost · port · per-lease keyrentnode lease <id> <minute>ComputeMarket.leaseAt(id).renter must equal the recovered addresssignature older than 5 minutes is refused

The contract stores one endpoint per listing, but a lease is per renter. The signature is what turns a public URL into a private door.

The relay is convenience, not protocol. It has no privileged role in the contract; if it went offline, its listings would go stale and anyone else's would be unaffected. Vast bills the relay operator in USD; renters pay the contract in USDG. The margin covers that gap.

Trust

Who can move what

The clearest way to state the custody model is as a permission table. Three actors exist: the renter, the provider, and Rentnode. The last column is empty on purpose.

Renter canrent · top upclose, any secondtake every unspent centfetch access with a signatureProvider canlist · reprice · close listingclaim what has accruedclose a lease, keeping only earnednever raise a live rateRentnode can— nothing —no owner · no pauseno fee switch · no upgradeno way to freeze escrow

The third column is the product. The relay is a provider like any other; its key has no more power than yours.

Concretely: no function in ComputeMarket is gated by an owner, admin, guardian or multisig role. There is no Ownable, no Pausable, no upgradeable proxy, no fee recipient. The deployer's key was used once, to deploy, and has no standing afterwards. The whole contract is under 240 lines - short enough to read in one sitting.

Trust

What the cryptography actually guarantees

Rentnode adds one signature scheme of its own - the access hand-over - and otherwise rests on the primitives of the chain. 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 against the lease: only the renter or the provider may close, only the provider may claim or reprice. Nobody, including Rentnode, can forge a signature for your key.

Access hand-over: EIP-191 personal_sign

The contract stores one endpoint per listing, but a lease belongs to one renter. So the console asks the renter to sign the plain message rentnode lease <id> <unix minute> with the wallet that paid - no gas, no transaction. The relay recovers the signer with ecrecover, reads leaseAt(id).renterfrom the chain, and returns the ssh host, port and private key only if they match. The minute in the message bounds replay to five minutes. The relay never learns the renter's wallet key, and no one else can fetch the ssh key.

Per-lease ssh keys: Ed25519

The relay generates a fresh Ed25519 keypair for every lease with ssh-keygen, installs the public half on the instance, and hands the private half to the renter over the signed channel. Closing the lease destroys the instance; the key is worthless afterwards.

Integrity: the chain's consensus

Escrow balances are storage slots in a contract whose bytecode is fixed at deployment and hashed into every block that follows. Altering one would mean altering Robinhood Chain's history. This is the same guarantee that protects USDG itself.

Re-entrancy and token safety

The contract inherits OpenZeppelin's ReentrancyGuard; rent, topUp, claim and close are nonReentrant. Transfers go through SafeERC20, which reverts on tokens that return nothing instead of true. Amounts are uint96: large enough for any real lease, small enough that the whole lease packs into two storage slots.

There is no zero-knowledge, no encryption of listings, no off-chain signing service in the money path. What you see on-chain is the whole settlement system. The relay is the only off-chain component, and it can only do what any provider can.

Trust

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.

  • The chain cannot see the hardware. A listing may be slower, smaller or deader than its spec claims. You pay for the seconds until you notice and close. Check a machine early; the first minute is cheap.
  • A dark provider still earns until you close. The meter runs on the clock, not on uptime. Set an alert on your own job, not on the contract.
  • The endpoint is public. Anyone can read it. A provider who puts a secret there has leaked it; use a relay-style signed hand-over or an authenticating host.
  • Relay counterparty. Leases on via Vast.ai listings depend on the relay process and the operator's Vast credit being alive. If either fails, close the lease; the contract refunds you regardless.
  • Immutability cuts both ways. A bug found after deployment stays. Fourteen tests cover metering, close-by-either-side, top-up, claim, the funded cap and a fuzz over timings that settles every lease to zero - but tests prove what was imagined.
  • Not a cloud. No SLA, no support desk, no recourse. That is the design.

Fund leases in small increments and top up as you go. The contract will happily hold a month of escrow, but there is no reason to give a stranger's clock more than an hour's head start.

Protocol

Reference

Deployed contracts - Robinhood Chain

NameRoleAddress
ComputeMarketEscrow, per-second metering, settlement0xd172e6Aa54e2D04F4168a339B63F284c99162D9d
USDGQuote asset, 6 decimals0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168
RelayProvider key of the Vast.ai relay - no special role0xb3180B4a2B6dB9415FA26Ebe92e4aaD973e73144

Functions

FunctionWhoEffect
list(kind, pricePerHour, spec, endpoint)anyonePublish a machine. Price in USDG per hour, 6 decimals. No deposit, no approval.
updateListing(id, pricePerHour, endpoint, open)providerReprice, move, or close a listing. Binds future leases only.
rent(listingId, amount)anyoneEscrow `amount` USDG against an open listing. The clock starts in the same block.
topUp(leaseId, amount)anyoneAdd funds to a running lease. Anyone may pay; only the renter is refunded.
claim(leaseId)providerWithdraw what has accrued so far, without ending the lease.
close(leaseId)renter or providerEnd the lease. Earned to the provider, the rest to the renter, one transaction.
earned / refundable / runway(leaseId)viewAccrued so far, refund if closed now, seconds left at the current rate.

Errors

ErrorWhen
NotProviderCaller does not own the listing or lease being claimed
NotPartyclose() from an address that is neither renter nor provider
ListingClosedrent() against a listing whose open flag is false
BadPricepricePerHour of zero
BadAmountZero escrow, zero top-up, or nothing to claim
AlreadyClosedtopUp() or close() on a settled lease
NoListing / NoLeaseIndex past the end of the array

Constants

NameValueMeaning
granularity1 secondearned = pricePerHour × elapsed ÷ 3600
KindGPU · CPU · Storage · DatabaseSorts the shelf; meaning of the spec is off-chain
relay MARGIN15%Over Vast's live price on relay listings
relay SYNC_MIN60 minutesHow often relay listings are repriced
access window5 minutesAge past which a signed access request is refused