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

add weth peg tests and docs 5376202 · on 5376202c13fb4103a21f603fecc7fd40680b607b · julienbrg · 8h ago
LoveCreate2.t.sol · 89 lines · 3.4 KBSolidity Blame HistoryRaw
 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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;

import {LoveScript} from "../script/Love.s.sol";
import {Love} from "../src/Love.sol";
import {Test} from "forge-std/Test.sol";

/// @notice The deployment address derives from the salt, the creation code and
///         the wETH constructor argument. These tests pin that derivation: same
///         salt and same wETH give the same address on any chain, a different
///         wETH gives a different one.
contract LoveCreate2Test is Test {
    bytes32 constant SALT = keccak256("LOVE");
    address constant WETH = 0x4200000000000000000000000000000000000006;

    LoveScript script;

    function setUp() public {
        script = new LoveScript();

        // The canonical deterministic deployer, as it exists on live networks.
        assertGt(CREATE2_FACTORY.code.length, 0, "create2 deployer missing");
    }

    function test_DeploysAtPredictedAddress() public {
        address predicted = vm.computeCreate2Address(SALT, keccak256(script.initCode(WETH)), CREATE2_FACTORY);

        Love deployed = Love(_deploy(SALT, WETH));

        assertEq(address(deployed), predicted);
        assertEq(deployed.symbol(), "LOVE");
        assertEq(address(deployed.WETH()), WETH);
    }

    /// @dev What the deploy script prints must be what the chain gives back.
    function test_ScriptPredictionMatchesDeployment() public {
        assertEq(script.predict(SALT, WETH), _deploy(SALT, WETH));
    }

    function test_ScriptUsesKeccakOfLoveAsDefaultSalt() public view {
        assertEq(script.DEFAULT_SALT(), SALT);
    }

    function test_ScriptDefaultsToOpStackWeth() public view {
        assertEq(script.DEFAULT_WETH(), WETH);
    }

    /// @dev Same salt, same code, same wETH, same address.
    function test_PredictionIsChainAgnostic() public {
        address onThisChain = script.predict(SALT, WETH);

        vm.chainId(137);
        assertEq(script.predict(SALT, WETH), onThisChain);

        vm.chainId(42_161);
        assertEq(script.predict(SALT, WETH), onThisChain);
    }

    function test_DifferentSaltsGiveDifferentAddresses() public view {
        assertTrue(script.predict(SALT, WETH) != script.predict(keccak256("LOVE2"), WETH));
    }

    /// @dev The wETH address is part of the creation code, so chains with their
    ///      own wETH get their own token address.
    function test_DifferentWethGivesDifferentAddress() public view {
        assertTrue(script.predict(SALT, WETH) != script.predict(SALT, address(0xBEEF)));
    }

    /// @dev Redeploying with the same salt must fail, not silently return the
    ///      existing token.
    function test_RevertWhen_RedeployingWithSameSalt() public {
        _deploy(SALT, WETH);

        (bool ok,) = CREATE2_FACTORY.call(abi.encodePacked(SALT, script.initCode(WETH)));
        assertFalse(ok);
    }

    function testFuzz_PredictionMatchesDeployment(bytes32 salt, address weth) public {
        assertEq(script.predict(salt, weth), _deploy(salt, weth));
    }

    function _deploy(bytes32 salt, address weth) internal returns (address deployed) {
        (bool ok, bytes memory ret) = CREATE2_FACTORY.call(abi.encodePacked(salt, script.initCode(weth)));
        require(ok, "create2 deployment failed");
        // casting to 'bytes20' is safe because the deployer returns the 20-byte address, raw
        // forge-lint: disable-next-line(unsafe-typecast)
        deployed = address(bytes20(ret));
    }
}