Robinhood Chain · reading the node
@getowed
GetOwed

Documentation

Overview

GetOwed reads the subscription receipts already landing in your mailbox and pays back a slice of the company behind each one as fractional tokenized stock. Pay for Netflix, hold a sliver of NFLX. Pay for Claude or ChatGPT, hold a sliver of NVDA.

Nothing is minted. Every reward transfers stock that already sits in a public vault, so the on-chain balance is the backing rather than a statement about it. You connect a mail filter and a wallet. GetOwed never signs in to your mailbox and only reads the receipts you send it.

How it works

  1. 1

    Get an address

    A unique collect-<id>@getowed.top that maps to your wallet and to nothing else.

  2. 2

    Forward receipts only

    A filter scoped to subscription senders. Two-factor codes and password resets never match it.

  3. 3

    GetOwed reads three fields

    Merchant, amount in USD, date. The merchant resolves to a tokenized stock.

  4. 4

    GetOwed verifies

    Valid DKIM, aligned to the merchant's own domain, deduped on Message-ID, addressed to you, inside the 45 day window. Fail one and the receipt pays nothing.

  5. 5

    The reward is signed

    Your $OWED holdings set the rung and the rate, the remaining monthly ceiling applies, and an EIP-712 voucher is signed for the exact share count at the live price.

  6. 6

    You claim

    Your own wallet submits the voucher and the vault transfers the stock. GetOwed never touches your key.

What earns a reward

A merchant that trades publicly pays in its own ticker. One that does not pays the listed proxy for its sector, so no covered receipt comes back empty. 83 merchants are mapped across 22 tickers today and the list keeps growing.

AI tools NVDAWatching and listening GOOGLIndependent infra QQQEnterprise cloud MSFTGaming TTWOCreative software ADBEFitness LULUHealth HIMSSocial METAMoney apps COINGetting around UBER
QQQInvesco QQQ141Password, Cloudflare, DigitalOcean, Fly.io, Hetzner, Neon, Netlify, NordVPN, Railway, Render, Supabase, Vercel, Vultr, Zoom
NVDANVIDIA11ChatGPT, Claude, Cursor, ElevenLabs, GeForce Now, Hugging Face, Midjourney, Perplexity, Replicate, Runway, Suno
GOOGLAlphabet10Crunchyroll, Gemini, Google Cloud, Google One, Google Workspace, Max, Paramount+, Substack, The New York Times, YouTube Premium
MSFTMicrosoft7AWS, GitHub, GitHub Copilot, LinkedIn Premium, Microsoft 365, Microsoft Azure, Xbox Game Pass
ADBEAdobe6Adobe Creative Cloud, Canva, Figma, Framer, Miro, Notion
LULULululemon5ClassPass, Oura, Peloton, Strava, Whoop
METAMeta5Discord Nitro, Meta Verified, Patreon, Tinder, X Premium
TTWOTake-Two4Epic Games, Nintendo Switch Online, PlayStation Plus, Steam
AAPLApple3Apple Music, Apple One, Apple TV+
AMZNAmazon3Amazon Prime, Audible, Twitch
HIMSHims & Hers3Calm, Headspace, Noom
DISDisney2Disney+, Hulu
NFLXNetflix1Netflix
SPOTSpotify1Spotify
EAElectronic Arts1EA Play
RBLXRoblox1Roblox Premium
CRMSalesforce1Slack
COINCoinbase1Coinbase One
HOODRobinhood1Robinhood Gold
UBERUber1Uber One
ABNBAirbnb1Airbnb
SPCXSpaceX1Starlink

Only a completed receipt from a covered merchant, verified by signature, pays anything.

Reward tiers

Your rate comes from how much $OWED you hold, measured as a share of total supply rather than a dollar figure. No lock-up. Each rung caps what one calendar month can pay.

TierHeldRateMonthly ceiling
Opennone14%$30
Filed0.05%23%$70
Stamped0.15%33%$170
Certified0.35%45%$420
Bonded0.7%60%$1,000
Settled1.4%75%$2,100
  • Rate at earn time. Whatever rate applied when a receipt was recorded is the rate locked into its voucher.
  • Best of the last 24 hours. A brief dip in holdings does not knock you down a rung.
  • Monthly ceiling. Rewards past the ceiling in a month are not paid, and it resets on the first.

Custody

OwedClaimVault holds the stock that backs rewards. It has no owner sweep and no arbitrary execute(). Stock leaves by exactly one path: a user calling claim() against a GetOwed-signed voucher. Stock enters by a plain transfer from the treasury.

Because every payout moves stock already in the vault, the vault balances are backing you can read any time on the proof page. Payouts are authorised by the reward signer key, so the vault is exactly as trustworthy as that key is kept, which is why every rotation emits SignerSet on-chain.

Privacy and anti-abuse

Why a forged receipt pays nothing

  • DKIM has to verify, and its signing domain has to belong to the real merchant. Editing a forwarded mail breaks it.
  • Rewards dedupe on the immutable Message-ID, with a body hash covering receipts that lack one.
  • The receipt has to name your own address among its recipients.
  • Receipts older than 45 days are rejected outright.
  • Each rung bounds what one account earns in a month.

What GetOwed can and cannot see

  • Only the receipts you forward: merchant, amount, date. Never your mailbox, never a password.
  • Delete the filter to revoke. There was no account access to take back.
  • Claims are signed by your own wallet. The key never leaves your browser.

Contract

The reward vault, MIT licensed and non-custodial, on Robinhood Chain (id 4663). The complete source is below with nothing elided.

claim(token, to, amount, id, deadline, sig)

The only way stock leaves. Verifies the voucher against the signer, enforces a single-use id and a deadline, transfers to `to`.

reserves(token) → uint256

Live vault balance of one reward stock. The proof-of-reserves read.

setRewardToken(token, allowed)

Owner: add or drop a stock from the payout allow-list.

setSigner(s)

Owner: rotate the reward signer. Emits SignerSet.

setPaused(p)

Owner: emergency stop for claims. Moves no funds.

That is the entire owner surface. No sweep, no execute(), no fee pull, no receive(). Nothing moves a token out except claim().

contracts/src/OwedClaimVault.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

/// @title OwedClaimVault
/// @notice Pre-funded, multi-stock reward vault for GetOwed. It holds a basket
/// of tokenized stocks (NVDA, GOOGL, MSFT, AMZN, NFLX, SPOT, QQQ and the rest)
/// and releases a reward only against a GetOwed-signed EIP-712 voucher. Nothing
/// is minted here. Every payout moves stock that is already in the vault, so
/// the on-chain balance is the backing rather than a claim about it.
///
/// The reward `amount` already carries the holder's tier rate. The GetOwed
/// signer reads their $OWED holdings, applies the tier rate (14% at Open up to
/// 75% at Settled) and that tier's monthly ceiling, then signs the final figure.
/// The contract checks the signature, the reward-token allow-list, the
/// single-use id and the deadline. The economics stay off-chain in the signer.
///
/// Non-custodial by construction: there is no owner sweep and no arbitrary
/// execute(). Stock leaves only through claim(). The operator cannot withdraw
/// the backing. Stock flows in by a plain ERC-20 transfer from the treasury,
/// which collects protocol fees, buys the stock and deposits it here.
contract OwedClaimVault is EIP712, Ownable {
    /// @notice Key that co-signs approved rewards. The trust anchor of the vault.
    address public signer;
    bool public paused;

    mapping(address => bool) public isRewardToken; // tokenized-stock allow-list
    mapping(bytes32 => bool) public voucherUsed;   // reward id => redeemed
    mapping(address => uint256) public totalPaid;  // per-token lifetime payout

    bytes32 public constant VOUCHER_TYPEHASH = keccak256(
        "Reward(address token,address to,uint256 amount,bytes32 id,uint256 deadline)"
    );

    event Claimed(address indexed token, address indexed to, uint256 amount, bytes32 indexed id);
    event RewardTokenSet(address indexed token, bool allowed);
    event SignerSet(address indexed signer);
    event PausedSet(bool paused);

    constructor(address signer_, address[] memory rewardTokens_)
        EIP712("GetOwed Rewards", "1")
        Ownable(msg.sender)
    {
        require(signer_ != address(0), "signer=0");
        signer = signer_;
        for (uint256 i = 0; i < rewardTokens_.length; i++) {
            require(rewardTokens_[i] != address(0), "token=0");
            isRewardToken[rewardTokens_[i]] = true;
            emit RewardTokenSet(rewardTokens_[i], true);
        }
    }

    /// @notice Live reserve of one reward stock. The proof-of-reserves read.
    function reserves(address token) external view returns (uint256) {
        return IERC20(token).balanceOf(address(this));
    }

    // ---------------------------------------------------------------- claim ---

    /// @notice Redeem an approved reward. Anyone may relay the voucher, but the
    /// stock always lands at `to`. Single use per `id`, expires at `deadline`.
    function claim(
        address token,
        address to,
        uint256 amount,
        bytes32 id,
        uint256 deadline,
        bytes calldata sig
    ) external {
        require(!paused, "paused");
        require(isRewardToken[token], "token");
        require(to != address(0), "to=0");
        require(block.timestamp <= deadline, "expired");
        require(!voucherUsed[id], "used");

        bytes32 structHash = keccak256(abi.encode(VOUCHER_TYPEHASH, token, to, amount, id, deadline));
        require(ECDSA.recover(_hashTypedDataV4(structHash), sig) == signer, "bad sig");

        voucherUsed[id] = true;
        totalPaid[token] += amount;
        require(IERC20(token).transfer(to, amount), "transfer failed");
        emit Claimed(token, to, amount, id);
    }

    // ---------------------------------------------------------------- admin ---
    // The owner surface is deliberately small. Nothing below moves a reward out
    // of the vault: there is no sweep, no arbitrary execute, no fee pull and no
    // receive(), so ether cannot be trapped here either. Rewards enter through a
    // plain ERC-20 transfer from the treasury EOA and leave only through claim().
    //
    // Rotating `signer` is recorded on-chain via SignerSet, which is what makes
    // the trust anchor auditable rather than merely asserted.

    function setRewardToken(address token, bool allowed) external onlyOwner {
        require(token != address(0), "token=0");
        isRewardToken[token] = allowed;
        emit RewardTokenSet(token, allowed);
    }

    function setSigner(address s) external onlyOwner {
        require(s != address(0), "signer=0");
        signer = s;
        emit SignerSet(s);
    }

    /// @notice Pausing stops payouts and nothing else. It cannot move funds.
    function setPaused(bool p) external onlyOwner {
        paused = p;
        emit PausedSet(p);
    }
}

On-chain addresses

Everything settles on Robinhood Chain (id 4663). Nothing is deployed yet, so the table below reads launch soon until it is.

$OWED token

Launch soon

Launches paired with ETH. Your holdings set your rate.

OwedClaimVault

Launch soon

Non-custodial. Stock leaves only against a signed voucher.

Treasury wallet

Launch soon

Takes fees, buys stock, funds the vault.

Reward signer

Launch soon

Co-signs every claim voucher. Public key, rotations logged on-chain.

CLI and MCP

Both tools talk to the GetOwed API and print back what they get. They read no local files, run no shell commands and never ask for a private key.

$node cli/owed.mjs status <addr_id>

this month's rewards, your rung, holdings and what is claimable

$node cli/owed.mjs claim <addr_id>

the exact call to submit from a wallet you control

$node cli/owed.mjs merchants spotify

which merchants are covered and which ticker each pays in

$node cli/owed.mjs chain

a live read of Robinhood Chain

Node 18 or newer. Both ship in this repository, under cli/ and mcp/. They read no local files, run no shell commands and never ask for a private key. Point either at another deployment with OWED_API. Claiming settles on-chain from a wallet you control.

FAQ

What can GetOwed actually read?

The receipts you forward, and nothing past them. From each one it takes the merchant, the charge and the date. GetOwed never signs in to your mailbox, never sees mail you did not forward, and never asks for a password.

What lands in my wallet?

Fractional tokenized stock, reserved against a public vault on Robinhood Chain and claimed to the wallet you connected. It moves with the market in both directions, which is the difference between stock and points.

Who pays for the stock?

The GetOwed treasury. Your subscription charge never changes. Fees on $OWED fund the purchases, and the stock sits in the vault before any voucher is signed against it.

Can GetOwed take a reward back?

No. Stock leaves the vault through one path, a claim you sign. There is no sweep, no arbitrary execute, no owner withdrawal. The whole contract is printed on the docs page.

Could someone forge a receipt?

Editing a forwarded mail breaks its DKIM signature, and GetOwed checks that the signing domain belongs to the merchant it names. It also dedupes on the Message-ID, requires that the mail was addressed to you, and rejects anything past the freshness window.

How do I stop?

Delete the mail filter. GetOwed holds nothing else of yours. Whatever you already claimed stays in your wallet.

Do I have to hold $OWED to earn?

No. Open earns 14% with zero holdings. Holding more raises the rate and the monthly ceiling together.

Is this an investment product?

No. GetOwed is a rewards utility. Tokenized stocks are held and transferred on Robinhood Chain, rewards are not a guaranteed return, and eligibility depends on the chain and on your jurisdiction.

NVIDIA, Alphabet and every other company named here have no affiliation with GetOwed.