0

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".

2 Answers 2

1

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);

    // ..
}
7
  • Where is the contract constructor which receives an address as a parameter? I haven't found any implementation details on this. If it is done over some kind of synthetic sugar constructions I would be glad to see the code or read docs on it.
    – Gleichmut
    Commented Aug 9, 2022 at 9:28
  • @Gleichmut The web3js code in the question doesn't create a contract it just instantiate an object to execute queries and transactions. That will be done by IERC721 nft = IERC721(_nft) the ABI is implicit in the interface IERC721 definition and the address is the parameter _nft.
    – Ismael
    Commented Aug 9, 2022 at 16:23
  • thank you, I already figure out it. It is still interesting to understand how excatly it was implemented as there is no default constructor which accept address, but it is a second priority. What is more important is to understand why simple instantiation works, but the same instantiation for payable functions would failed (transaction has been reverted) which was addressed in origin question above.
    – Gleichmut
    Commented Aug 11, 2022 at 13:40
  • @Gleichmut It is just a type casting, no constructor involved. The other question perhaps should be better as a separate one. I haven't tried it yet, but the documentation could be out of date, try increasing the gas. Also transferring ether requires the contract to have at least enough balance to cover the value transferred.
    – Ismael
    Commented Aug 12, 2022 at 11:56
  • thank you for your help with this. Gas is not issue: I have checked it is consumed much less (2x-3x times less) for this tx. Regarding balance do you mean address of user who execute tx or address of contract? For the first case it is a test chain with 100 ether on the balance, for the second case I would ask you to clarify in more details.
    – Gleichmut
    Commented Aug 13, 2022 at 12:47
1

First you need to have that second contract (or an interface of it) in your directory, and then you need to import it into your solidity contract

import "ContractB.sol";

From there, you can make calls to Contract B by calling ContractB(<0xaddressOfContract>).someFunction

It looks like you're trying to interface with an ERC-721 contract within another ERC-721 contract. In that case, you already have OpenZeppelin's ERC721.sol imported. You can simply call ERC721(<contractAddress>).function and it will work.

If you want to call any functions in that ERC-721 contract that aren't standard ERC-721 functions, then you would need to import that actual contract (or an interface of it)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.