Skip to Content
solidondocs

Treasuries

How each meme contract controls its own addresses on Base, Robinhood Chain and Solana through NEAR Chain Signatures, and how cash and stock are booked.

Every meme owns two treasury addresses outside NEAR: one EVM address used on both Base and Robinhood Chain, and one Solana address. Both are derived from the meme's NEAR account by the NEAR MPC network (Chain Signatures). No person holds a key to them. Only the meme contract can ask the MPC network to sign for them.

Derived addresses

TreasurySignature schemeMPC domainDerivation pathSet by
EVM (Base Sepolia and Robinhood Chain testnet)ECDSA (secp256k1)0evm-treasuryinit_treasury(), anyone, once
Solana devnetEdDSA (Ed25519)1solana-treasuryinit_solana_treasury(), anyone, once

The MPC signer is v1.signer-prod.testnet. The contract reads its derived public key and stores the resulting address. The same EVM address is used on every EVM chain, with a separate nonce per chain. On Solana the relayer then sets the treasury's USDC and stock token accounts with set_solana_accounts, from canonical bumps.

Example, HONEY (honey.solidon.testnet):

What the contract signs

The contract builds every treasury transaction itself, from config that was locked when the factory was initialized. A caller cannot supply calldata, a recipient or a token.

MethodChainTransaction built by the contract
approve_router(chain)Base, Robinhood Chainapprove(router, max) on that chain's USDC, for the locked Uniswap v3 SwapRouter02
buy_stock(chain)Base, Robinhood ChainSwapRouter02 exactInputSingle of up to max_swap_usdc USDC into the meme's locked stock, minAmountOut = oracle value minus 1%
buy_stock_solana(blockhash, tick_arrays)SolanaA legacy message with CreateIdempotent for the stock token account and Raydium CLMM swap_v2 of up to max_swap_usdc USDC into the stock, minAmountOut = oracle value minus 1%
resign_solana(blockhash, tick_arrays)SolanaThe last Solana buy again, same amount and minAmountOut, with a new blockhash

On Solana, two inputs come from the caller: a recent blockhash and the pool's tick arrays. Every other account comes from locked config and the contract's own derivations. A wrong blockhash or tick array can only make the swap fail on Solana; it cannot redirect funds.

The testnet cap is 5 USDC per swap per chain, so the 0.3% pool fee plus price impact stays inside the 1% slippage allowed against the oracle. Larger balances are swapped over several transactions.

Signature verification before storing

The contract does not trust the MPC response blindly. On every signature it runs:

  • ecrecover on EVM, and
  • ed25519_verify on Solana, over the exact message,

and stores the signed transaction only if the signature matches its own treasury key. A wrong or malicious signature is discarded.

One signature is in flight at a time across all chains. If a signing callback never completes, anyone can call clear_stuck_signature() after 300 blocks to free the slot; the nonce is not consumed.

Anyone broadcasts

Signed transactions are public. get_signed_tx(chain, nonce) returns them ready to send: 0x hex on EVM, base64 on Solana. Any account can broadcast them. The official keeper does this as a convenience; if it stops, anyone else can take over. The treasury needs a little ETH (Base, Robinhood Chain) and SOL (Solana) for gas, which anyone can top up.

Cash arrivals

USDC leaves NEAR through fund_chain(chain) and is booked as in transit for that chain. When it arrives, the chain's USDC ledger is credited out of that in-transit amount.

Anyone calls credit_cash(chain, tx_hash, log_index, log) with the USDC Transfer log from the transaction receipt. The contract checks that the log is a Transfer from the chain's USDC to the treasury, computes the MPC payload hash itself, and calls verify_foreign_transaction on v1.signer-prod.testnet (domain 3) with that expected_payload_hash. The MPC answers only if its nodes see that exact log. A wrong claim gets no answer. Each log is credited once.

Because every credit is capped by cash already counted in NAV, a credit can only move value from "in transit" to "on the chain". It cannot create value.

The ledger books the minimum

Stock holdings are booked, not read. When a swap is signed, the ledger records its minAmountOut, the least it can receive. A swap that lands leaves the chain slightly above the ledger. The app shows the ledger next to the real explorer balance for each chain.

Disclosure: reverted swaps stay booked

A signed EVM swap can revert on-chain, for example when the pool has drifted more than 1% from the oracle ("Too little received"). The ledger booked minAmountOut at signing, so the stock figure is overstated while the USDC stays unspent in the treasury. Total value is unchanged, but its split is wrong. The chain's USDC ledger reads 0, so that USDC is not spent again. The app flags the chain "Less on-chain". This is the case today for HONEY on Base and Robinhood Chain, from two swaps that reverted before the automatic re-peg of the synthetic pools ran. Base example: 0x9609b7….

Planned fix: book EVM swaps only after the MPC verifies the swap's Transfer log on Base, and give relayer chains a capped "swap failed" report that returns the booking to USDC.

Expired Solana buys

A Solana transaction expires about 60 to 90 seconds after its blockhash. If a signed buy never lands, anyone can call resign_solana once 200 NEAR blocks have passed since it was signed and nothing else is in flight. The same buy is signed again with a new blockhash, and the ledger is not touched again. The 200-block wait (at least 2 minutes) is longer than a blockhash lifetime, so the old and new transaction can never both land.

Proven live

WhatEvidence
MPC-signed EVM transactions mined on Base Sepolia and Robinhood Chain testnetdocs/SPIKE.md S23
MPC EdDSA controls a Solana address; hand-built Raydium swap signed by the MPC and finalized on devnetdocs/SPIKE.md S21, S25
The contract's own expected payload hash for a Base USDC Transfer log, signed by the live testnet MPCdocs/SPIKE.md S26
One meme holding NVDA on all three chains, every step signed at the contract's requestdocs/DEPLOYMENTS.md, "End to end"

See Security for the full threat model and Contracts reference for method details.

On this page