Version 2 Released! Our biggest documentation upgrade to date.

sthUSD Implementation

sthUSD transforms idle thUSD into a yield-generating asset while maintaining the liquidity and stability users expect from stablecoins. This page explains how sthUSD works under the hood, from its ERC-4626 foundation to the custom mechanisms that make it secure and efficient.

What Problem Does sthUSD Solve?

Traditional stablecoins force users to choose between yield and liquidity. You can either:

  • Hold USDC (liquid but no yield)

  • Lock tokens in vaults (yield but no liquidity)

sthUSD eliminates this trade-off by providing both yield and liquidity through an intelligent vault design.

Contract Overview

Property
Value

Contract

sthUSD.sol

Standard

ERC-4626 Vault with Tharwa extensions

Address

0xf7Af0A8079F12F19533B0DF69ce7ee6718b0C46f (Mainnet)

Security

0 Critical, 0 High findings


How sthUSD Works: Core Concepts

The Share-Based Model

sthUSD uses the ERC-4626 vault standard, which represents ownership through shares rather than direct token amounts. Here's why this matters:

Problem: Direct 1:1 token staking

  • 100 tokens in = 100 tokens out

  • Yield added by minting new tokens

  • Creates inflation and dilution

Example: Stake 1000 USDC, earn 50 USDC in new tokens

Asset Definitions

sthUSD manages one primary asset with sophisticated accounting:

asset() - thUSD (The Underlying Token)

This represents the ERC-20 token that users deposit to earn yield. In sthUSD's case, this is always thUSD (0x76972F054aB43829064d31fF5f3AcC5Fabe57FE8).

Key Point: Users deposit thUSD and receive sthUSD shares. The value of these shares grows as the vault earns yield from Tharwa's RWA portfolio.

shares - sthUSD (The Vault Token)

These represent proportional ownership in the vault. Unlike many DeFi protocols where shares are minted/burned arbitrarily, sthUSD shares have real economic meaning:

As totalAssets() grows through yield, each share becomes worth more thUSD.

State Variables Explained

sthUSD tracks several key variables to maintain security and prevent manipulation:

Why These Variables Matter:

  • _pooledAssets: Prevents "donation attacks" where someone sends tokens directly to manipulate share price

  • _yieldAmount & _vestingEnd: Ensures new depositors can't immediately claim yield that was earned before they arrived

  • _cooldownPeriod & _silo: Provides flexibility between instant liquidity and enhanced security

  • Fee variables: Allow protocol sustainability without hardcoded rates


Accounting Model: How Value Accrues

The Core Challenge: Preventing Manipulation

The biggest challenge in yield-bearing tokens is preventing "donation attacks" where malicious actors manipulate share prices. Here's how sthUSD solves this:

Scenario: Malicious actor exploits naive accounting

  1. Attacker deposits 1 wei to get shares

  2. Attacker donates 1000 thUSD directly to contract

  3. Share price skyrockets artificially

  4. New depositors get almost no shares for their deposits

  5. Attacker withdraws at inflated price

Result: New users get rugged, attacker profits

Total Assets Calculation

The heart of sthUSD's security is its totalAssets() function:

Breaking this down:

  • _pooledAssets: Only includes legitimate deposits and properly added yield

  • _unvestedAmount(): Excludes yield that hasn't finished vesting yet

  • Result: Share price reflects only "earned" and "available" assets

Yield Vesting: Preventing Yield Theft

When Tharwa adds yield to sthUSD, it doesn't become immediately available. Instead, it vests linearly over 30 days:

Why Vesting Matters:

Without Vesting: Someone could deposit right before yield is added, immediately claim a large portion, then withdraw

With Vesting: Yield is distributed fairly over time to users who were actually staked when it was earned

Example:

  • Day 0: 1000 thUSD yield added, starts 30-day vest

  • Day 15: 50% of yield (500 thUSD) is vested and included in totalAssets()

  • Day 30: 100% of yield (1000 thUSD) is fully vested

Asset Flow Tracking

Yield Vesting Mechanism


Cooldown System

Cooldown States

The cooldown system provides flexibility for different withdrawal preferences:

Cooldown Period
Behavior
Use Case

0 (OFF)

Standard ERC4626 withdraw/redeem

DeFi integrations, instant liquidity

3 days

Staged cooldown via silo

Reduced exit fees, planned withdrawals

7 days

Extended cooldown via silo

Maximum security, institutional use

Cooldown Implementation

Silo Contract

The ThUSDSilo contract manages assets during cooldown:


Fee Structure

Fee Configuration

Current Fee Parameters

Fee Type
Current Rate
Maximum
Applied When

Entry Fee

0 bps (0%)

1000 bps (10%)

Deposit/Mint

Exit Fee

0 bps (0%)

1000 bps (10%)

Withdraw/Redeem/Cooldown


Access Control & Security

Role-Based Permissions

Role
Permissions
Purpose

DEFAULT_ADMIN_ROLE

All administrative functions

Protocol governance

PAUSER_ROLE

Pause/unpause contract

Emergency response

YIELD_MANAGER_ROLE

Add yield to vault

Treasury operations

FEE_MANAGER_ROLE

Configure fee parameters

Fee optimization

Security Features

  1. Pausable: Emergency pause for all user-facing functions

  2. Blacklist: Compliance-focused address restrictions

  3. Reentrancy Protection: All external functions protected

  4. Safe Math: OpenZeppelin's Math library for overflow protection


Gas Optimization

Efficient Storage Layout

Gas-Efficient Operations

Operation
Gas Cost
Optimization

Deposit

~50,000

Minimal external calls

Withdraw

~45,000

Direct asset transfer

Cooldown

~60,000

Single silo interaction

Add Yield

~40,000

Simple accounting update


Testing & Validation

Comprehensive Test Suite

Invariant Testing

Key invariants maintained throughout all operations:

  1. totalAssets() >= totalSupply() * minSharePrice

  2. _pooledAssets >= totalAssets() + unvestedAmount()

  3. sum(balanceOf(users)) == totalSupply()

  4. cooldownAssets + vaultAssets == totalPooledAssets


Integration Examples

Basic Integration

Advanced Integration with Cooldown


Developer Resources

Last updated