Used to validate inputs and conditions before execution.
// Used in both test contracts and main contractsrequire(success,"Call failed");
revert
Similar to require, revert is useful when the condition to check is complex.
So put it at the end of a longer logic statement making it easier to read.
// This error definition is needed in the main contract and the test contracterrorFundMe__RefundFailed();// In main contractif (!callSuccess) revertFundMe__RefundFailed();// In test contract// Expects the next line to revert with the specified errorvm.expectRevert(FundMe__RefundFailed.selector);testHelper.fundMeRefund();
The .selector property retrieves the unique identifier (selector) of the FundMe__RefundFailed error.
In the case of errors (and events), the selector is derived from the error's name and its parameters.
assert
// Used in both test contracts and main contractsassert(funders.length ==3);assertEq(funders.length,3); // More informative logs
Gas Saving
errorFundMe__NotOwner();// Uses more gas as a custom error is stored as a string (bytes array)require(msg.sender == i_owner);// Uses less gas as the error is not stored as a stringif (msg.sender != i_owner) revertFundMe__NotOwner();
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;contract Error {functiontestRequire(uint_i) publicpure {// Require should be used to validate conditions such as:// - inputs// - conditions before execution// - return values from calls to other functionsrequire(_i >10,"Input must be greater than 10"); }functiontestRevert(uint_i) publicpure {// Revert is useful when the condition to check is complex.// This code does the exact same thing as the example aboveif (_i <=10) {revert("Input must be greater than 10"); } }uintpublic num;functiontestAssert() publicview {// Assert should only be used to test for internal errors,// and to check invariants.// Here we assert that num is always equal to 0// since it is impossible to update the value of numassert(num ==0); }// Custom error with multiple parameterserrorInsufficientBalance(uint balance,uint withdrawAmount);functiontestCustomError(uint_withdrawAmount) publicview {uint bal =address(this).balance;if (bal < _withdrawAmount) {revertInsufficientBalance({balance: bal, withdrawAmount: _withdrawAmount}); } }}
Example 2
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;contract Account {uintpublic balance;uintpublicconstant MAX_UINT =2**256-1;functiondeposit(uint_amount) public {uint oldBalance = balance;uint newBalance = balance + _amount;// balance + _amount does not overflow if balance + _amount >= balancerequire(newBalance >= oldBalance,"Overflow"); balance = newBalance;assert(balance >= oldBalance); }functionwithdraw(uint_amount) public {uint oldBalance = balance;// balance - _amount does not underflow if balance >= _amountrequire(balance >= _amount,"Underflow");if (balance < _amount) {revert("Underflow"); } balance -= _amount;assert(balance <= oldBalance); }}