1

I have The Following Function in my Smart Contract

 function functionName(uint256 param1, address param2)
        external
        override
    {
        require(msg.sender == marketContract, "only market contract");

The Market Contract Address is Set in the Constructor

 constructor(address marketContractAddr) 
        {
        marketContract = marketContractAddr;
        }

I Have Then Written The Following in my Test in Hardhat in the beforeEach I do the Following

    marketContract = await ethers.getContractFactory("Market");
    market = await marketContract.deploy();
    await market.deployed();

    mediaContract = await ethers.getContractFactory("Media");
    media = await mediaContract.deploy(market.address);
    await media.deployed(); 

and get my signers using the following

[owner,addr1,addr2] = await ethers.getSigners();

I Then Want to in my test make the following call

 const res = await media.functionName(1,addr2.address)
 await res.wait();

The Above is expected to revert due to the following require statement

 require(msg.sender == marketContract, "only market contract");

How Can One Call This Function With The Deployed Market Contract as the msg.sender ?

I Have Tried The Following

  1. Tried Using connect when making the call from my test seen below
 const res = await media.connect(market).functionName(1,addr2.address)

which fails with the following

" Error: VoidSigner cannot sign transactions "

I Then Tried The Following which also fails

 const res = await media.functionName(1,addr2.address{
       from:market.address
     })

I Then Tried Running My Test After Deploying My Contracts to my Local "npx hardhat node"

I Then Receive the following error

"Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"name":"ProviderError"

I Realized that when running

market = await marketContract.deploy();

A New Address Was Created For My Market Contract and it didn't match what I had already deployed to my local network

so I tried Recreating my Contracts within my test at the deployed local addresses

    const marketRes = await artifacts.readArtifact("Market");
    const marketResContract = new ethers.Contract("0x5FbDB2315678afecb367f032d93F642f64180aa3", marketRes.abi, ethers.provider);
    

Still With no Success receiving the following errors depending on weather I use connect or from

"invalid signer or provider" and "Contract with a Signer cannot override from"

It Seems Pretty Straight Forward but cannot seem to find success would really appreciate any guidance

Thank you Team

2 Answers 2

2

Hello Team Have Finally Resolved It

One Has To First

    
  await hre.network.provider.request({
  method: "hardhat_impersonateAccount",
  params: [market.address],
});

Then Get The Signer Using the Following

 const signer = await ethers.getSigner(market.address);

One Can Then Use the Signer In The Connect Of The Contract Call From Within Your Hardhat Test

await media.connect(signer).functionName(1,addr2.address);

and end impersonating the contract using the following

  await hre.network.provider.request({
  method: "hardhat_stopImpersonatingAccount",
  params: [market.address],
});

I Hope This Can Help Anyone Else Facing this Issue

Thank You

2
  • It worked partially because now I have InvalidInputError: sender doesn't have enough funds to send tx. The max upfront cost is: 499021982986307664 and the sender's account only has: 0 Commented Mar 8, 2022 at 15:04
  • ok I solved this sending first some ETH to my contract with signer.sendTransaction({to: MyContract.address, value: parseEther("1")}) for example Commented Mar 8, 2022 at 17:29
0

You have to code the function call into the Market contract itself, then protect that function with whatever validation logic you need. Dummy implementation:

interface ICalledByMarket {
  function functionName(uint256 param1, address param2) external;
}

contract CalledByMarket is ICalledByMarket {
  function functionName(uint256 param1, address param2) {
    // do stuff
  }

  // rest of your code
}

contract Market {
  `onlyAuthorizedCaller` is a modifier with whatever protection logic you want
  function callOtherContract(uint256 param1, address param2) public is onlyAuthorizedCaller {
    ICalledByMarket(otherContractAddress).functionName(param1, param2);
  }

  // rest of your code
}

You can also use .call syntax as described here or any other number of resources to achieve the same effect

1
  • Hello Sir Thanks For The Response that is already my implementation the issue is not the solidity smart contract but when calling the functions from HardHat Tests hope this clarifies details of challenge I am facing Commented Mar 3, 2022 at 11:00

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.