Difference between __init and __init_unchained

Hi. I am developing an upgradeable erc721 and erc1155 smart contract using the transparent proxy pattern. I am having trouble understanding the difference between __init and __init_unchained and what is init_unchianed used for.

For example in the upgradeable smart contract provided by openzeppelin we have

function __ERC1155_init(string memory uri_) internal onlyInitializing {
        __ERC1155_init_unchained(uri_);
    }

function __ERC1155_init_unchained(string memory uri_) internal onlyInitializing {
        _setURI(uri_);
    }

Can someone explain me the difference and working using the above examples?

I think you would normally just use the first one. I remember reading somewhere that the second version is there is to make sure that when initializing certain contracts the initializer is only called once.

The unchained method groups all the logic that would normally be done inside the constructor or at the moment of deployment. And the init one gathers all the logic the constructor header would done. To ilustrate it a bit better, I'll use this other example that contains almost every scenario:

On the ERC20PermitUpgradeable contract we have:
Non upgradeable:

    // solhint-disable-next-line var-name-mixedcase
    bytes32 private immutable _PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");


    constructor(string memory name) EIP712(name, "1") {}

Upgradeable:

 function __ERC20Permit_init(string memory name) internal onlyInitializing {
        __EIP712_init_unchained(name, "1");//////////////This is doing  EIP712(name, "1")
        __ERC20Permit_init_unchained(name);
    }

    function __ERC20Permit_init_unchained(string memory) internal onlyInitializing {
        _PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");}///////////////Since its an empty constructor the only thing it includes is storage variable declarations that would be done at the time of deployment
3 Likes

We have some docs about these functions here:

This thread provides a much more comprehensive explanation of this topic: