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.

LoveCreate2.t.sol · 175 lines · 7.0 KBSolidity Blame HistoryRaw
Merge 1-add-main-logic into main dded29a rickub 5h ago1// SPDX-License-Identifier: MIT
2pragma solidity ^0.8.30;
3
4import {LoveScript} from "../script/Love.s.sol";
5import {Love} from "../src/Love.sol";
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago6import {Fixtures} from "./Fixtures.sol";
Merge 1-add-main-logic into main dded29a rickub 5h ago7import {Test} from "forge-std/Test.sol";
8
Merge 3-peg-love-to-weth into main ce13509 rickub 4h ago9/// @title LoveCreate2Test
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago10/// @notice The deployment address now derives from the salt and the creation
11/// code alone. wETH used to be a constructor argument and so part of
12/// that creation code, which gave the token a different address on
13/// every chain whose wETH sat elsewhere; it is read from the registry
14/// instead. These tests pin the consequence: same salt, same address,
15/// on any chain, whatever its wETH is and wherever it lives.
16contract LoveCreate2Test is Test, Fixtures {
Merge 1-add-main-logic into main dded29a rickub 5h ago17 bytes32 constant SALT = keccak256("LOVE");
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago18 address constant OP_STACK_WETH = 0x4200000000000000000000000000000000000006;
19 address constant MAINNET_WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
Merge 1-add-main-logic into main dded29a rickub 5h ago20
21 LoveScript script;
22
23 function setUp() public {
24 script = new LoveScript();
25
26 // The canonical deterministic deployer, as it exists on live networks.
27 assertGt(CREATE2_FACTORY.code.length, 0, "create2 deployer missing");
28 }
29
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago30 /*//////////////////////////////////////////////////////////////
31 THE REGISTRY
32 //////////////////////////////////////////////////////////////*/
33
34 /// @dev `Love` has the registry's address compiled in, so if the registry's
35 /// creation code moves — an edit to the contract, a solc bump, a
36 /// change of optimizer settings — this fails rather than shipping a
37 /// token pointing at an empty address.
38 function test_LoveRegistryConstantMatchesDeterministicAddress() public {
39 setUpChain(OP_STACK_WETH, WETH9_OP_LEGACY);
40
41 assertEq(new Love().REGISTRY(), script.registryAddress());
42 }
43
44 function test_RegistryLandsAtTheAddressLoveExpects() public {
45 assertEq(address(deployRegistry()), script.registryAddress());
46 }
47
48 /// @dev The registry takes no constructor arguments, which is what makes
49 /// its address the same everywhere.
50 function test_RegistryAddressIsChainAgnostic() public {
51 address onThisChain = script.registryAddress();
52
53 vm.chainId(137);
54 assertEq(script.registryAddress(), onThisChain);
55
56 vm.chainId(42_161);
57 assertEq(script.registryAddress(), onThisChain);
58 }
59
60 /*//////////////////////////////////////////////////////////////
61 THE DERIVATION
62 //////////////////////////////////////////////////////////////*/
63
Merge 1-add-main-logic into main dded29a rickub 5h ago64 function test_DeploysAtPredictedAddress() public {
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago65 setUpChain(OP_STACK_WETH, WETH9_OP_LEGACY);
Merge 1-add-main-logic into main dded29a rickub 5h ago66
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago67 address predicted = vm.computeCreate2Address(SALT, keccak256(script.initCode()), CREATE2_FACTORY);
68 Love deployed = Love(_deploy(SALT));
Merge 1-add-main-logic into main dded29a rickub 5h ago69
70 assertEq(address(deployed), predicted);
71 assertEq(deployed.symbol(), "LOVE");
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago72 assertEq(address(deployed.WETH()), OP_STACK_WETH);
Merge 1-add-main-logic into main dded29a rickub 5h ago73 }
74
75 /// @dev What the deploy script prints must be what the chain gives back.
76 function test_ScriptPredictionMatchesDeployment() public {
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago77 setUpChain(OP_STACK_WETH, WETH9_OP_LEGACY);
78
79 assertEq(script.predict(SALT), _deploy(SALT));
Merge 1-add-main-logic into main dded29a rickub 5h ago80 }
81
82 function test_ScriptUsesKeccakOfLoveAsDefaultSalt() public view {
83 assertEq(script.DEFAULT_SALT(), SALT);
84 }
85
Merge 3-peg-love-to-weth into main ce13509 rickub 4h ago86 function test_ScriptDefaultsToOpStackWeth() public view {
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago87 assertEq(script.DEFAULT_WETH(), OP_STACK_WETH);
Merge 3-peg-love-to-weth into main ce13509 rickub 4h ago88 }
89
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago90 /// @dev Same salt, same code, same address — and unlike before, no wETH
91 /// argument that could make the answer differ.
Merge 1-add-main-logic into main dded29a rickub 5h ago92 function test_PredictionIsChainAgnostic() public {
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago93 address onThisChain = script.predict(SALT);
Merge 1-add-main-logic into main dded29a rickub 5h ago94
95 vm.chainId(137);
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago96 assertEq(script.predict(SALT), onThisChain);
Merge 1-add-main-logic into main dded29a rickub 5h ago97
98 vm.chainId(42_161);
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago99 assertEq(script.predict(SALT), onThisChain);
Merge 1-add-main-logic into main dded29a rickub 5h ago100 }
101
102 function test_DifferentSaltsGiveDifferentAddresses() public view {
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago103 assertTrue(script.predict(SALT) != script.predict(keccak256("LOVE2")));
Merge 3-peg-love-to-weth into main ce13509 rickub 4h ago104 }
105
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago106 /*//////////////////////////////////////////////////////////////
107 THE POINT OF ALL THIS
108 //////////////////////////////////////////////////////////////*/
109
110 /// @dev The test that replaces `test_DifferentWethGivesDifferentAddress`.
111 /// Two chains, two different wETH implementations at two different
112 /// addresses, one LOVE address. This is what the registry buys.
113 function test_SameAddressOnChainsWithDifferentWeth() public {
114 // A snapshot stands in for a second chain. Etching the code away is
115 // not enough: a deployed account keeps its nonce, and CREATE2 refuses
116 // to build over that, so the registry could never be redeployed.
117 uint256 freshChain = vm.snapshotState();
118
119 setUpChain(OP_STACK_WETH, WETH9_OP_LEGACY);
120 address onOpStack = _deploy(SALT);
121 assertEq(address(Love(onOpStack).WETH()), OP_STACK_WETH);
122
123 vm.revertToState(freshChain);
124
125 // Different chain id, a different wETH implementation, at a different
126 // address.
127 vm.chainId(1);
128 setUpChain(MAINNET_WETH, WETH9_CANONICAL);
129 address onMainnet = _deploy(SALT);
130 assertEq(address(Love(onMainnet).WETH()), MAINNET_WETH);
131
132 assertEq(onOpStack, onMainnet, "LOVE must land at one address on both chains");
Merge 1-add-main-logic into main dded29a rickub 5h ago133 }
134
135 /// @dev Redeploying with the same salt must fail, not silently return the
136 /// existing token.
137 function test_RevertWhen_RedeployingWithSameSalt() public {
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago138 setUpChain(OP_STACK_WETH, WETH9_OP_LEGACY);
139 _deploy(SALT);
Merge 1-add-main-logic into main dded29a rickub 5h ago140
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago141 (bool ok,) = CREATE2_FACTORY.call(abi.encodePacked(SALT, script.initCode()));
Merge 1-add-main-logic into main dded29a rickub 5h ago142 assertFalse(ok);
143 }
144
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago145 function testFuzz_PredictionMatchesDeployment(bytes32 salt) public {
146 setUpChain(OP_STACK_WETH, WETH9_OP_LEGACY);
147
148 assertEq(script.predict(salt), _deploy(salt));
149 }
150
151 /*//////////////////////////////////////////////////////////////
152 CONSTRUCTOR GUARDS
153 //////////////////////////////////////////////////////////////*/
154
155 function test_RevertWhen_RegistryNotDeployed() public {
156 vm.expectRevert(abi.encodeWithSelector(Love.RegistryNotDeployed.selector, script.registryAddress()));
157 new Love();
158 }
159
160 function test_RevertWhen_WethNotRegistered() public {
161 deployRegistry();
162
163 vm.expectRevert(abi.encodeWithSelector(Love.WethNotRegistered.selector, script.registryAddress()));
164 new Love();
Merge 1-add-main-logic into main dded29a rickub 5h ago165 }
166
Merge 3-peg-love-to-weth into main ce13509 rickub 4h ago167 /// @dev Deploys through the canonical deterministic deployer, as the script does.
Merge 5-weth-bytecode-verification into main 2f6da5e rickub 3h ago168 function _deploy(bytes32 salt) internal returns (address deployed) {
169 (bool ok, bytes memory ret) = CREATE2_FACTORY.call(abi.encodePacked(salt, script.initCode()));
Merge 1-add-main-logic into main dded29a rickub 5h ago170 require(ok, "create2 deployment failed");
171 // casting to 'bytes20' is safe because the deployer returns the 20-byte address, raw
172 // forge-lint: disable-next-line(unsafe-typecast)
173 deployed = address(bytes20(ret));
174 }
175}