I'm studying about call function in solidity and got stuck. Below is the code I'm working on and what I want is to call bar function from Foo in Loo contract.

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

contract Loo {
    Foo foo;

    function callWithInstance(address payable _t, uint a, uint b) public payable returns(uint) {
        foo = Foo(_t);
        return foo.bar(a,b);
    }
    
    function callWithEncodeSignature(address _t, uint a, uint b) public returns(uint) {
       bytes memory data = abi.encodeWithSignature("bar(uint, uint)", a, b);
        (bool success, bytes memory returnData) = _t.call( data);
        require(success);
        uint c = abi.decode(returnData, (uint));
        return c;
    }

    function callWithEncode(address _t, uint a, uint b) public returns(uint) {
        (bool success, bytes memory returnData) = _t.call( bytes4(keccak256("bar(uint, uint)")), a, b);
        require(success);
        uint c = abi.decode(returnData, (uint));
        return c;
    }
    
}

contract Foo {
    function bar(uint a, uint b) public pure returns(uint) {
        return a+b;
    }
}
  1. I cannot find any advantages using call function instead of calling the function directly from contract instance. What is the advantage of using it?
  2. My callWithEncodeSignature fails to get pass the require(success). I cannot find out the reason.
  3. My callWithEncode function gives "TypeError: Wrong argument count for function call". What did I missed?

1- The call , callcode (this is deprecated), and delegatecall functions are provided in order to interact with functions that do not have an ABI. These functions are not safe to use due to the impact on type safety and security of the contracts.

2- you should call it like this:

  _t.call( data)("")

3- call expects only one argument but you are passing 3 arguments