Concepts
USD pricing & Chainlink
Pools take ETH and ERC-20s, but minimums are enforced in USD. Here is exactly how.
Why USD, not ETH
Pricing a minimum in ETH means the floor moves with the market — a $5 minimum becomes $20 if ETH triples. Pricing in USD keeps the commitment stable even when the underlying asset swings.
The conversion path
When a funder calls fund() or fundERC20(), the contract reads the latest Chainlink price feed for the asset and converts the incoming amount to its USD equivalent. The conversion happens at the time of the transaction, using the feed snapshot at that block.
// Simplified — see PriceConverter.sol
function getConversionRate(uint256 ethAmount, AggregatorV3Interface feed)
internal view returns (uint256 usdValue)
{
(, int256 answer, , , ) = feed.latestRoundData();
// Chainlink ETH/USD returns 8 decimals. Normalize to 18.
uint256 ethPrice = uint256(answer) * 1e10;
usdValue = (ethPrice * ethAmount) / 1e18;
}Which feeds are used
- ETH/USD — a single Chainlink aggregator passed into the pool constructor. Immutable per pool.
- Each whitelisted ERC-20 — paired with its own Chainlink aggregator and decimals at deploy time (e.g., WBTC/USD for WBTC contributions).
Input parity across the app
Deploy, fund, and withdraw all accept USD inputs. The UI handles the USD→asset conversion before signing. The chain enforces the USD minimum on submit, which means a long wait between quote and confirmation could land a transaction just above or just below the threshold if the asset price moves — the contract is the source of truth.
Edge cases
- Feed outages. If a Chainlink feed stops updating, contributions continue to price against the last answer until the aggregator recovers.
- Decimals mismatch. ERC-20 token decimals are captured at deploy and used to scale the feed answer. If the wrong decimals are passed in, the minimum check will be off by an order of magnitude. This is why token configs are immutable.