When the called contract doesn't adhere to the ABI, we can't just use ContractAInstance.f(); or ContractA ContractAInstance = ContractA(0x123456) to define a new instance.
In this case, we have to use the special low-level call function, using the following call structure:
contract_address.call(bytes4(sha3("function_name(arguments types)")), parameters_values)
In the previous example, we could call f() with two arguments using ContractAaddress.call(bytes4(keccak256("f(uint256,string)")), 10, ”hello”);.
This is a sort of tedious manual construction of the ABI function signature. However, things are getting better with newer Solidity. Since release 0.4.22, the abi.encode(), abi.encodePacked(), abi.encodeWithSelector(), and abi.encodeWithSignature() global functions have been defined to encode structured data, therefore helping us to build a valid call, as follows:
OneInstance.call(abi.encodeWithSignature("function_name(arguments types)")),parameters_values)
call can be used along with the .gas() and value() methods to adjust the supplied gas and value in the call.
call returns true if the called function executes without exception. Also, it will fire an exception if the call contract does not exist, or if it throws an exception or runs out of gas. If we apply call to a contract without specifying a function name, its fallback will be executed (maybe that's why the fallback function doesn’t have a name).