julien/lovepublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/julien/love.git
git clone ssh://git@rickub.com/julien/love.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Merge 5-weth-bytecode-verification into main 2f6da5e · on main · rickub · 39m ago
README.md · 93 lines · 3.0 KBmarkdown
Blame HistoryOpen raw

Love

The official LOVE token.

Install

forge install
cp .env.example .env

Build & test

forge build            # compile
forge test             # run tests
forge test -vvv        # with traces
forge fmt              # format
anvil                  # local node

How wETH is chosen

LOVE is pegged to wETH, and that wETH is not a constructor argument. It is read
at construction time from WETHRegistry, which accepts an address only if its
EXTCODEHASH is one of ten reviewed wETH implementations and it survives a
one-wei deposit/withdraw round trip. Registration is permissionless, ownerless
and write-once.

Two things follow. A LOVE instance can never be bound to a typo, a lookalike
ERC-20 or an unreviewed wrapper. And because wETH is no longer in the creation
code, the creation code is byte-identical everywhere, so CREATE2 gives LOVE one
address on every chain instead of one per wETH deployment.

The allowlist covers 14 chains across 5 implementations. Deployment is blocked
elsewhere, on purpose: the remaining chains either carry bridged ETH with no
deposit()/withdraw(), or put wETH behind an upgradeable proxy, where a
codehash commits to a forwarder rather than to behaviour. To re-derive the list
from chain state:

./script/weth-codehashes.sh

One caveat worth knowing before you trust an instance: the gate proves a
candidate is a reviewed wETH implementation, not that it is the wETH a
chain's ecosystem uses. Anyone can deploy a fresh WETH9 copy — same bytecode,
no liquidity — and register it first. Nothing is stealable, since it is real
WETH9 and fully redeemable, but check WETH() against the chain's canonical
address before treating a deployment as the real one.

Deploy

Deployment uses CREATE2, so the token has the same address on every EVM network.
Bringing up a chain is registry, then registration, then token — run() does
all three and skips whichever has already happened.

forge script script/Love.s.sol:LoveScript --sig 'predict()'   # print the address

WETH=0x4200000000000000000000000000000000000006 \
forge script script/Love.s.sol:LoveScript \
  --rpc-url base_sepolia \
  --account "$DEPLOYER_ACCOUNT" \
  --broadcast \
  --verify

WETH defaults to the OP Stack predeploy and is ignored once a wETH is
registered. Registration sends 1 wei, which stays in the registry.

To check determinism for real, deploy on two local chains and compare:

./script/multichain-check.sh

It starts two anvil nodes (chain IDs 31337 and 31338), gives them different
wETH implementations at different addresses, brings both up, and exits
non-zero if the two LOVE addresses differ. Override PORT_A, PORT_B,
CHAIN_ID_A, CHAIN_ID_B or SALT as needed.

License

GPL-3.0

Contact

Julien Béranger (GitHub)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# Love

The official LOVE token.

## Install

```shell
forge install
cp .env.example .env
```

## Build & test

```shell
forge build            # compile
forge test             # run tests
forge test -vvv        # with traces
forge fmt              # format
anvil                  # local node
```

## How wETH is chosen

LOVE is pegged to wETH, and that wETH is not a constructor argument. It is read
at construction time from `WETHRegistry`, which accepts an address only if its
`EXTCODEHASH` is one of ten reviewed wETH implementations *and* it survives a
one-wei deposit/withdraw round trip. Registration is permissionless, ownerless
and write-once.

Two things follow. A LOVE instance can never be bound to a typo, a lookalike
ERC-20 or an unreviewed wrapper. And because wETH is no longer in the creation
code, the creation code is byte-identical everywhere, so CREATE2 gives LOVE one
address on every chain instead of one per wETH deployment.

The allowlist covers 14 chains across 5 implementations. Deployment is blocked
elsewhere, on purpose: the remaining chains either carry bridged ETH with no
`deposit()`/`withdraw()`, or put wETH behind an upgradeable proxy, where a
codehash commits to a forwarder rather than to behaviour. To re-derive the list
from chain state:

```shell
./script/weth-codehashes.sh
```

One caveat worth knowing before you trust an instance: the gate proves a
candidate *is* a reviewed wETH implementation, not that it is *the* wETH a
chain's ecosystem uses. Anyone can deploy a fresh WETH9 copy — same bytecode,
no liquidity — and register it first. Nothing is stealable, since it is real
WETH9 and fully redeemable, but check `WETH()` against the chain's canonical
address before treating a deployment as the real one.

## Deploy

Deployment uses CREATE2, so the token has the same address on every EVM network.
Bringing up a chain is registry, then registration, then token — `run()` does
all three and skips whichever has already happened.

```shell
forge script script/Love.s.sol:LoveScript --sig 'predict()'   # print the address

WETH=0x4200000000000000000000000000000000000006 \
forge script script/Love.s.sol:LoveScript \
  --rpc-url base_sepolia \
  --account "$DEPLOYER_ACCOUNT" \
  --broadcast \
  --verify
```

`WETH` defaults to the OP Stack predeploy and is ignored once a wETH is
registered. Registration sends 1 wei, which stays in the registry.

To check determinism for real, deploy on two local chains and compare:

```shell
./script/multichain-check.sh
```

It starts two anvil nodes (chain IDs 31337 and 31338), gives them *different*
wETH implementations at *different* addresses, brings both up, and exits
non-zero if the two LOVE addresses differ. Override `PORT_A`, `PORT_B`,
`CHAIN_ID_A`, `CHAIN_ID_B` or `SALT` as needed.

## License

GPL-3.0

## Contact

**Julien Béranger** ([GitHub](https://github.com/julienbrg))

- Element: [@julienbrg:matrix.org](https://matrix.to/#/@julienbrg:matrix.org)
- Farcaster: [julien-](https://warpcast.com/julien-)
- Telegram: [@julienbrg](https://t.me/julienbrg)