Every Ethereum transaction costs gas, denominated in ETH. Simple enough—until you try to explain it to someone who doesn’t hold ETH.
“You need to buy this volatile cryptocurrency to pay fees on the network, then watch your fee estimate change based on that cryptocurrency’s price, network congestion, and opaque gas limit settings.”
Signet uses USD as its native currency. Gas is priced in dollars. Balances are in dollars. No conversion math. No volatility anxiety.
The Cost of ETH Denomination
On Ethereum and most rollups, users face compounding complexity. They need to acquire ETH just to pay fees — even if they only want stablecoins. Gas estimates are denominated in a unit that means nothing to most people, and prices fluctuate between when you check and when you submit. Fee estimation is imprecise enough that users routinely overpay or underpay. And when your ETH balance drops below the fee threshold, you’re stuck.
DeFi protocols build elaborate workarounds: gas tokens, fee abstraction, paymasters. All to paper over a fundamental UX problem.
Gas in Dollars
On Signet, the native currency is USD with 18 decimals:
// Check your balance — returns USD, not ETH
uint256 balance = address(this).balance;
// Transfer value — sends USD
payable(recipient).transfer(100e18); // 100 USD
// Receive payment — msg.value is USD
receive() external payable {
require(msg.value >= 10e18, "Minimum 10 USD");
}No wrappers. No conversions. msg.value is dollars. Gas costs are dollars. Your wallet shows dollars. ETH lives on L1; you hold USD on Signet.
What Changes
Gas fees are denominated in USD — a transaction that costs $0.02 today costs $0.02 tomorrow (network congestion aside). No checking ETH price before transacting. Users deposit ETH or USDC via Passage and receive USD on Signet, giving them one asset for everything: fees, transfers, DeFi.
Applications tracking costs, revenue, or user balances get everything in dollars — no price feed lookups, no conversion at time of transaction, no reconciliation. Wallets show “$0.02 fee” instead of “0.000008 ETH (~$0.02)”.
How It Works
Signet’s execution layer prices gas in USD and accepts USD for payment. Block producers accept USD for inclusion, the protocol burns USD to pay for execution, and users see USD deducted from their balance.
This isn’t fee abstraction or a paymaster contract. USD is the actual native currency of the chain, just as ETH is native to Ethereum.
Same Semantics, Different Unit
If you’re porting an Ethereum contract, the semantics are identical:
// Works exactly as expected
function purchase() external payable {
require(msg.value >= price, "Insufficient payment");
_mint(msg.sender, 1);
payable(treasury).transfer(msg.value);
}Only the unit changes. msg.value is USD instead of ETH. Everything else—transfer, send, call with value—works exactly as expected.
Getting USD
Users enter Signet by depositing via Passage:
// On Ethereum: deposit 1 ETH → receive USD on Signet at market rate
IPassage(PASSAGE).enter{value: 1 ether}(recipient);
// On Ethereum: deposit 1000 USDC → receive 1000 USD on Signet
IERC20(USDC).approve(PASSAGE, 1000e6);
IPassage(PASSAGE).enterToken(recipient, USDC, 1000e6);ETH converts to USD at the current market rate. Stablecoins convert 1:1.
Wrapped USD
For protocols that need an ERC-20 representation:
// WUSD address on Signet
address constant WUSD = 0x0000000000000000007369676e65742D77757364;
// Wrap native USD → WUSD (ERC-20)
IWUSD(WUSD).deposit{value: 100e18}();
// Unwrap WUSD → native USD
IWUSD(WUSD).withdraw(100e18);Same pattern as WETH on Ethereum.
Get Started
- Parmigiana Testnet — USD-native from day one
- Passage and Transactor — How to deposit
Questions? Get in touch.