Solidity

使用 ether.js 在測試中呼叫另一個合約時模擬合約

  • August 16, 2021

我是 Solidity 開發的新手,正在為一個 dapp(Hardhat、Chai、ethers.js、Smockit)編寫測試,其中兩個合約ProductMarket共存。我正在嘗試對Market只能從Product實例呼叫的函式進行測試。

這是Market契約。它持有對 a 的引用Product,並且有一個foo方法,如果不從 that 呼叫,該方法將恢復Product

pragma solidity ^0.8.4;

contract Market {
   public address productAddr;

   constructor(address addr) {
       productAddr = addr;
   }

   function foo() external {
       require(msg.sender == productAddr, "nope!");
       // do something...
   }
}

因此,在測試該foo方法時,我需要確保呼叫是從Product合約實例發出的,否則它會恢復。我如何用 ethers.js 做到這一點?

我試過使用.connect,它需要一個簽名者或提供者作為參數,就像這樣……

const signers = await ethers.getSigners();
const ProductFactory = await ethers.getContractFactory('Product', signers[0]);
const MarketFactory = await ethers.getContractFactory('Market', signers[0]);
const product = await ProductFactory.deploy();
const market = await MarketFactory.deploy(product.address); // store product address

market.connect(product.signer).foo();  // not working :-(

…但它會恢復,因為product.signer返回對 的引用signers[0],而不是對我想作為呼叫者呈現的契約的引用,顯然。

我應該如何進行?任何幫助將不勝感激,並將擴大我的知識。

contract.signer返回合約部署者賬戶的簽名者,而不是合約自身地址的簽名者。模擬一個賬戶地址真的很困難,因為被模擬的賬戶需要包含 ETH 來支付通過它產生的任何交易。所以我想你首先需要知道合約地址是什麼(可能使用 CREATE2),然後向它發送一些 ETH,然後在你發送 ETH 的地址創建合約並模擬它來生成該交易。如果你反其道而行之,合約地址很可能會有一個回退功能來拒絕接受任何發送的 ETH。您需要使用 Hardhat 才能模擬帳戶,操作方法如下:https ://hardhat.org/hardhat-network/reference/#hardhat-impersonateaccount

引用自:https://ethereum.stackexchange.com/questions/107190