0

In my system, users can request to be verified by a trusted contract. When a user creates an account he deploys this contract (omitting non-related parts)

pragma solidity ^0.4.11;

contract User {
    // State variables
    address owner = msg.sender;
    bool verified = false;
    uint creationTime = now;
    struct PersonalInfo {
        string firstName;
        string LastName;
        string email;
    }
    uint level = 0;

    function requestVerification(address trustEntity) {
        /*
            This function should send a verification request
            to a trust entity's contract
        */
    }
}

There is a known trusted entity, whose contract address will be known to everyone, who should be the only entity capable of verifying the users. Its contract (omitting non-related parts) is

pragma solidity ^0.4.11;

contract TrustEntity {
    address owner;
    address registry;
    address[] public pendingRequests;

    function verifyUsers(address user) {
        /*
            Whenever a user requests verification, his
            address should be pushed to the pendingRequests
            array, so it can then be fetched to verify or
            reject
        */
    }   
}

Every example I see of a contract interacting with another contract, they're both in the same file (docs, this question) so I don't know if it is possible for a contract to call another contract (or, in this specific case, to push an address into another contract's state variable / change another contract's state variable).

2 Answers 2

0

Yes.

The calling contract needs two things; the address of the contract to be called, and a description of the ABI. The ABI is, in summary, a description of the function names and layout of the arguments.

You often see the contracts in the same file because it gives the compiler the information it needs about the ABI. In many cases, one or more of the contracts won't be deployed manually, but rather through a process in one or more other contracts.

You might see something like this:

import "/Utility.sol"; // something already deployed. We want the code so the compiler can see the interface.

contract Factory { // something that deploys instances
  Utility utility; // Type is Utility (contract)
  function Factory(address _utility) {
    utility = Utility(_utility); // Utility at the supplied (known) address
  }
  function newInstance() returns(address contract) {
    Instance = new Instance(utility); // make a new instance and inform about another contract's address
    return instance;
}

contract Instance { // something that will copied/deployed many times
  Utility utility;
  function Instance(address _utility) { // utility address passed in
    utility = Utility(_utility); // get set to use the Utility
  }
}

In the above, the idea is that Utility is deployed, and the deployer knows the address, so they pass it into the contructor when they deploy the Factory (otherwise, how will it know?). They don't need to deploy an Instance because the Factory does that. The compiler still needs to see all three source files when Factory gets compiled. Factory needs a copy of the bytecode it's supposed to deploy with new Instance(); and it needs the interface to Utility because the other two contracts both talk to it.

A little more practical example over here: Is There a Simple Contract Factory Pattern?

Hope it helps.

1

Every example I see of a contract interacting with another contract, they're both in the same file (docs, this question)

You can have contracts in multiple file.Two contracts which should interact need not be in same file. you let know the other contract which you want to interact via import statement.

In this case if User contracts wants to interact with TrustEntity then it should be like below

pragma solidity ^0.4.11;
import "TrustEntity.sol"; -- Import statement

contract User {
....
...
}

I don't know if it is possible for a contract to call another contract (or, in this specific case, to push an address into another contract's state variable / change another contract's state variable).

Yes,It is possible. You pass the instance of the other contract in the constructor(Ideally it is the address where the contract is deployed). In this case

 pragma solidity ^0.4.11;
    import "TrustEntity.sol"; -- Import statement
    Trustentity trustentity;
    contract User {
   function User(address _trustentity )
    {
  trustentity= Trustentity(_trustentity); // This will pick the address where your contract is deployed. 
    }

To change the state variable of other contract,you access it via other contract instance. i.e trustentity.pendingRequests will give you all pending request of users in user contract.

2
  • Thanks for the explanation! It all seems to work fine, however there is still one issue. trustEntity.pendingRequests should return the pending requests array, so why do I get an error if I try to write trustentity.pendingRequests.push(owner) from the User contract? I thought it would behave just the same. The error I get is browser/User.sol:19:6: TypeError: Member "push" not found or not visible after argument-dependent lookup in function (uint256) constant external returns (address) trustEntity.pendingRequests.push(owner); ^------------------------------^
    – mcansado
    Aug 4, 2017 at 15:41
  • I've actually asked a new question regarding this here because it's a bit of a different issue.
    – mcansado
    Aug 4, 2017 at 15:58

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.