Solidity

如何在松露堅固性測試中增加 block.number?

  • December 21, 2021

有沒有辦法block.number在基於堅固性的松露測試中增加(例如探勘一個塊)?

通過對 evm 進行 RPC 呼叫,我可以使用基於 javascript 的測試很好地做到這一點,但我找不到任何關於我們是否可以通過用solidity 編寫的測試來做到這一點的資訊。

使用 truffle/ganache 和可靠性測試似乎無法輕鬆增加塊數。

對於基於 javascript 的測試,您始終可以使用以下方法一一推進塊編號:

advanceBlock = () => {
 return new Promise((resolve, reject) => {
   web3.currentProvider.send({
     jsonrpc: '2.0',
     method: 'evm_mine',
     id: new Date().getTime()
   }, (err, result) => {
     if (err) { return reject(err) }
     const newBlockHash = web3.eth.getBlock('latest').hash

     return resolve(newBlockHash)
   })
 })

但是,如果您需要探勘大量塊,這不能很好地擴展。Ganache 不支持一次探勘多個區塊。

我發現的解決方法(我相信其他人也有)是將block.number合約中的呼叫替換為虛擬函式:

function _blockNumber() internal virtual view returns (uint256) {
   return block.number;
}

然後出於測試目的,您可以針對從原始合約繼承的測試合約進行測試,並_blockNumber()覆蓋該函式:

contract TestableMyContract is MyContract {
   uint256 _fakeBlockNumber;
   constructor(string memory name_, string memory symbol_) MyContract(name_, symbol_) {
   }

   function __test_setBlockNumber(uint256 blockNumber_) public {
       _fakeBlockNumber = blockNumber_;
   }

   function _blockNumber() internal override view returns (uint256) {
       if (0 == _fakeBlockNumber) {
           return super._blockNumber();
       }
       return _fakeBlockNumber;
   }
}

在基於 javascript 的測試中,您可以簡單地更改塊號:

contract("MyContract", (accounts) => {
   it("should do something when the block number increases", async () => {
       const instance = await TestMyContract.deployed();
       const deployBlock = await web3.eth.getBlock("latest");
       const deployBlockNumber = deployBlock.number;
       await instance.__test_setBlockNumber(deployBlockNumber + BLOCKS_TO_INCREASE);
   });
});

因為我們只是呼叫一個合約函式來“改變”(合約的視圖)區塊號,我們可以類似地從可靠性測試中呼叫它:

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/TestableMyContract.sol";

contract TestMyContract {
   function test_increase_block_number() public {
       TestableMyContract c = TestableMyContract(DeployedAddresses.TestableMyContract());
       c.__test_setBlockNumber(DESIRED_BLOCK_NUMBER);
   }
}

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