I'm wondering what's the difference from
contract TestToken {
mapping(address => uint) balance;
error InsufficientBalance(uint256 available, uint256 required);
function transfer(address to, uint256 amount) public {
if (amount > balance[msg.sender])
// Error call using named parameters. Equivalent to
// revert InsufficientBalance(balance[msg.sender], amount);
revert InsufficientBalance({
available: balance[msg.sender],
required: amount
});
balance[msg.sender] -= amount;
balance[to] += amount;
}
// ...
}
and
contract TestToken {
mapping(address => uint) balance;
error InsufficientBalance(uint256 available, uint256 required);
function transfer(address to, uint256 amount) public {
require(balance[msg.sender]<amount, "Insufficient Balance");
balance[msg.sender] -= amount;
balance[to] += amount;
}
// ...
}
to handle error in solidity
From the low-level standpoint, both approaches are the same. Both throw an exception with an array of bytes as the exception data.
You can catch
both errors in the low-level catch (bytes memory)
block
function foo() public {
try this.transfer(address(0x123), 2) {
// ok
} catch (bytes memory data) {
// returns either the encoded object or the encoded string
}
}
But you can only catch
the string-encoded error with the "regular" catch Error(string memory)
block
function foo() public {
try this.transfer(address(0x123), 2) {
// ok
} catch Error (string memory reason) {
// returns the string message
// fails to catch if an object is returned
}
}
Docs: https://docs.soliditylang.org/en/v0.8.13/control-structures.html#try-catch
Note that there is a logical error in the second snippet.
// `balance` needs to be lower than `amount`
// otherwise fail
require(balance[msg.sender]<amount, "Insufficient Balance");
should be
// `balance` needs to be larger or equal than `amount`
// otherwise fail
require(balance[msg.sender] => amount, "Insufficient Balance");