9

I am forking the Sushiswap Exchange code for educational purposes, and I have come across a variable in the code called INIT_CODE_HASH. I am struggling to understand exactly how this variable works, and how it is used in the various DeFi platforms.

My limited understanding is that INIT_CODE_HASH is used to verify which function of a contract a caller is calling, by using the hash of the init code (Not really sure what the init code is). For some reason I don't quite understand, this is both for security and efficiency purposes.

My Question:

What is INIT_CODE_HASH, and how is it calculated / used?

3 Answers 3

5

https://www.codegrepper.com/code-examples/javascript/calculate+init+code+hash+nodejs

This shows how it's used with COMPUTED_INIT_CODE_HASH (https://www.codegrepper.com/code-examples/javascript/calculate+init+code+hash+nodejs):

import { INIT_CODE_HASH } from '../src/constants'

import { bytecode } from '@uniswap/v2-core/build/UniswapV2Pair.json'
import { keccak256 } from '@ethersproject/solidity'

const COMPUTED_INIT_CODE_HASH = keccak256(['bytes'], [`0x${bytecode}`])
4

INIT_CODE_HASH is a hash of the initcode of a contract. The initcode is the code that creates the bytecode that is stored on-chain. You can read more about the types of bytecode here.

Most dapps, including Sushiswap, use this variable to create a new contract with create2. When a dapp wants to create a contract with a known address, they will use the create2 opcode, which uses the hashed initcode as a parameter. The EIP for it is here.

You can see that Sushiswap uses it in this getCreate2Address address:

[tokens[1].address]: getCreate2Address(
            FACTORY_ADDRESS,
            keccak256(['bytes'], [pack(['address', 'address'], [tokens[0].address, tokens[1].address])]),
            INIT_CODE_HASH
          )
0

anyone have a good idea how the INIT_CODE_HASH value is calculated to begin with? AI's seem to think its a hash of the deployed pool(s) bytecode.

I am deploying mocks of the [v3] factory, NonfungiblePositionManager, and Pool contracts. This involves some slight modifications of the contracts -- a thing that will likely alter theresulting abi and bytecode of the deployed pools, so I need a different INIT_CODE_HASH in order to replicate these pool addresses deterministically. For sure 'computeAddress' in the PoolAddress.sol library is not giving me the address of my deployed pool contracts.

I've tried AI's suggestions of hashing the bytecode of the deployed pool contract (i also tried inputing the mock factory address), using this as the value of INIT_CODE_HASH, then using this as a means to compute/ replicate the pool address(s). So far it does not work. The code for this [i.e. a mock version of PoolAddress.sol] is,

    // SPDX-License-Identifier: GPL-2.0-or-later
    pragma solidity 0.7.6;
    pragma abicoder v2;
    
    contract ComputePoolAddress {

        // get bytecode of deployed pool, or any other contract
        function getContractByteCode(address _addr) public view returns (bytes memory) {
           uint length;
           assembly {
               length := extcodesize(_addr)
           }
           bytes memory bytecode = new bytes(length);
           assembly {
               extcodecopy(_addr, add(bytecode, 0x20), 0, length)
           }
           return bytecode;
       }
    
        // compute hash of bytecode
       function computePoolInitCodeHash(address _contractAddress) public view returns (bytes32) {
           // Get the bytecode of the pool contract
           bytes memory poolBytecode = getContractByteCode(_contractAddress);
    
           // Compute the keccak256 hash of the bytecode
           bytes32 hash = keccak256(poolBytecode);
           
           return hash;
       }
    
        // compute [replicate] deployed pool address deterministically
        function computeAddress(address factory,
                                address token0,
                                address token1,
                                uint24 fee,
                                address contract_) 
                                public view returns (address pool) 
        {
            require(token0 < token1, "token1 > token0");
            bytes32 POOL_INIT_CODE_HASH = computePoolInitCodeHash(contract_);
            pool = address(
                uint256(
                    keccak256(
                        abi.encodePacked(
                            hex'ff',
                            factory,
                            keccak256(abi.encode(token0, token1, fee)),
                            POOL_INIT_CODE_HASH
                            )
                        )
                    )
                );
            }
    
  • note that compiling this with pragma solidity 0.8.0 or higher will cause errors because of casting an address to a uint256 }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.