Technical Overview
River Architecture Document (WIP)

Overview
The River Protocol Core is a primary set of four smart contracts.
RiverUSD (rUSD) - A “Synthetic” stablecoin that is originally 1:1 backed with USDC.
ERC20 Upgradeable
StakedRiverUSD (srUSD) - A vault token that RiverUSD holders can deposit into to earn yield from River structured credit strategies
ERC[20,4626,7540] Upgradeable
Globals - A global access control manager
TimelockGovernor - A privileged actor that has special permissions to call various functions across RiverUSD, StakedRiverUSD, and Globals
All contracts besides TimelockGovernor are upgradable.
RiverUSD
RiverUSD is a synthetic stablecoin that is originally 1:1 mintable and withdrawable for USDC. It offers a standard ERC20 for the River Ecosystem. In its initial phases, RiverUSD maintains a whitelist. Only members added to the whitelist by an admin are able to mint RiverUSD.
Flows
Mint Flow

Withdraw Flow

Security Considerations
Only upgradeable by TimelockGovernor
Only whitelisted addresses can mint rUSD
Only an admin (From Globals) can manage the mint whitelist
Redemptions are not whitelisted
Initially only 1:1 backed by USDC
Less integration risks
Always redeemable 1:1 for USDC since rUSD holders must opt in to purchase srUSD vault tokens.
StakedRiverUSD
StakedRiverUSD is the yield bearing counterpart to RiverUSD. RiverUSD holders can deposit StakedRiverUSD vault tokens that accrue yield as River uses the underlying funds to deploy into off-chain structured credit opportunities.


Staked River Strategies
Strategies are modules attached to StakedRiverUSD that have special permissions to draw from the underlying RiverUSD backing the StakedRiverUSD vault. StakedRiverUSD is expected to only have two strategies in the near term.
StructuredCreditStrategy - This will pull RiverUSD , convert it to USDC and send it to a pre-approved Offramp address which will fund the structured credit deals originated.
Structured Credit Strategy

Strategy admins report on the performance of the off-chain loans which determines the srUSD share price.

Determining srUSD Share Price
srUSD has two share prices: Optimistic and Conservative. The optimistic price is used to determine the share price for new deposits while the conservative price is used to determine the share price for withdrawals.
Optimistic Pricing
The srUSD optimistic price can be calculated as
TotalReserves=rUSDreserves+∑strategiesAUM(strategy)
Structured Credit Formulas
AUM = principalOustanding + accruedInterest
Accrued Interest = perSecondEstimatedInterestRate * offchainCapital * secondsElapsed
Where offchainCapital is the amount of rUSD that has been offramped and is being used to fund off-chain loans.
River Strategy Formulas
AUM = strategy.previewWithdraw(shares)
Conservative Pricing
TotalReserves=rUSDreserves+∑strategiesAUM(strategy) -UnrealizedLosses(strategy)
Invariants
conservativeSharePrice <= optimisticSharePrice
First in First Out (FIFO) Exit Queue (FIFO)
Because River deploys capital into off-chain structured credit facilities, underlying liquidity is not always immediately available for withdrawals. To ensure fair and orderly exits, srUSD uses a First-In-First-Out (FIFO) withdrawal queue. Each depositor may maintain up to 10 open FIFO positions at any given time.
When an srUSD holder enters the queue, their srUSD shares are burned and replaced with a queued withdrawal position representing the amount of shares they wish to redeem. Withdrawal requests are fulfilled sequentially as liquidity becomes available.
A queued position has the following properties:
Servicing & Redemption: A position becomes redeemable once the Servicer updates the queue and allocates rUSD to it. The amount of rUSD owed is determined using the conservative srUSD share price at the moment the Servicer processes that position.
Partial Redemptions: If only a portion of a position’s shares can be serviced at a given update, the position is partially redeemed, and the remainder stays in the queue until additional liquidity is available.
User-Initiated Cancellation: At any time before a position has been fully serviced, a user may cancel that position and receive back the equivalent amount of srUSD shares they originally burned.
The Servicer is expected to update the FIFO queue whenever sufficient liquidity is available and doing so does not compromise the protocol’s investment strategies or cash-management obligations. This ensures that user exits proceed smoothly while allowing River to maintain efficient capital deployment.
Staked River USD Security Considerations
Staked River is only upgradeable by the TimelockGovernor
Only “Strategies” can request funds
Each strategy has its own admin that is responsible for managing the strategy.
The structured credit strategy manager can only send funds to preapproved “Offramp” actors
The structured credit strategy can only request funds if called by the TimelockGovernor and it has permissions to send the funds to an approved offramper
This is a double layer of protection.
All strategies must inherit the IStrategy interface
Only the timelock can add or remove strategy
Only whitelisted addresses can deposit rUSD into srUSD
Redemptions are not whitelisted
Only an admin (From Globals) can manage the deposit whitelist
Interest rate updates are bounded by a max of 40% APY. (Configurable by timelock)
Globals
The Globals contract includes three primary modules.
Global Access Control
The Globals contract exposes a public Access Control API. Other contracts (rUSD and srUSD) can read from the global access control module. This allows for faster coordination and a central point of truth for recognizing authorized or permissioned actors.
All roles in Globals are listed below:
DEFAULT_ADMIN_ROLE (Manages whitelist)
STRUCTURED_CREDIT_STRATEGY_ADMIN_ROLE (Reports on performance and returns yield and principal)
ALIAS_ADMIN_ROLE (Toggles alias statuses)
SERVICER_ROLE (Updates the FIFO Queue)
Instance Registry
Similar to Access Control, the Globals contract allows for the registration of “Instances”. For example, offrampers are not assigned the OFFRAMPER_ROLE, but rather, Globals recognize a certain address as a valid instanceOf the type keccak256(“Offramper”). The instance module offers cleaner separation and management.
The "Offramper" receives funds from the Structured Credit Strategy.
Alias Registry
The Alias Registry is a finely scoped Pause protocol. Other contracts can check if an alias is turned on or off and take action based on the status. For example, the srUSD contract has a checkAlias modifier that reverts if the alias is disabled. It attaches this modifier on the deposit function. This allows an approved alias controller to pause certain functions in times of stress.
All Aliases:
STAKED_RIVER_4626_MINT
STAKED_RIVER_DEPOSIT
STRUCTURED_CREDIT_REPORT
RIVER_DEPOSIT
Security Considerations
Granting and removing roles is gated by the timelock contract
The instance registry is controlled by the timelock contract
Only the Timelock contract can add an “Offramper” role.
The Alias registry is controlled by an ALIAS_CONTROLLER role
Withdraw and redeem functions are not tied to the alias registry in order to prevent a withdraw deadlock
River Timelock Governor Security Model
Proposer Requirements
Each Proposer must be a 3/5 Multisig
There must always be a primary proposer and at least one backup proposer
Canceller Requirement Multisig
A canceller does not have a strict quorum requirement
There must always be a primary canceller and at least one backup canceller
Power Balance
There must always be at least as many cancellers as there are proposers.
A proposer may not also be a canceller
Granting & Removing Roles
The timelock on a Grant/Revoke role function MUST be 5 days.
Description:
The TimelockExecutor contract extends openzeppelin's TimelockController with extra modules to harden security.
Role In The Protocol
The timelock executor is responsible for
Upgrading Contracts (Globals.sol,River.sol,StakedRiver.sol)
Adding or removing roles on the timelock itself
Adding or removing roles in Globals.sol
Adding or removing strategies in StakedRiver.sol
Allowing a strategy to pull funds from StakedRiver.sol
Modules
Proposer Rate Limit Module
If a proposer gets compromised, they could spam the timelock with a large amount of functions which would make it painful the a canceller to cancel all the timelocked transactions. By having a rate limit of 1 proposal per 5 minutes per proposer, we reduce this risk. A proposer can submit a max of 2016 transactions per week under this rate limit.
Cancel Allowance Module
The cancel allowance module allows the timelock itself to grant any address a number of "cancel" operations that it can perform at any time. The number of cancel operations that an address can be granted is clamped to 4032 at any given time. This gives enough allowance to individually remove all transactions proposed by a single proposer in a two week span.
The cancel module is a safeguard against a canceller multisig not being able to respond in due time. EOA's or bots can be setup to monitor actions and call cancel if the action does not meet or breaks certain requirements.
Function Selector Registration
The timelock has permission to execute critical functions across the River Protocol. This includes things such as updating implementations for proxies, updating approved offrampers, allowing strategies to draw funds from staked tokens, granting and removing roles, etc.
Some functions are more critical than others. For example, an upgrade should be heavily scrutinized by all parties, while granting an EXECUTOR_ROLE has more relaxed security assumptions.
In order to add flexibility in timelocks, the function selector registration module allows to define specific minimum delays to an (address,function_selector) pair.
For example, a proxy upgrade could have a 10 day timelock, while adding or removing a role could have a 4 day timelock.
Functions are default denied until they are registered with the function selector registration module.
Timeout Module
In the case of a proposer getting compromised and requesting many transactions, a canceller can bulk invalidate all pending transactions and also prevent future proposal from being submit for that specific proposer. The canceller cannot specify a timestamp more than 2 weeks in the future. Once the canceller has initiated their timelock, they have a 21 day cooldown before they can rate limit that proposer again.
Immutable Selectors
Granting or adding a role can never be longer than TimeoutCooldown(21 days) - MaxTimeout(14 days) - 2 days = 5 days . This is so that in case of a canceller trying to permanently censor proposers, and the canceller keys being lost (unable to renounce the canceller role) , a proposer can fit in a proposal to remove the canceller. If the proposer themselves are malicious, this is also not a problem as the backup canceller can timeout the malicious proposer. If the backup canceller is not available, the cancel allowance module can take over and freeze up to two weeks of proposals from a single proposer.
Upgrading a contract must always take longer than TimeoutCooldown(21d) - MaxTimeout(14d) + 2 days = 9 days. This is so that a single live canceller can always fully censor all upgrade transactions. If the canceller is maliciously censoring upgrades, they can be replaced by the timelock.
Global Circuit Breaker
Is it worth having a CIRCUIT_BREAKER_ADMIN role that's a 5/8 and can trigger the wind-down protocol?
Flows
Happy Path
Proposal for execution is submit
Timelock deadline is met
Executors execute transaction
Malformed Proposal
Primary proposer messes up the inputs
Canceller cancels the transaction
Malicious Transaction / Compromised Proposer
Primary proposer becomes compromised and creates a malicious transaction
Proposer is rate limited in number of transactions they can propose
Canceller can cancel the individual transactions or timeout the proposer (max 1 week timeout)
Canceller can timeout the proposer
a) If primary proposer keyholders still have the key, they can renounce their role
b) If primary proposer keyholders lose access to the key, secondary proposer can request a transaction for the timelock to remove or replace the primary proposer.
Malicious but Recoverable Canceller
If a canceller becomes compromised, they could rate limit all proposers and prevent them from proposing a transaction that would remove / replace the canceller. If the canceller members still have access to their private keys, they can revoke their canceller status. After a proposer timeout has ended,
Malicious and Unrecoverable Canceller
If a canceller becomes compromised and the key holders are not able to renounce the role because they have lost the keys, the malicious canceller could try to continuously timeout all proposers. In order to prevent this, the timelock protocol establishes a MIN_TIME_BETWEEN_TIMEOUT_ACTIONS. This is currently set to 21 days while the MAX_TIMEOUT_DURATION is set to 14 days. This means that a proposer could propose to remove the canceller during those 7 days without fear of being rate limited. The process to add or remove a role takes 5 days leaving enough room. If the proposer becomes compromised as well, the backup canceller can rate limit the proposer again or the cancel allowance module can come into effect.
Wind-Down Protocol Overview
The Wind-Down Protocol defines a standardized recovery process to ensure that user exits remain possible in the event of a governance deadlock. It guarantees that liquidity can be safely withdrawn and capital unwound from active strategies even when core administrative roles — proposers, cancellers, or executors — become inactive or compromised.
A deadlock is formally defined as a state in which the Timelock contract has not executed any proposal within the preceding six-month period. Once this condition is met, the protocol transitions into wind-down mode, modifying certain permissions and operational constraints to restore liveness.
Under normal operation, specific vault functions (e.g., those within StakedRiver.sol) restrict exits by requiring that a designated SERVICER_ROLE update the FIFO redemption queue. This restriction enables controlled cash management and ensures that liquidity is available for ongoing yield strategies and deal commitments. During a deadlock, it is assumed that all operations are suspended; therefore, the protocol removes reliance on the SERVICER_ROLE, allowing any participant to update the FIFO queue and progress pending withdrawals.
Capital allocated to strategies — which ordinarily deploy assets from StakedRiver to earn and distribute yield — must also be unwound. Upon entering wind-down mode, strategies are required to return all held capital to StakedRiver, ensuring that liquidity providers can redeem their positions. Any residual or off-chain capital managed by the team must likewise be repatriated to StakedRiver over time until all obligations are settled.
The Globals contract exposes an API to check if the protocol is in wind-down so that the protocol can coordinate to enforce it.
Deadlock Scenarios
All Cancellers Compromised and Unrecoverable
If all cancellers are lost or compromised, the Timelock becomes incapable of executing valid proposals. To detect this condition, the Timelock records the timestamp of the last executed operation. Operational policy requires that at least one “heartbeat” (dummy) transaction be executed every six months to maintain governance liveness. If no operation occurs within that window, protocol components automatically shift to wind-down mode. For instance, StakedRiver.sol, which ordinarily restricts FIFO queue updates to the SERVICER_ROLE, will permit any address to perform updates, ensuring that liquidity providers can exit even in the absence of administrative oversight.
All Proposers Compromised or Unrecoverable
If proposers are unable to create or advance new proposals for execution, a deadlock arises from the proposal side. After six months of inactivity, the same wind-down logic is triggered, restoring open access to essential functions such as FIFO queue servicing and strategy unwinding.
Key Storage Requirements
Any signer on more than 1 privileged roles must diversify their hardware wallets between Ledger and Trezor.
Signing Requirements
Use custom CLI or Gnosis CLI, don't interact with frontends
Last updated

