7

I was scrolling around Ethereum StackExchange and I came across with an interesting thought that I have never read or seen anyone talk about. I'm perfectly aware of how contracts work and are compiled, generating the ABI and Bytecode. I was thinking, is there a way to store the ABI struct and Bytecode (the outputs of the compilation) as variables inside the smart contract itself?

I drew a scheme in a paper, and it seems that I end up on a paradigm of "who comes first, the chicken or the egg?". Because to get the ABI and Bytecode, I need the compilation to occur... and for the compilation to occur, I would need the ABI and bytecode stored in variables previously. So My conclusion is that this ain't possible to do. I searched a bit and couldn't find anything about this. Did anyone ever ask this? Any idea if this is actually achievable?

4 Answers 4

4

Unfortunately, you cannot store the deploying contract's bytecode as a variable in the contract directly, as that creates a circular reference. From the docs:

This property can not be accessed in the contract itself or any derived contract. It causes the bytecode to be included in the bytecode of the call site and thus circular references like that are not possible.

One thing you can do is get the bytecode (either the creationCode or the runtimeCode) from an imported (but not inherited) contract using type(C).creationCode and type(C).runtimeCode, respectively (see the differences here). We actually do this with Authereum contracts since we use create2 to deploy a contract for each new user.

3

You can use ERC930 Eterenal Storage pattern in contract design, through which you can be use to write up-gradable contract by separating your contract's storage and business logic.

I can came something what are you expecting to do (correct me if i'm wrong) in RocketPool's smart contract .

2

You could store them in variables. Doing so would provide no assurance of fidelity with the actual contract as would rely on the deployment ceremony doing it honestly. Another issue is you would have to convert the ABI to Hex or find another way to escape the quotes.

pragma solidity 0.5.16;

contract SimpleIntrospection {

    bytes public BYTECODE;
    bytes public ABI;

    function setByteCode(bytes memory _bytecode, bytes memory _abi) public {
        require(BYTECODE.length == 0, "Already set.");
        require(_bytecode.length > 0, "Send byteCode.");
        require(_abi.length > 0, "send ABI");
        BYTECODE = _bytecode;
        ABI = _abi;
    }
}

Doable. Could be in your constructor.

Hope it helps.

1

Once your contract is deployed, you can use assembly code within solidity to access your byte code as seen in this example below.

The benefit of this vs just saving a parameter is that you are confident this is actually the byte code of the contract. One downside is that trying to use this in the constructor I do not believe will work.

assembly link

pragma solidity ^0.5.0;

contract StoreByteCode {

    function getByteCode() public view returns(bytes memory b_code){
        return at(address(this));
    }

    function at(address _addr) private view returns (bytes memory o_code) {
        assembly {
            // retrieve the size of the code, this needs assembly
            let size := extcodesize(_addr)
            // allocate output byte array - this could also be done without assembly
            // by using o_code = new bytes(size)
            o_code := mload(0x40)
            // new "memory end" including padding
            mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
            // store length in memory
            mstore(o_code, size)
            // actually retrieve the code, this needs assembly
            extcodecopy(_addr, add(o_code, 0x20), 0, size)
        }
    }
}

Your Answer

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

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