How to detect missing function in opcode

Hello, suppose i havce the following two contracts (with the same name and no comments to minimize differences)

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract number1 {
    
    uint256 private number;

    function owner() external view virtual returns (uint256) {
        return number;
    }

    function num() external view virtual returns (uint256) {
        return 5;
    }

    
}

and

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract number1 {
    
    uint256 private number;

    function owner() external view virtual returns (uint256) {
        return number;
    }

    
}

When compiled in remix, i get the following opcodes per the order i listed the contracts:
1 - PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xE3 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH1 0x32 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x4E70B1DC EQ PUSH1 0x37 JUMPI DUP1 PUSH4 0x8DA5CB5B EQ PUSH1 0x51 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x3D PUSH1 0x6B JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x48 SWAP2 SWAP1 PUSH1 0x8A JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x57 PUSH1 0x74 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x62 SWAP2 SWAP1 PUSH1 0x8A JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 PUSH1 0x5 SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x84 DUP2 PUSH1 0xA3 JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH1 0x9D PUSH1 0x0 DUP4 ADD DUP5 PUSH1 0x7D JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 GASLIMIT 0xCA PUSH12 0xD78E7C14AC6A727538EC61A0 0xD4 0xE2 0xCF ISZERO 0x1E PUSH23 0xF2B9ED739410BE7DE83A6664736F6C6343000807003300

2- PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xB6 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH1 0x28 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x8DA5CB5B EQ PUSH1 0x2D JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x33 PUSH1 0x47 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x3E SWAP2 SWAP1 PUSH1 0x5D JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 DUP1 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x57 DUP2 PUSH1 0x76 JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH1 0x70 PUSH1 0x0 DUP4 ADD DUP5 PUSH1 0x50 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 0xE8 0xCD PUSH29 0x415E234F0499BCF4358C70570AE0645800E28F952A9A162BA6733FB881 PUSH5 0x736F6C6343 STOP ADDMOD SMOD STOP CALLER.

is there any way to detect the opcode of the missing function?
regards.

function names are represented in bytecode by taking the function signature of the name ("owner()" and "num()") and applying the keccak-256-hash function on it.
Of the result the first 8 characters (which is 4 bytes and also called a function signature) are taken and pushed onto the stack with the PUSH4 opcode during the construction phase of a contract.

In your example the function signature for owner() is 8da5cb5b and for num() it is 4e70b1dc. This site is quite useful for quick calculation: https://emn178.github.io/online-tools/keccak_256.html

if you search the opcode you can find these coupled with the PUSH4 command. the first code has both PUSH4 0x4E70B1DC and PUSH4 0x8DA5CB5B while the second code only has PUSH4 0x8DA5CB5B.

That is one approach to checking which functions are possibly missing in another contract. However, please note that PUSH4 "..." does not necessarily mean that the 4 bytes pushed are from a function signature (unless the compiler guarantees it, which I am not aware of)

1 Like

is there any way to check if the implementation of the function is the same or has it been changed between the contract?

it should be possible, but that is a bit more complicated. I recommend reading the following blog series by Openzeppelin (and also following along with Remix in your own browser, this will help a lot with understanding): https://blog.openzeppelin.com/deconstructing-a-solidity-contract-part-i-introduction-832efd2d7737/