5

I tried to use the function "Call", as described here: Calling function from deployed contract

But seems it is not working at all.

How can I call a function from an existing deployed smart contract?

I'm trying to call a simple function from an existing address that receives an address as parameter.

This is the code I'm using to call the external function:

Contract A:

function CallExternalFunction(address externalContractAddress) 
{    
    externalContractAddress.call(bytes4(sha3("FunctionX(address)")),0xfffff);
    //sends 0xfffff as input parameter to the external contract
}

The source code of the already deployed contract is like this:

Contract B:

contract test { 

mapping (address => uint256) public balanceOf; 

function test() { 

}

function FunctionX(address _address)
{
    balanceOf[_address] = 50000;    
}
}
Resten
  • 533
  • 1
  • 8
  • 14
  • 1
    Do you have the source code or ABI of the contract to call? – Rob Hitchens Apr 19 '17 at 12:39
  • I updated the question with the source code – Resten Apr 19 '17 at 12:47
  • There doesn't seem to be anything wrong with this approach; it's just a lower level call to the external contract. There are just a few caveats. With call all of your gas (minus ~30k) will be forwarded to the external contract to do with it what it pleases, which is a vulnerability especially if the call fails and defaults to the fallback function. call also breaks type-safety for function arguments and will still transfer ether if an exception is emitted on execution, so make sure to place the call in a require() in order to revert transactions that don't behave as expected. – Garen Vartanian Sep 26 '18 at 19:51

1 Answers1

4

Try this. Deploy the caller, and it will deploy the test contract to simplify matters.

contract Caller {

  test public t;

  function Caller() {
    t = new test();
  }

  function callIt(address theAddress)
    public
    returns(bool success)
  {
    t = test(t); <===== here the other contract address can be called t = test([OtherContractAddress]); example: test(0x12345);
    bool result = t.FunctionX(theAddress);
    return result;
  }
}

contract test { 

  mapping (address => uint256) public balanceOf; 

  function FunctionX(address _address) public returns(bool success)
  {
    balanceOf[_address] = 50000; 
    return true;
  }
}

In Remix to show it working.

enter image description here

You can use a similar structure for a contract that is already if you have the source code, by using and Interface contract. Here "Caller" compiler can see just enough of test {} to manage the interface.

contract Caller {

  test public t;

  // where test is deployed and the address is known
  // Pass in the address for test {}.

  function Caller(address tAddress) {
    t = test(tAddress); // address of contract t
  }

  function callIt(address theAddress)
    public
    returns(uint bal)
  {
      return t.FunctionX(theAddress);
  }
}

// This interface constant includes the function interfaces (exactly as in the "real" contract" with the fynctions undefined
// This tells the compiler how to communicate with the ABI in test{}.

contract test { 
  function FunctionX(address _address) public returns(uint balanceOf) {}
}
Resten
  • 533
  • 1
  • 8
  • 14
Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145
  • The example you displayed seems to be the 2 contracts in the same deployed address right? In my case the Contract A and B are deployed in different addresses (I updated the description with contract A and B). Do you know how to make it work when the contracts are deployed in different addresses? – Resten Apr 19 '17 at 13:19
  • 1
    No. Two contracts at one address is not possible. Two contracts in a single source file, with the first contract deploying an instance of the other (one way for it to know the address of the other). Caller at 0xb872, test at 0x22e6.t = new test(); deploys a new instance of test. For already deployed test{} you can pass in the address or hard code the address. Caller will need to know it to make the call. The single source file gives the compiler a view of the test contract so it) understands the test{} interface and has the bytecode it needs to deploy a new test{}. – Rob Hitchens Apr 19 '17 at 14:33
  • I like the forward-declaration idea. Note the compiler (solcjs) generates "Unused local variable" warning for _address in the above example. – bitsanity Oct 09 '17 at 00:06