In Solidity, clones with immutable arguments are a technique used to create lightweight, efficient instances of contracts, often referred to as "clones" or "minimal proxies." This approach leverages the EIP-1167 standard for minimal proxy contracts, which allows for the deployment of multiple instances of a contract with minimal overhead in terms of gas costs and deployment complexity. In smart contract development, proxy contracts delegate calls to implementation contracts, allowing for upgradability and flexibility. By embedding immutable arguments directly into the proxy's bytecode, developers can avoid the high gas costs associated with storage operations.

Immutable Arguments in Proxies

Traditionally, proxy contracts that need to be parametrizable require storage to hold these parameters. Storage operations in Ethereum are costly because writing to and reading from storage consumes a significant amount of gas. To mitigate these costs, the concept of clones with immutable arguments was introduced. These immutable arguments are encoded directly into the proxy contract's bytecode during deployment.

However, understanding how these immutable arguments are utilized is essential. Typically, the proxy contract acts as a middleman, forwarding calls to an implementation contract. When forwarding a call, the proxy appends the immutable arguments to the call data. This way, the implementation contract receives the necessary parameters along with the function call, allowing it to execute the desired functionality based on these arguments.

Mechanism of Immutable Arguments

When a proxy contract is created with immutable arguments, these arguments are stored in the proxy contract. When the proxy contract is called, it caches these immutable arguments to memory and then appends them to the end of the calldata. This is more gas-efficient because reading from calldata is cheaper than accessing storage.

The implementation contract can access these parameters directly from the call's input data without needing additional storage reads.

There is also a sneaky vulnerability with this pattern when it comes to delegate-calling from an implementation address, you can read more here: