Skip to content

Latest commit

 

History

History
125 lines (92 loc) · 5.14 KB

03.md

File metadata and controls

125 lines (92 loc) · 5.14 KB
title actions requireLogin material
Calling Other Contracts- Cont'd
checkAnswer
hints
true
editor
language startingCode answer
sol
caller/CallerContract.sol caller/EthPriceOracleInterface.sol
pragma solidity 0.5.0; //1. Import from the "./EthPriceOracleInterface.sol" file contract CallerContract { // 2. Declare `EthPriceOracleInterface` address private oracleAddress; function setOracleInstanceAddress (address _oracleInstanceAddress) public { oracleAddress = _oracleInstanceAddress; //3. Instantiate `EthPriceOracleInterface` } }
pragma solidity 0.5.0; contract EthPriceOracleInterface { function getLatestEthPrice() public returns (uint256); }
pragma solidity 0.5.0; import "./EthPriceOracleInterface.sol"; contract CallerContract { EthPriceOracleInterface private oracleInstance; address private oracleAddress; function setOracleInstanceAddress (address _oracleInstanceAddress) public { oracleAddress = _oracleInstanceAddress; oracleInstance = EthPriceOracleInterface(oracleAddress); } }

Awesome! Now that you've saved the address of the oracle into a variable, let's learn about how you can call a function from a different contract.

Calling the Oracle Contract

For the caller contract to interact with the oracle, you must first define something called an interface.

Interfaces are somehow similar to contracts, but they only declare functions. In other words, an interface can't:

  • define state variables,
  • constructors,
  • or inherit from other contracts.

You can think of an interface as of an ABI. Since they're used to allow different contracts to interact with each other, all functions must be external

Let's look at a simple example. Suppose there's a contract called FastFood that looks something like the following:

pragma solidity 0.5.0;

contract FastFood {
  function makeSandwich(string calldata _fillingA, string calldata _fillingB) external {
    //Make the sandwich
  }
}

This very simple contract implements a function that "makes" a sandwich. If you know the address of the FastFood contract and the signature of the makeSandwich, then you can call it.

Note: A function signature comprises the function name, the list of the parameters, and the return value(s).

Continuing with our example, let's say you want to write a contract called PrepareLunch that calls the makeSandwich function, passing the list of ingredients such as "sliced ham" and "pickled veggies". I'm not hungry but this sounds tempting😄.

To make it so that the PrepareLunch smart contract can call the makeSandwich function, you must follow the following steps:

  1. Define the interface of the FastFood contract by pasting the following snippet into a file called FastFoodInterface.sol:

    pragma solidity 0.5.0;
    
    interface FastFoodInterface {
       function makeSandwich(string calldata _fillingA, string calldata _fillingB) external;
    }
  2. Next, you must import the contents of the ./FastFoodInterface.sol file into the PrepareLunch contract.

  3. Lastly, you must instantiate the FastFood contract using the interface:

fastFoodInstance = FastFoodInterface(_address);

At this point, the PrepareLunch smart contract can call the makeSandwich function of the FastFood smart contract:

fastFoodInstance.makeSandwich("sliced ham", "pickled veggies");

Putting it together, here's how the PrepareLunch contract would look like:

pragma solidity 0.5.0;
import "./FastFoodInterface.sol";

contract PrepareLunch {

  FastFoodInterface private fastFoodInstance;

  function instantiateFastFoodContract (address _address) public {
    fastFoodInstance = FastFoodInterface(_address);
    fastFoodInstance.makeSandwich("sliced ham", "pickled veggies");
  }
}

Now, let's use the above example for inspiration as you set up the caller contract to execute the updateEthPrice function from the oracle smart contract.

Put It to the Test

We've gone ahead and created a new file called caller/EthPriceOracleInterface.sol and placed it into a new tab. Give it a read-through. Then, let's focus back on the caller/CallerContract.sol tab.

  1. After the line of code that declares the pragma, import the ./EthPriceOracleInterface.sol file.

  2. Let's add an EthPriceOracleInterface variable named oracleInstance. Place it above the line of code that declares the oracleAddress variable. Let's make it private.

  3. Now let's jump to the setOracleInstanceAddress function. Instantiate the EthPriceOracle contract using EthPriceOracleInterface and store the result in the oracleInstance variable. If you can't remember the syntax for doing this, check the example from above. But first, try to do it without peeking.

Oops! By now, you probably know enough about Solidity to figure out that there's a security hole in this code🤯. In the next chapter, we'll explain how to make the setOracleInstanceAddress function safe.