julien/lovepublic Fork 0
a34c2e887f1d3af813774b021d2c9bfc47d4ac10
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.

Love.s.sol · 188 lines · 7.8 KBSolidity Blame HistoryRaw
add love contract 9bf25a7 julienbrg 11h ago1// SPDX-License-Identifier: MIT
2pragma solidity ^0.8.30;
3
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago4import {IWETH} from "../src/IWETH.sol";
add love contract 9bf25a7 julienbrg 11h ago5import {Love} from "../src/Love.sol";
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago6import {WETHRegistry} from "../src/WETHRegistry.sol";
add love contract 9bf25a7 julienbrg 11h ago7import {Script, console} from "forge-std/Script.sol";
8
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago9/// @title LoveScript
10/// @author Julien Béranger
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago11/// @notice Brings LOVE up on a chain, in the order the design requires:
12/// registry first, wETH registered second, token third.
13/// @dev Both contracts go through the canonical deterministic deployer and
14/// neither takes constructor arguments, so their creation code is
15/// identical on every chain and so are their addresses. That is the whole
16/// point — LOVE is one address everywhere, not one per wETH deployment.
17/// Keep `solc`, the optimizer settings and `bytecode_hash = "none"` as
18/// they are in `foundry.toml`, or both addresses move.
add love contract 9bf25a7 julienbrg 11h ago19contract LoveScript is Script {
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago20 /// @notice Salt used for `Love` when `SALT` is not set in the environment.
Merge 1-add-main-logic into main dded29a rickub 10h ago21 bytes32 public constant DEFAULT_SALT = keccak256("LOVE");
22
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago23 /// @notice Salt the registry is deployed with. Not configurable: `Love`
24 /// has the resulting address compiled into it.
25 bytes32 public constant REGISTRY_SALT = keccak256("LOVE.WETHRegistry");
26
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago27 /// @notice wETH address used when `WETH` is not set in the environment.
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago28 /// @dev The OP Stack predeploy, which is where wETH sits on Optimism,
29 /// Base, Mode, Zora, Lisk, World Chain, Unichain, Soneium and Ink.
30 /// Chains outside that set need `WETH` set explicitly.
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago31 address public constant DEFAULT_WETH = 0x4200000000000000000000000000000000000006;
32
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago33 /// @notice The registry, once `run()` has deployed or found it.
34 WETHRegistry public registry;
35
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago36 /// @notice The token, once `run()` has deployed or found it.
add love contract 9bf25a7 julienbrg 11h ago37 Love public love;
38
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago39 /// @notice Deploy the registry, register wETH and deploy the token,
40 /// skipping whichever of those has already happened.
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago41 /// @dev Reads `SALT` and `WETH` from the environment, falling back to the
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago42 /// defaults, and asserts both deployments match their predictions.
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago43 /// @return The deployed token.
Merge 1-add-main-logic into main dded29a rickub 10h ago44 function run() public returns (Love) {
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago45 address w = wethAddress();
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago46 address predictedRegistry = registryAddress();
47 address predicted = predict(salt());
Merge 1-add-main-logic into main dded29a rickub 10h ago48
49 console.log("deployer ", CREATE2_FACTORY);
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago50 console.log("registry ", predictedRegistry);
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago51 console.log("weth ", w);
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago52 console.log("salt ", vm.toString(salt()));
53 console.log("initCodeHash ", vm.toString(initCodeHash()));
Merge 1-add-main-logic into main dded29a rickub 10h ago54 console.log("predicted ", predicted);
55
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago56 _ensureRegistry(predictedRegistry);
57 _ensureRegistered(IWETH(w));
58 _ensureLove(predicted);
add love contract 9bf25a7 julienbrg 11h ago59
Merge 1-add-main-logic into main dded29a rickub 10h ago60 return love;
61 }
62
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago63 /// @notice Print what `run()` would deploy, without broadcasting.
64 /// @return predicted The address the current salt derives to.
Merge 1-add-main-logic into main dded29a rickub 10h ago65 function predict() public view returns (address predicted) {
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago66 predicted = predict(salt());
Merge 1-add-main-logic into main dded29a rickub 10h ago67
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago68 console.log("registry ", registryAddress());
69 console.log("weth ", wethAddress());
70 console.log("salt ", vm.toString(salt()));
71 console.log("initCodeHash ", vm.toString(initCodeHash()));
Merge 1-add-main-logic into main dded29a rickub 10h ago72 console.log("predicted ", predicted);
73 }
74
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago75 /// @notice Derive the token's deployment address from a salt.
76 /// @dev Takes no wETH argument, unlike the address derivation this
77 /// replaces: wETH is no longer in the creation code, which is why the
78 /// answer is the same on every chain.
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago79 /// @param s The CREATE2 salt.
80 /// @return The address `Love` would land at.
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago81 function predict(bytes32 s) public pure returns (address) {
82 return vm.computeCreate2Address(s, initCodeHash(), CREATE2_FACTORY);
83 }
84
85 /// @notice The address the registry lands at on every chain.
86 /// @return The registry's CREATE2 address.
87 function registryAddress() public pure returns (address) {
88 return vm.computeCreate2Address(REGISTRY_SALT, keccak256(registryInitCode()), CREATE2_FACTORY);
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago89 }
90
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago91 /// @notice The token's creation code, which now carries no arguments.
92 /// @return The creation code handed to CREATE2.
93 function initCode() public pure returns (bytes memory) {
94 return type(Love).creationCode;
Merge 1-add-main-logic into main dded29a rickub 10h ago95 }
96
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago97 /// @notice Hash of the token's creation code.
98 /// @return The keccak256 of `initCode()`.
99 function initCodeHash() public pure returns (bytes32) {
100 return keccak256(initCode());
Merge 1-add-main-logic into main dded29a rickub 10h ago101 }
102
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago103 /// @notice The registry's creation code.
104 /// @return The creation code handed to CREATE2.
105 function registryInitCode() public pure returns (bytes memory) {
106 return type(WETHRegistry).creationCode;
107 }
108
109 /// @notice The salt to deploy the token with.
110 /// @dev `SALT` overrides the default, e.g. to mine a vanity address or to
111 /// route around a chain where the registry has been squatted.
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago112 /// @return The configured salt, or `DEFAULT_SALT`.
Merge 1-add-main-logic into main dded29a rickub 10h ago113 function salt() public view returns (bytes32) {
114 return vm.envOr("SALT", DEFAULT_SALT);
add love contract 9bf25a7 julienbrg 11h ago115 }
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago116
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago117 /// @notice The wETH address to register on this chain.
118 /// @dev `WETH` overrides the default, which only holds on OP Stack chains.
119 /// Ignored once a wETH is already registered.
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago120 /// @return The configured wETH address, or `DEFAULT_WETH`.
121 function wethAddress() public view returns (address) {
122 return vm.envOr("WETH", DEFAULT_WETH);
123 }
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago124
125 /// @dev Deploys the registry unless it is already there.
126 /// @param predicted Where it should land.
127 function _ensureRegistry(address predicted) private {
128 if (predicted.code.length > 0) {
129 console.log("registry already deployed");
130 registry = WETHRegistry(payable(predicted));
131 return;
132 }
133
134 vm.startBroadcast();
135 registry = new WETHRegistry{salt: REGISTRY_SALT}();
136 vm.stopBroadcast();
137
138 require(address(registry) == predicted, "LoveScript: registry address mismatch");
139 console.log("registry deployed at", address(registry));
140 }
141
142 /// @dev Registers `candidate` unless a wETH is already registered. Reverts
143 /// inside the registry if the candidate's code is not a reviewed wETH
144 /// — which is the intended outcome on a chain whose wETH has not been
145 /// reviewed, not a script failure to work around.
146 /// @param candidate The wETH to register.
147 function _ensureRegistered(IWETH candidate) private {
148 IWETH registered = registry.weth();
149
150 if (address(registered) != address(0)) {
151 console.log("weth already registered", address(registered));
152 require(
153 address(registered) == address(candidate) || address(candidate) == DEFAULT_WETH,
154 "LoveScript: a different weth is registered on this chain"
155 );
156 return;
157 }
158
159 vm.startBroadcast();
160 registry.register{value: registry.PROBE()}(candidate);
161 vm.stopBroadcast();
162
163 console.log("weth registered", address(registry.weth()));
164 }
165
166 /// @dev Deploys the token unless it is already there.
167 /// @param predicted Where it should land.
168 function _ensureLove(address predicted) private {
169 if (predicted.code.length > 0) {
170 console.log("already deployed, nothing to do");
171 love = Love(predicted);
172 return;
173 }
174
175 vm.startBroadcast();
176 love = new Love{salt: salt()}();
177 vm.stopBroadcast();
178
179 require(address(love) == predicted, "LoveScript: address mismatch");
180
181 console.log("Love deployed at", address(love));
182 console.log("name ", love.name());
183 console.log("symbol ", love.symbol());
184 console.log("weth ", address(love.WETH()));
185 console.log("rate ", love.RATE());
186 console.log("totalSupply ", love.totalSupply());
187 }
add love contract 9bf25a7 julienbrg 11h ago188}