Proof of Reserve
A verification mechanism that cryptographically proves on-chain token supply is backed by real off-chain or cross-chain assets.
Proof of Reserve (PoR) is a cryptographic verification method that proves the assets backing a token or protocol actually exist. In DeFi, PoR is used to verify that wrapped tokens, stablecoins, and Real World Asset tokens are fully collateralized by their claimed reserves. This prevents fractional reserve fraud where issuers mint more tokens than they have backing assets—a practice that has led to major collapses in crypto history.
Why Proof of Reserve Matters
Without PoR, users must trust issuers aren't printing unbacked tokens:
1Scenario: Wrapped Bitcoin (WBTC)2- Claims: 1 WBTC = 1 BTC held in custody3- Risk: Custodian mints WBTC without depositing BTC4- Result: Token becomes partially backed, eventual collapse
PoR provides cryptographic verification that reserves match or exceed circulating supply.
How Proof of Reserve Works
On-Chain Verification
1import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";23contract TokenWithPoR {4 AggregatorV3Interface public reserveFeed;56 function mint(uint256 amount) external onlyMinter {7 // Get verified reserve amount from Chainlink PoR feed8 (, int256 reserves,,,) = reserveFeed.latestRoundData();910 // Ensure supply never exceeds reserves11 require(12 totalSupply() + amount <= uint256(reserves),13 "Insufficient reserves"14 );1516 _mint(msg.sender, amount);17 }1819 function getReserveRatio() external view returns (uint256) {20 (, int256 reserves,,,) = reserveFeed.latestRoundData();21 if (totalSupply() == 0) return type(uint256).max;22 return uint256(reserves) * 1e18 / totalSupply();23 }24}
Chainlink Proof of Reserve
Chainlink provides PoR feeds for various asset types:
Cross-Chain Reserves: Verify BTC/ETH locked on other chains Off-Chain Reserves: Verify bank balances, custody holdings Self-Attested Reserves: Protocol-reported reserves with oracle delivery
1// Example: WBTC Reserve Feed2AggregatorV3Interface wbtcReserves = AggregatorV3Interface(3 0x... // Chainlink WBTC PoR feed address4);56function checkCollateralization() public view returns (bool) {7 (, int256 btcReserves,,,) = wbtcReserves.latestRoundData();8 return uint256(btcReserves) >= wbtcToken.totalSupply();9}
Types of Proof of Reserve
Cross-Chain PoR
Verify assets locked on another blockchain:
1Bitcoin locked in custody → Chainlink nodes verify → On-chain feed2 ↓3WBTC minted on Ethereum ≤ Verified BTC amount
Off-Chain PoR
Verify traditional assets (bank accounts, commodities):
1Bank account balance → Third-party attestation → Chainlink feed2 ↓3Stablecoin supply ≤ Verified USD balance
Smart Contract PoR
Verify DeFi protocol collateralization:
1// Verify lending protocol solvency2function getLendingReserves() public view returns (uint256) {3 return totalDeposits - totalBorrows + collateralValue;4}
PoR in Practice
Stablecoins
1contract Stablecoin {2 AggregatorV3Interface public usdReserves;34 modifier ensureBacking(uint256 mintAmount) {5 (, int256 reserves,,,) = usdReserves.latestRoundData();6 require(7 totalSupply() + mintAmount <= uint256(reserves),8 "Insufficient USD backing"9 );10 _;11 }1213 function mint(address to, uint256 amount)14 external15 onlyMinter16 ensureBacking(amount)17 {18 _mint(to, amount);19 }20}
Wrapped Tokens
1contract WrappedAsset {2 // Circuit breaker if reserves drop3 function checkHealth() public view returns (bool) {4 (, int256 reserves,,,) = reserveFeed.latestRoundData();5 uint256 ratio = uint256(reserves) * 100 / totalSupply();6 return ratio >= MIN_RESERVE_RATIO; // e.g., 100%7 }89 modifier whenHealthy() {10 require(checkHealth(), "Reserve ratio too low");11 _;12 }1314 function redeem(uint256 amount) external whenHealthy {15 _burn(msg.sender, amount);16 // Release underlying asset17 }18}
RWA Tokens
For tokenized Real World Assets:
1contract RWAToken {2 // PoR verifies physical assets back the tokens3 function verifyBacking() external view returns (bool, string memory) {4 (, int256 assetValue,,,) = porFeed.latestRoundData();5 uint256 tokenValue = totalSupply() * pricePerToken;67 if (uint256(assetValue) >= tokenValue) {8 return (true, "Fully backed");9 } else {10 return (false, "Under-collateralized");11 }12 }13}
Security Considerations
Feed Staleness
PoR feeds may not update in real-time:
1function getReserves() public view returns (uint256) {2 (3 uint80 roundId,4 int256 reserves,5 uint256 startedAt,6 uint256 updatedAt,7 uint80 answeredInRound8 ) = reserveFeed.latestRoundData();910 // Check freshness11 require(block.timestamp - updatedAt < MAX_STALENESS, "Stale PoR data");12 require(reserves > 0, "Invalid reserves");1314 return uint256(reserves);15}
Attestation Trust
For off-chain reserves, you trust the attestor:
- Who performs the audit?
- How often?
- What's their liability?
Flash Loan Considerations
PoR checks should happen atomically with minting:
1// VULNERABLE: Separate check and mint2function checkThenMint(uint256 amount) external {3 require(checkReserves(amount), "Insufficient reserves");4 // Attacker could manipulate reserves here5 _mint(msg.sender, amount);6}78// SECURE: Atomic check9function secureMint(uint256 amount) external {10 (, int256 reserves,,,) = reserveFeed.latestRoundData();11 require(totalSupply() + amount <= uint256(reserves), "Insufficient");12 _mint(msg.sender, amount);13}
Audit Checklist
When auditing Proof of Reserve implementations:
- PoR checked before every mint
- Feed staleness validated
- Atomic check-and-mint pattern
- Reserve ratio thresholds appropriate
- Circuit breakers on under-collateralization
- Feed address immutable or properly governed
- Decimal handling correct
- Trust assumptions documented
Notable PoR Implementations
| Asset | PoR Provider | Reserve Type |
|---|---|---|
| WBTC | Chainlink | Cross-chain BTC |
| USDC | Third-party audits | Bank accounts |
| PAXG | Chainlink | Gold bars |
| stETH | Chainlink | Beacon chain ETH |
Proof of Reserve brings transparency to backed assets, reducing counterparty risk and enabling trustless verification of collateralization—a critical component for stablecoins, wrapped assets, and RWA tokens.
Articles Using This Term
Learn more about Proof of Reserve in these articles:
Related Terms
Oracle
A service that provides external data (prices, events, random numbers) to smart contracts that cannot access off-chain information directly.
Chainlink
The leading decentralized oracle network providing secure, tamper-proof data feeds for smart contracts.
Real World Asset (RWA)
Physical or traditional financial assets tokenized on blockchain, such as real estate, bonds, or commodities.
Need expert guidance on Proof of Reserve?
Our team at Zealynx has deep expertise in blockchain security and DeFi protocols. Whether you need an audit or consultation, we're here to help.
Get a Quote

