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
use alloy::{
    primitives::{Address, Bytes, B256},
    sol_types::SolCall,
};

/// The address of the contract deployer.
pub const CONTRACT_DEPLOYER_ADDRESS: Address = Address::new([
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x80, 0x06,
]);

alloy::sol! {
    /// Function to create a contract.
    function create(bytes32 salt, bytes32 bytecodeHash, bytes memory constructorInput);

    /// Function to create a contract using create2.
    function create2(bytes32 salt, bytes32 bytecodeHash, bytes memory constructorInput);

    /// Event emitted when a contract is deployed.
    event ContractDeployed(
        address indexed deployerAddress,
        bytes32 indexed bytecodeHash,
        address indexed contractAddress
    );
}

/// Encodes the calldata for creating a contract.
///
/// This function encodes the bytecode hash and constructor input into a `Bytes` object
/// for use in contract creation operations using ContractDeployer contract.
///
/// # Arguments
///
/// * `bytecode_hash` - The hash of the contract bytecode.
/// * `constructor_input` - The constructor input data.
///
/// # Returns
///
/// The encoded calldata as `Bytes`.
pub(crate) fn encode_create_calldata(bytecode_hash: B256, constructor_input: Bytes) -> Bytes {
    // The salt parameter is required as per signature but is not used during create
    // See: https://github.com/matter-labs/era-contracts/blob/main/system-contracts/contracts/interfaces/IContractDeployer.sol#L65
    let call = createCall {
        salt: Default::default(),
        bytecodeHash: bytecode_hash,
        constructorInput: constructor_input,
    };

    call.abi_encode().into()
}

/// Encodes the calldata for creating a contract using create2.
///
/// This function encodes the salt, bytecode hash, and constructor input into a `Bytes` object
/// for use in contract creation operations using ContractDeployer contract.
///
/// # Arguments
///
/// * `salt` - The salt value.
/// * `bytecode_hash` - The hash of the contract bytecode.
/// * `constructor_input` - The constructor input data.
///
/// # Returns
///
/// The encoded calldata as `Bytes`.
pub(crate) fn encode_create2_calldata(
    salt: B256,
    bytecode_hash: B256,
    constructor_input: Bytes,
) -> Bytes {
    let call = createCall {
        salt,
        bytecodeHash: bytecode_hash,
        constructorInput: constructor_input,
    };

    call.abi_encode().into()
}