Solidity
如何在松露堅固性測試中增加 block.number?
有沒有辦法
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); } }