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;    
}
}
3
  • 1
    Do you have the source code or ABI of the contract to call? Apr 19, 2017 at 12:39
  • I updated the question with the source code
    – Resten
    Apr 19, 2017 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. Sep 26, 2018 at 19:51

1 Answer 1

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) {}
}
3
  • 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, 2017 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{}. Apr 19, 2017 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 9, 2017 at 0:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.