Three contracts form the backend of the DEX Dashboard: MockERC20 (token), Faucet (distribution), and MockDEX (trading). All contracts inherit from OpenZeppelin for battle-tested security.
OpenZeppelin-based ERC20 token with mint capability restricted to a designated faucet address. Deployed as three independent instances.
| Token | Symbol | Contract | Decimal |
|---|---|---|---|
| Mock Ethereum | mETH |
MockERC20("Mock ETH", "mETH", faucetAddress) |
18 |
| Mock Bitcoin | mBTC |
MockERC20("Mock BTC", "mBTC", faucetAddress) |
18 |
| Mock USDC | mUSDC |
MockERC20("Mock USDC", "mUSDC", faucetAddress) |
18 |
mint(to, amount) β Only callable by the designated faucet address. Emits TokensMinted event.setFaucet(newFaucet) β onlyOwner. Updates the address authorized to mint.MockERC20__NotFaucet() β Caller is not the faucet addressMockERC20__InvalidFaucet() β Faucet address is zeroTime-locked faucet distributing 10 tokens per claim with an independent 24-hour cooldown per wallet per token. Supports all three mock tokens (mETH, mBTC, mUSDC).
mapping(address => mapping(uint256 => uint256)) lastClaim; // user => tokenIndex => unix timestamp mapping(address => mapping(uint256 => uint256)) lifetimeClaimed; // user => tokenIndex => total tokens claimed uint256 claimAmount; // Default: 10 * 10**18 uint256 cooldown; // Default: 24 hours (86400s) MockERC20[] tokens; // [mETH, mBTC, mUSDC]
claimToken(tokenIndex) β Claims tokens. 0=mETH, 1=mBTC, 2=mUSDC. Reverts if cooldown hasn't elapsed.getClaimInfo(user, tokenIndex) β (canClaim, timeRemaining, totalClaimed, lastClaimTime) β View function for claim eligibility.getTokenCount() β uint256 β Returns number of supported tokens (3).getTokenAddress(tokenIndex) β address β Returns token contract address by index.setClaimAmount(amount) β onlyOwner. Updates tokens per claim.setCooldown(seconds) β onlyOwner. Updates cooldown period.Faucet__CooldownNotElapsed(remaining) β Must wait remaining secondsFaucet__InvalidToken() β Token index out of rangeFaucet__InvalidAddress() β Zero address in constructorFaucet__InvalidClaimAmount() β Claim amount set to zeroFaucet__InvalidCooldown() β Cooldown set to zeroA fixed-ratio DEX supporting 6 swap paths across 3 tokens. Uses a simplified reserve-based model (not a constant product AMM like Uniswap).
IERC20 public immutable mETH; // mETH token contract IERC20 public immutable mBTC; // mBTC token contract IERC20 public immutable mUSDC; // mUSDC token contract uint256 public ethReserve; // Current mETH reserve uint256 public btcReserve; // Current mBTC reserve uint256 public usdcReserve; // Current mUSDC reserve uint256 public ethSwapRate; // mUSDC per 1 mETH (scaled 1e18) uint256 public btcSwapRate; // mUSDC per 1 mBTC (scaled 1e18)
| Direction | Function | Calculation | Reserve Check |
|---|---|---|---|
| mETH β mUSDC | swapETHForUSDC() |
usdcOut = ethIn Γ ethRate / 1e18 |
usdcReserve |
| mUSDC β mETH | swapUSDCForETH() |
ethOut = usdcIn Γ 1e18 / ethRate |
ethReserve |
| mBTC β mUSDC | swapBTCForUSDC() |
usdcOut = btcIn Γ btcRate / 1e18 |
usdcReserve |
| mUSDC β mBTC | swapUSDCForBTC() |
btcOut = usdcIn Γ 1e18 / btcRate |
btcReserve |
| mETH β mBTC | swapETHForBTC() |
usdcValue = ethIn Γ ethRate / 1e18 |
btcReserve |
| mBTC β mETH | swapBTCForETH() |
usdcValue = btcIn Γ btcRate / 1e18 |
ethReserve |
Cross-rate swaps (mETH β mBTC) route through mUSDC internally. For example, swapping mETH β mBTC first converts ETH to USDC value via ethSwapRate, then converts that USDC value to BTC via btcSwapRate.
addLiquidity(ethAmount, btcAmount, usdcAmount) β onlyOwner. Deposits tokens into DEX reserves. Emits LiquidityAdded.getEthRate() β uint256 β Returns current mETHβmUSDC rate.getBtcRate() β uint256 β Returns current mBTCβmUSDC rate.setEthRate(newRate) β onlyOwner. Updates mETH swap rate.setBtcRate(newRate) β onlyOwner. Updates mBTC swap rate.minOutput parameter. If the calculated output is less than the minimum, the transaction reverts with MockDEX__SlippageExceeded(actual, minimum).MockDEX__InsufficientLiquidity() β Not enough tokens in reserveMockDEX__SlippageExceeded(actual, minimum) β Output below minimumMockDEX__ZeroAmount() β Input amount is zeroMockDEX__InvalidAddress() β Zero address in constructorMockDEX__InvalidRate() β Swap rate set to zeroLiquidityAdded(provider, ethAmount, btcAmount, usdcAmount)Swapped(user, fromToken, toToken, amountIn, amountOut)EthRateUpdated(oldRate, newRate)BtcRateUpdated(oldRate, newRate)See the Testing Guide for details on the test suite covering all contracts.