# Changelog All notable changes to this project are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ### Changed - `Love`'s constructor no longer takes wETH. It reads it from `WETHRegistry` at a fixed address and reverts with `RegistryNotDeployed` or `WethNotRegistered` if there is nothing to read. The creation code is therefore byte-identical on every chain, so CREATE2 gives LOVE one address everywhere rather than one per wETH deployment — the previous behaviour, where the wETH argument was part of the creation code, is gone. **Breaking:** the deployment interface and the resulting address both change. - `script/Love.s.sol` brings a chain up in three steps — deploy the registry, register wETH, deploy the token — skipping whichever has already happened. `predict()` and `initCode()` no longer take a wETH argument. - `script/multichain-check.sh` now gives its two anvil nodes different wETH implementations at different addresses, which is what makes a matching LOVE address meaningful; it also fails if both nodes end up on the same wETH. - Tests run against real WETH9 runtime bytecode etched from live chains rather than against `MockWETH`, since a mock's codehash is not on the allowlist and adding it would mean testing a different allowlist from the one that ships. `MockWETH` is now the "correct behaviour, wrong bytecode" rejection case. ### Added - `WETHRegistry`, naming the wETH LOVE pegs to on a chain. `register()` is permissionless and payable, takes exactly 1 wei, and accepts a candidate only if its `EXTCODEHASH` is one of ten reviewed wETH implementations and a deposit/withdraw round trip of that wei succeeds. Ownerless, no setter, write-once, so nothing can move the token under a live peg. The allowlist is compile-time, so extending it means publishing a new registry and no key can revoke an entry. The probe wei is kept rather than refunded, so a registrar with no payable fallback can still register. `receive()` reverts outside a probe, keeping the registry from becoming ether it cannot move. - `IWETH`, the narrow wrapper interface the registry probes against. - `script/weth-codehashes.sh` and `script/weth-chains.tsv`, surveying the wETH on 27 chains and grouping them by implementation, so every allowlist entry is reproducible from chain state. The survey found 23 distinct codehashes across those chains, collapsing to 5 implementations over 14 chains once bridged-ETH tokens, upgradeable proxies and non-EVM bytecode are excluded. - `test/fixtures/`, real WETH9 runtime bytecode from Base and Ethereum, with `test/Fixtures.sol` to stage a chain: registry, wETH, registration. - `WETHRegistryTest`, covering both gates, the write-once rule, the exact probe value, ether sent outside a probe, and all ten allowlist entries. - Foundry project scaffolding (`forge-std`, CI workflow, `.gitignore`). - `Love`, an ERC-20 token (`LOVE`, 18 decimals) on OpenZeppelin v5, pegged to wETH at 100000 LOVE per wETH. No mint function and no owner: supply moves only through the permissionless `deposit(uint256)` and `withdraw(uint256)`, so circulating LOVE is always backed by wETH held by the contract. `withdraw` reverts with `AmountNotDivisibleByRate` unless the amount is a multiple of the rate, keeping the peg free of rounding dust. - `MockWETH`, a test-only WETH9 stand-in, and tests covering deposit, withdraw, the divisibility revert, backing invariants, round-trips, transfers, approve/`transferFrom`, reverts and fuzzing. - Deployment script `script/Love.s.sol`, deploying with CREATE2 through the canonical deterministic deployer; salt defaults to `keccak256("LOVE")` and is overridable via `SALT`, the wETH to register defaults to the OP-Stack address and is overridable via `WETH`. Neither contract takes constructor arguments, so both land at the same address on every chain. - `predict()` entrypoint printing the deployment address without broadcasting, and CREATE2 tests pinning address determinism across chain IDs, including that two chains with different wETH still give LOVE one address. - `foundry.toml` with pinned solc 0.8.30, optimizer, fmt rules, fuzz/invariant defaults, and Base Sepolia RPC/Etherscan endpoints driven by env vars. - `script/multichain-check.sh`, deploying `Love` on two local anvil nodes with different chain IDs and failing if the two addresses don't match. - `remappings.txt` for `@openzeppelin/contracts/` and `forge-std/`. - `.env.example` documenting required environment variables, including `WETH`.