Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling external contract in solidity dynamically

I am trying to make a contract have a function that is capable of calling functions of another contract. The key part of my goal is that the contract should not be able to be deployed without any import statements and will not know the name of the contract by default. In other words the user of this contract would input the called contracts data (i.e. address, name) as parameters. What is the best way to accomplish this?

like image 899
GK1 Avatar asked Mar 30 '17 00:03

GK1


2 Answers

Not sure why this was downvoted.

If I understand the question correctly, you want to deploy the contract without knowledge of the specific details of the contracts it will have to communicate with.

You can greatly simplify this by assuming knowledge of their interfaces.

You can define interfaces without importing contract code. Define the function interfaces and leave the function definitions empty:

contract WidgetInterface {

   function doSomething() returns(uint) {}
   function somethingElse() returns(bool isTrue) {}

}

Use that Interface contract to talk to actual contracts:

WidgetInterface w = WidgetInterface(actualContractAddress);

In my opinion it will usually be possible and advisable to register authorized/valid contracts as you go. Maintain a list of the contracts it can safely talk to, along these lines:

if(!isAuthorized(actualContractAddress)) throw; 

where actualContractAddress is supplied by sender and isAuthorized() is a function you have worked out to query an internal registry.

Hope it helps.

like image 61
Rob Hitchens Avatar answered Oct 23 '22 09:10

Rob Hitchens


You can do this by using an interface, as suggested by Rob Hitchens, or you could define the interface dynamically and execute a method by using .call, .callcode, .delegatecall.

Here's an example:

contract ContractsCaller {

    function execute(address contractAt, uint _i, bytes32 _b) returns (bool) {
        return contractAt.call(bytes4(sha3("testMethod(uint256,bytes32)")), _i, _b);
    }
}

contract Test {

    uint256 public i;
    bytes32 public b;

    function testMethod(uint256 _i, bytes32 _b) {
        i = _i;
        b = _b;
    }
}

Test can be defined in a separate file. ContractsCaller doesn't need to know anything about Test besides its address and the signature of the method it's calling.

The signature of the method is the first 4 bytes of the method name and the types of its parameters:

bytes4(sha3("testMethod(uint256,bytes32)"))

More information about .call, .callcode, .delegatecall.

like image 23
Zvezdomir Zlatinov Avatar answered Oct 23 '22 10:10

Zvezdomir Zlatinov