Search code examples
ethereumsolidity

How can I code a contract call for a contract that is currently unknown?


There is a contract called Voting. sol and it can accept proposals and votes on these proposals.

I want to be able that when people create proposals to be able to specify a call that will happen once the vote is finished.

The call should have the Address of the contract to call, function to call, and parameters to pass to the function.

However, we don't know these (neither the contract to be called ABI) upon creation of Voting. sol only when we are creating a proposal later on.

Is there some way to do this?


Solution

  • You can create a proxy contract in advance, fix its address in Vol.sol, and then transfer the address of the smart contract you need through this proxy contract. In addition to the address through the proxy, you can also transfer the ABI specification. If you use an array of bytes32 to pass parameters to the Vol-contract method, then you can pass any number of parameters of different types.

    1. You deploy contract Proxy and save it address
    2. Use Proxy address for initialisation public ProxyAddr in contract VolUser
    3. Late, after deploing contract Vol, you call Proxy method SetVol with values (Vol-address, "AnyFunction(bytes32[])"
    4. When calling method CallVol of the VolUser contract, the method AnyFunction of the Vol contract will be called.
        pragma solidity >=0.5.8 <0.6.0;
        
        contract Proxy
        {
        
            address  Owner ;
        
            address  VolAddr ;
             string  VolABI ;
        
        
           constructor() public
           {
                Owner=tx.origin ;
           }
        
           function SetVol(address VolAddr_, string memory VolABI_) public
           {
               if(tx.origin!=Owner)  require(false) ;
        
                  VolAddr=VolAddr_ ;
                  VolABI =VolABI_ ;
           }
        
           function GetVol() public view returns (address, string memory retVal)
           {
               return(VolAddr, VolABI) ;
           }
        
        }
        
        
        contract VolUser
        {
        
            Proxy  ProxyAddr ;
        
        
           constructor() public
           {
           }
        
           function CallVol() public
           {
                  address           VolAddr ;
                   string    memory VolABI ;
                  bytes32[2] memory VolPars ;
                     bool           result ;
        
                (VolAddr, VolABI)=ProxyAddr.GetVol() ;
        
                         VolPars[0]=               "ABC" ;
                         VolPars[1]=bytes32(uint256(321)) ;
                     
                (result,)=address(VolAddr).call.gas(0x300000).value(0)(abi.encodeWithSignature(VolABI, VolPars)) ;
        
           }
        
        }
        
        contract Vol
        {
        
           constructor() public
           {
           }
        
           function AnyFunction(bytes32[] memory VolPars_) public
           {
        //     ...
           }
        
        }