Solidity
使用 ether.js 在測試中呼叫另一個合約時模擬合約
我是 Solidity 開發的新手,正在為一個 dapp(Hardhat、Chai、ethers.js、Smockit)編寫測試,其中兩個合約
Product
和Market
共存。我正在嘗試對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