From solidity docs:
The EVM does not provide a direct way for a contract to detect whether
it was called using CALL or not, but a contract can use the ADDRESS
opcode to find out “where” it is currently running. [...]
More specifically, the runtime code of a library always starts with a
push instruction, which is a zero of 20 bytes at compilation time.
When the deploy code runs, this constant is replaced in memory by the
current address and this modified code is stored in the contract. [...]
Library:
pragma solidity ^0.5.8;
library lib {
function isZero (address _address) public pure returns (bool) {
return _address == address(0x0);
}
}
Contract:
pragma solidity ^0.5.8;
import "./lib.sol";
contract Importer {
function doSom (address _address) public pure returns (bool) {
require(lib.isZero(_address));
return true;
}
}
You can see in the bytecode the PUSH20
instruction of a zero of 20 bytes:
...
JUMPDEST
PUSH1 0x0
PUSH20 0x0
...
But in Remix (Debug):
143 PUSH20 bbf289d846208c16edc8474705c748aff07732db

What you can do is look for a DELEGATECALL
opcode in the bytecode and try to search the identifier of the function (in this case: isZero(address): 0x673C8BE
). Only when you have knowledge about the method_id (signature) of the function, something easy with the SafeMath.sol
library.
DELEGATECALL
:
...
JUMPDEST
POP
GAS
DELEGATECALL
ISZERO
...
In Remix (Debug):

Function identifier:
...
PUSH20 0x0
PUSH4 0x673C8BE
DUP4
...
In Remix (Debug):
