Solidity Revert and Assert
The revert statement stops a call at once with a message. The assert statement checks a condition that should never fail.
Revert stops a withdraw that is too big
This ledger holds a plain number balance. A withdraw bigger than the balance reverts at once.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract PlainLedger {
uint256 public balance;
function add(uint256 amount) public {
balance += amount;
}
function withdraw(uint256 amount) public {
if (amount > balance) {
revert("Amount beats the balance");
}
balance -= amount;
}
}
Assert checks a result that must hold
Adding one must grow the count by exactly one. Assert checks that fact right after the update.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract CheckedCounter {
uint256 public count;
function increment() public {
uint256 before = count;
count += 1;
assert(count == before + 1);
}
}
Revert guards and assert confirms
One function can use both tools. Revert guards the withdraw, and assert confirms each add.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract GuardedLedger {
uint256 public balance;
function add(uint256 amount) public {
uint256 before = balance;
balance += amount;
assert(balance == before + amount);
}
function withdraw(uint256 amount) public {
if (amount > balance) {
revert("Amount beats the balance");
}
balance -= amount;
}
}
Example
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract SafeLedger {
uint256 public balance;
uint256 public totalAdded;
uint256 public totalWithdrawn;
function add(uint256 amount) public {
balance += amount;
totalAdded += amount;
assert(balance == totalAdded - totalWithdrawn);
}
function withdraw(uint256 amount) public {
if (amount > balance) {
revert("Amount beats the balance");
}
balance -= amount;
totalWithdrawn += amount;
assert(balance == totalAdded - totalWithdrawn);
}
}
Key points
- Revert: a statement that stops a call at once and undoes its changes.
- Use revert inside an if when a bad case needs its own branch.
- The text in quotes is the message shown when revert runs.
- Assert: a check for a condition that should always be true.
- Use assert after an update to check an invariant.
- Invariant: a rule about the stored data that should always hold.
In this example, add grows the balance and the total added together. The withdraw function reverts when the amount beats the balance. After each update, assert checks that the balance equals the total added minus the total withdrawn. A failed withdraw changes none of the three stored numbers.
Note
assert gives no message, unlike revert and require.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Remix IDE
Exercise
Which statement is the right tool for a condition that should never fail?