The function is the extended/inter-procedural variant of the instructions(), meaning that it works recursively. It returns a set of Instructions object representing all the instructions which are reachable from the target function, the differences between extended_instructions() and instructions() the latter will only return instructions directly accessible from the function. At the same time, the extended version will find all the instructions recursively, which are eventually called when executing the function.
Also, note that the return types of extended_instructions() -> Set[Instruction] and instructions() -> Instructions are different, the extended version returns a set of Instruction objects, while the original one returns Instructions (queryable) object.
Example
from glider import*defquery():# lets find a function with name transferFrom functions =Functions().with_name('functionCallWithValue').exec(1)#print the code of the functionprint(functions[0].source_code())#return the list of (extended) instructions, as it return a set, we need to cast it to listreturnlist(functions[0].extended_instructions())
For the function:
functionfunctionCallWithValue(address target,bytesmemory data,uint256 value ) internalreturns (bytesmemory) {returnfunctionCallWithValue(target, data, value,"Address: low-level call with value failed"); }
The output is:
Example Output
"root":{4 items"contract":string"0x9e35577836b8ac2e075a8d30e150bb9aafcbb64e""contract_name":string"Address""sol_function":solidityfunctionfunctionCallWithValue(address target,bytesmemory data,uint256 value ) internalreturns (bytesmemory) {returnfunctionCallWithValue(target, data, value,"Address: low-level call with value failed"); }"sol_instruction":solidityreturnfunctionCallWithValue(target, data, value,"Address: low-level call with value failed")},..."root":{4 items"contract":string"0x9e35577836b8ac2e075a8d30e150bb9aafcbb64e""contract_name":string"Address""sol_function":solidityfunctionfunctionCallWithValue(address target,bytesmemory data,uint256 value,stringmemory errorMessage ) internalreturns (bytesmemory) {require(address(this).balance >= value,"Address: insufficient balance for call");require(isContract(target),"Address: call to non-contract"); (bool success,bytesmemory returndata) = target.call{value: value}(data);returnverifyCallResult(success, returndata, errorMessage); }"sol_instruction":soliditybytesmemory returndata}root":{4 items"contract":string"0x9e35577836b8ac2e075a8d30e150bb9aafcbb64e""contract_name":string"Address""sol_function":solidityfunctionfunctionCallWithValue(address target,bytesmemory data,uint256 value,stringmemory errorMessage ) internalreturns (bytesmemory) {require(address(this).balance >= value,"Address: insufficient balance for call");require(isContract(target),"Address: call to non-contract"); (bool success,bytesmemory returndata) = target.call{value: value}(data);returnverifyCallResult(success, returndata, errorMessage); }"sol_instruction":solidityrequire(address(this).balance >= value,"Address: insufficient balance for call")},..."root":{4 items"contract":string"0x9e35577836b8ac2e075a8d30e150bb9aafcbb64e""contract_name":string"Address""sol_function":solidityfunctionverifyCallResult(bool success,bytesmemory returndata,stringmemory errorMessage ) internalpurereturns (bytesmemory) {if (success) {return returndata; } else {// Look for revert reason and bubble it up if presentif (returndata.length >0) {// The easiest way to bubble the revert reason is using memory via assemblyassembly {let returndata_size :=mload(returndata)revert(add(32, returndata), returndata_size) } } else {revert(errorMessage); } } }"sol_instruction":solidityreturndata.length >0}...