Solidity – How to Call a Contract Within a Smart Contract

erc-721soliditytokens

I need solidity analog of web3 command:

const contract = new web3.eth.Contract(contractJSON.abi, deployedAddress)

The context is:

  1. Contract A call contract B
  2. Contract B receives an address of contract A instance which calls contract B
  3. Contract B by this address restore the instance of contract A including its custom inner state.
  4. Contract B call some public functions of Contract A for the defined purpose

Here is details on oppen zeppelin forum. Please note as abi is mandatory we are talking about the case when both Contract A and Contract B source code is available.

Update
Yesterday I was working on docs sample:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.2 <0.9.0;

contract InfoFeed {
    function info() public payable returns (uint ret) { return 42; }
}

contract Consumer {
    InfoFeed feed;
    function setFeed(InfoFeed addr) public { feed = addr; }
    function callFeed() public { feed.info{value: 10, gas: 800}(); }
}

which failed to calFeed() with exception:

[vm]
from: 0xAb8...35cb2
to: Consumer.callInfoPayable() 0x7EF...8CB47
value: 0 wei
data: 0x574...3ed13
logs: 0
hash: 0xbd4...90453

transact to Consumer.callInfoPayable errored: VM error: revert.

revert
    The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the value you send should be less than your current balance.
Debug the transaction to get more information.

Error message points out on error payable modifier requirement which function already has. Today by strip the sample to simple external call I was able to execute the call:

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract InfoFeed {
    function info() public pure returns (uint) { return 42; }
    function infoPayable() public payable returns (uint) { return 42; }
}
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

import "./InfoFeed.sol";

contract Consumer {

    InfoFeed feed;

    function setInfoFeed(address addr) public { feed = InfoFeed(addr); }

    function getInfo() public view returns (uint) { return feed.info(); }

}

Now the question is to fix contract call for payable function. Especially when this sample from the official docs and should work "as is".

Best Answer

In solidty it will be something like this

function bid(address _nft, uint _nftId, uint _startingBid) {
    // ..

    IERC721 nft = IERC721(_nft);
    nft.safeTransferFrom(msg.sender, address(this), _nftId);

    // ..
}
Related Topic