Commit 3682c657 by Balaji Pachai Committed by Nicolás Venturo

Added message string for require() (#1704)

* Error handling in ERC20 and ERC721

* Added message string for require.

* Fixed solhint errors.

* Updated PR as per issue #1709

* changes as per #1709 and openzeppelin forum.

* Changes in require statement

* Changes in require statement

* build pipeline fix

* Changes as per @nventuro's comment.

* Update revert reason strings.

* Fianal update of revert reason strings.

* WIP: Updating reason strings in test cases

* WIP: Added changes to ERC20 and ERC721

* Fixes linting errors in *.tes.js files

* Achieved 100% code coverage

* Updated the test cases with shouldFail.reverting.withMessage()

* Fix package-lock.

* address review comments

* fix linter issues

* fix remaining revert reasons
parent 4a0a67b0
...@@ -13,8 +13,7 @@ library Roles { ...@@ -13,8 +13,7 @@ library Roles {
* @dev Give an account access to this role. * @dev Give an account access to this role.
*/ */
function add(Role storage role, address account) internal { function add(Role storage role, address account) internal {
require(!has(role, account)); require(!has(role, account), "Roles: account already has role");
role.bearer[account] = true; role.bearer[account] = true;
} }
...@@ -22,8 +21,7 @@ library Roles { ...@@ -22,8 +21,7 @@ library Roles {
* @dev Remove an account's access to this role. * @dev Remove an account's access to this role.
*/ */
function remove(Role storage role, address account) internal { function remove(Role storage role, address account) internal {
require(has(role, account)); require(has(role, account), "Roles: account does not have role");
role.bearer[account] = false; role.bearer[account] = false;
} }
...@@ -32,7 +30,7 @@ library Roles { ...@@ -32,7 +30,7 @@ library Roles {
* @return bool * @return bool
*/ */
function has(Role storage role, address account) internal view returns (bool) { function has(Role storage role, address account) internal view returns (bool) {
require(account != address(0)); require(account != address(0), "Roles: account is the zero address");
return role.bearer[account]; return role.bearer[account];
} }
} }
...@@ -15,7 +15,7 @@ contract CapperRole { ...@@ -15,7 +15,7 @@ contract CapperRole {
} }
modifier onlyCapper() { modifier onlyCapper() {
require(isCapper(msg.sender)); require(isCapper(msg.sender), "CapperRole: caller does not have the Capper role");
_; _;
} }
......
...@@ -15,7 +15,7 @@ contract MinterRole { ...@@ -15,7 +15,7 @@ contract MinterRole {
} }
modifier onlyMinter() { modifier onlyMinter() {
require(isMinter(msg.sender)); require(isMinter(msg.sender), "MinterRole: caller does not have the Minter role");
_; _;
} }
......
...@@ -15,7 +15,7 @@ contract PauserRole { ...@@ -15,7 +15,7 @@ contract PauserRole {
} }
modifier onlyPauser() { modifier onlyPauser() {
require(isPauser(msg.sender)); require(isPauser(msg.sender), "PauserRole: caller does not have the Pauser role");
_; _;
} }
......
...@@ -15,7 +15,7 @@ contract SignerRole { ...@@ -15,7 +15,7 @@ contract SignerRole {
} }
modifier onlySigner() { modifier onlySigner() {
require(isSigner(msg.sender)); require(isSigner(msg.sender), "SignerRole: caller does not have the Signer role");
_; _;
} }
......
...@@ -19,7 +19,7 @@ contract WhitelistAdminRole { ...@@ -19,7 +19,7 @@ contract WhitelistAdminRole {
} }
modifier onlyWhitelistAdmin() { modifier onlyWhitelistAdmin() {
require(isWhitelistAdmin(msg.sender)); require(isWhitelistAdmin(msg.sender), "WhitelistAdminRole: caller does not have the WhitelistAdmin role");
_; _;
} }
......
...@@ -18,7 +18,7 @@ contract WhitelistedRole is WhitelistAdminRole { ...@@ -18,7 +18,7 @@ contract WhitelistedRole is WhitelistAdminRole {
Roles.Role private _whitelisteds; Roles.Role private _whitelisteds;
modifier onlyWhitelisted() { modifier onlyWhitelisted() {
require(isWhitelisted(msg.sender)); require(isWhitelisted(msg.sender), "WhitelistedRole: caller does not have the Whitelisted role");
_; _;
} }
......
...@@ -54,9 +54,9 @@ contract Crowdsale is ReentrancyGuard { ...@@ -54,9 +54,9 @@ contract Crowdsale is ReentrancyGuard {
* @param token Address of the token being sold * @param token Address of the token being sold
*/ */
constructor (uint256 rate, address payable wallet, IERC20 token) public { constructor (uint256 rate, address payable wallet, IERC20 token) public {
require(rate > 0); require(rate > 0, "Crowdsale: rate is 0");
require(wallet != address(0)); require(wallet != address(0), "Crowdsale: wallet is the zero address");
require(address(token) != address(0)); require(address(token) != address(0), "Crowdsale: token is the zero address");
_rate = rate; _rate = rate;
_wallet = wallet; _wallet = wallet;
...@@ -136,8 +136,8 @@ contract Crowdsale is ReentrancyGuard { ...@@ -136,8 +136,8 @@ contract Crowdsale is ReentrancyGuard {
* @param weiAmount Value in wei involved in the purchase * @param weiAmount Value in wei involved in the purchase
*/ */
function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view { function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
require(beneficiary != address(0)); require(beneficiary != address(0), "Crowdsale: beneficiary is the zero address");
require(weiAmount != 0); require(weiAmount != 0, "Crowdsale: weiAmount is 0");
} }
/** /**
......
...@@ -31,8 +31,8 @@ contract FinalizableCrowdsale is TimedCrowdsale { ...@@ -31,8 +31,8 @@ contract FinalizableCrowdsale is TimedCrowdsale {
* work. Calls the contract's finalization function. * work. Calls the contract's finalization function.
*/ */
function finalize() public { function finalize() public {
require(!_finalized); require(!_finalized, "FinalizableCrowdsale: already finalized");
require(hasClosed()); require(hasClosed(), "FinalizableCrowdsale: not closed");
_finalized = true; _finalized = true;
......
...@@ -24,9 +24,9 @@ contract PostDeliveryCrowdsale is TimedCrowdsale { ...@@ -24,9 +24,9 @@ contract PostDeliveryCrowdsale is TimedCrowdsale {
* @param beneficiary Whose tokens will be withdrawn. * @param beneficiary Whose tokens will be withdrawn.
*/ */
function withdrawTokens(address beneficiary) public { function withdrawTokens(address beneficiary) public {
require(hasClosed()); require(hasClosed(), "PostDeliveryCrowdsale: not closed");
uint256 amount = _balances[beneficiary]; uint256 amount = _balances[beneficiary];
require(amount > 0); require(amount > 0, "PostDeliveryCrowdsale: beneficiary is not due any tokens");
_balances[beneficiary] = 0; _balances[beneficiary] = 0;
_vault.transfer(token(), beneficiary, amount); _vault.transfer(token(), beneficiary, amount);
......
...@@ -28,7 +28,7 @@ contract RefundableCrowdsale is FinalizableCrowdsale { ...@@ -28,7 +28,7 @@ contract RefundableCrowdsale is FinalizableCrowdsale {
* @param goal Funding goal * @param goal Funding goal
*/ */
constructor (uint256 goal) public { constructor (uint256 goal) public {
require(goal > 0); require(goal > 0, "RefundableCrowdsale: goal is 0");
_escrow = new RefundEscrow(wallet()); _escrow = new RefundEscrow(wallet());
_goal = goal; _goal = goal;
} }
...@@ -45,8 +45,8 @@ contract RefundableCrowdsale is FinalizableCrowdsale { ...@@ -45,8 +45,8 @@ contract RefundableCrowdsale is FinalizableCrowdsale {
* @param refundee Whose refund will be claimed. * @param refundee Whose refund will be claimed.
*/ */
function claimRefund(address payable refundee) public { function claimRefund(address payable refundee) public {
require(finalized()); require(finalized(), "RefundableCrowdsale: not finalized");
require(!goalReached()); require(!goalReached(), "RefundableCrowdsale: goal reached");
_escrow.withdraw(refundee); _escrow.withdraw(refundee);
} }
......
...@@ -12,8 +12,8 @@ import "./PostDeliveryCrowdsale.sol"; ...@@ -12,8 +12,8 @@ import "./PostDeliveryCrowdsale.sol";
*/ */
contract RefundablePostDeliveryCrowdsale is RefundableCrowdsale, PostDeliveryCrowdsale { contract RefundablePostDeliveryCrowdsale is RefundableCrowdsale, PostDeliveryCrowdsale {
function withdrawTokens(address beneficiary) public { function withdrawTokens(address beneficiary) public {
require(finalized()); require(finalized(), "RefundablePostDeliveryCrowdsale: not finalized");
require(goalReached()); require(goalReached(), "RefundablePostDeliveryCrowdsale: goal not reached");
super.withdrawTokens(beneficiary); super.withdrawTokens(beneficiary);
} }
......
...@@ -21,7 +21,7 @@ contract AllowanceCrowdsale is Crowdsale { ...@@ -21,7 +21,7 @@ contract AllowanceCrowdsale is Crowdsale {
* @param tokenWallet Address holding the tokens, which has approved allowance to the crowdsale. * @param tokenWallet Address holding the tokens, which has approved allowance to the crowdsale.
*/ */
constructor (address tokenWallet) public { constructor (address tokenWallet) public {
require(tokenWallet != address(0)); require(tokenWallet != address(0), "AllowanceCrowdsale: token wallet is the zero address");
_tokenWallet = tokenWallet; _tokenWallet = tokenWallet;
} }
......
...@@ -16,6 +16,9 @@ contract MintedCrowdsale is Crowdsale { ...@@ -16,6 +16,9 @@ contract MintedCrowdsale is Crowdsale {
*/ */
function _deliverTokens(address beneficiary, uint256 tokenAmount) internal { function _deliverTokens(address beneficiary, uint256 tokenAmount) internal {
// Potentially dangerous assumption about the type of the token. // Potentially dangerous assumption about the type of the token.
require(ERC20Mintable(address(token())).mint(beneficiary, tokenAmount)); require(
ERC20Mintable(address(token())).mint(beneficiary, tokenAmount),
"MintedCrowdsale: minting failed"
);
} }
} }
...@@ -21,8 +21,9 @@ contract IncreasingPriceCrowdsale is TimedCrowdsale { ...@@ -21,8 +21,9 @@ contract IncreasingPriceCrowdsale is TimedCrowdsale {
* @param finalRate Number of tokens a buyer gets per wei at the end of the crowdsale * @param finalRate Number of tokens a buyer gets per wei at the end of the crowdsale
*/ */
constructor (uint256 initialRate, uint256 finalRate) public { constructor (uint256 initialRate, uint256 finalRate) public {
require(finalRate > 0); require(finalRate > 0, "IncreasingPriceCrowdsale: final rate is 0");
require(initialRate > finalRate); // solhint-disable-next-line max-line-length
require(initialRate > finalRate, "IncreasingPriceCrowdsale: initial rate is not greater than final rate");
_initialRate = initialRate; _initialRate = initialRate;
_finalRate = finalRate; _finalRate = finalRate;
} }
...@@ -32,7 +33,7 @@ contract IncreasingPriceCrowdsale is TimedCrowdsale { ...@@ -32,7 +33,7 @@ contract IncreasingPriceCrowdsale is TimedCrowdsale {
* all calls to it are a mistake. * all calls to it are a mistake.
*/ */
function rate() public view returns (uint256) { function rate() public view returns (uint256) {
revert(); revert("IncreasingPriceCrowdsale: rate() called");
} }
/** /**
......
...@@ -17,7 +17,7 @@ contract CappedCrowdsale is Crowdsale { ...@@ -17,7 +17,7 @@ contract CappedCrowdsale is Crowdsale {
* @param cap Max amount of wei to be contributed * @param cap Max amount of wei to be contributed
*/ */
constructor (uint256 cap) public { constructor (uint256 cap) public {
require(cap > 0); require(cap > 0, "CappedCrowdsale: cap is 0");
_cap = cap; _cap = cap;
} }
...@@ -43,6 +43,6 @@ contract CappedCrowdsale is Crowdsale { ...@@ -43,6 +43,6 @@ contract CappedCrowdsale is Crowdsale {
*/ */
function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view { function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
super._preValidatePurchase(beneficiary, weiAmount); super._preValidatePurchase(beneficiary, weiAmount);
require(weiRaised().add(weiAmount) <= _cap); require(weiRaised().add(weiAmount) <= _cap, "CappedCrowdsale: cap exceeded");
} }
} }
...@@ -48,7 +48,8 @@ contract IndividuallyCappedCrowdsale is Crowdsale, CapperRole { ...@@ -48,7 +48,8 @@ contract IndividuallyCappedCrowdsale is Crowdsale, CapperRole {
*/ */
function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view { function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
super._preValidatePurchase(beneficiary, weiAmount); super._preValidatePurchase(beneficiary, weiAmount);
require(_contributions[beneficiary].add(weiAmount) <= _caps[beneficiary]); // solhint-disable-next-line max-line-length
require(_contributions[beneficiary].add(weiAmount) <= _caps[beneficiary], "IndividuallyCappedCrowdsale: beneficiary's cap exceeded");
} }
/** /**
......
...@@ -24,7 +24,7 @@ contract TimedCrowdsale is Crowdsale { ...@@ -24,7 +24,7 @@ contract TimedCrowdsale is Crowdsale {
* @dev Reverts if not in crowdsale time range. * @dev Reverts if not in crowdsale time range.
*/ */
modifier onlyWhileOpen { modifier onlyWhileOpen {
require(isOpen()); require(isOpen(), "TimedCrowdsale: not open");
_; _;
} }
...@@ -35,8 +35,9 @@ contract TimedCrowdsale is Crowdsale { ...@@ -35,8 +35,9 @@ contract TimedCrowdsale is Crowdsale {
*/ */
constructor (uint256 openingTime, uint256 closingTime) public { constructor (uint256 openingTime, uint256 closingTime) public {
// solhint-disable-next-line not-rely-on-time // solhint-disable-next-line not-rely-on-time
require(openingTime >= block.timestamp); require(openingTime >= block.timestamp, "TimedCrowdsale: opening time is before current time");
require(closingTime > openingTime); // solhint-disable-next-line max-line-length
require(closingTime > openingTime, "TimedCrowdsale: opening time is not before closing time");
_openingTime = openingTime; _openingTime = openingTime;
_closingTime = closingTime; _closingTime = closingTime;
...@@ -87,8 +88,9 @@ contract TimedCrowdsale is Crowdsale { ...@@ -87,8 +88,9 @@ contract TimedCrowdsale is Crowdsale {
* @param newClosingTime Crowdsale closing time * @param newClosingTime Crowdsale closing time
*/ */
function _extendTime(uint256 newClosingTime) internal { function _extendTime(uint256 newClosingTime) internal {
require(!hasClosed()); require(!hasClosed(), "TimedCrowdsale: already closed");
require(newClosingTime > _closingTime); // solhint-disable-next-line max-line-length
require(newClosingTime > _closingTime, "TimedCrowdsale: new closing time is before current closing time");
emit TimedCrowdsaleExtended(_closingTime, newClosingTime); emit TimedCrowdsaleExtended(_closingTime, newClosingTime);
_closingTime = newClosingTime; _closingTime = newClosingTime;
......
...@@ -15,7 +15,7 @@ contract WhitelistCrowdsale is WhitelistedRole, Crowdsale { ...@@ -15,7 +15,7 @@ contract WhitelistCrowdsale is WhitelistedRole, Crowdsale {
* @param _weiAmount Amount of wei contributed * @param _weiAmount Amount of wei contributed
*/ */
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal view { function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal view {
require(isWhitelisted(_beneficiary)); require(isWhitelisted(_beneficiary), "WhitelistCrowdsale: beneficiary doesn't have the Whitelisted role");
super._preValidatePurchase(_beneficiary, _weiAmount); super._preValidatePurchase(_beneficiary, _weiAmount);
} }
} }
...@@ -44,7 +44,7 @@ contract ERC20Migrator { ...@@ -44,7 +44,7 @@ contract ERC20Migrator {
* @param legacyToken address of the old token contract * @param legacyToken address of the old token contract
*/ */
constructor (IERC20 legacyToken) public { constructor (IERC20 legacyToken) public {
require(address(legacyToken) != address(0)); require(address(legacyToken) != address(0), "ERC20Migrator: legacy token is the zero address");
_legacyToken = legacyToken; _legacyToken = legacyToken;
} }
...@@ -68,9 +68,10 @@ contract ERC20Migrator { ...@@ -68,9 +68,10 @@ contract ERC20Migrator {
* @param newToken_ the token that will be minted * @param newToken_ the token that will be minted
*/ */
function beginMigration(ERC20Mintable newToken_) public { function beginMigration(ERC20Mintable newToken_) public {
require(address(_newToken) == address(0)); require(address(_newToken) == address(0), "ERC20Migrator: migration already started");
require(address(newToken_) != address(0)); require(address(newToken_) != address(0), "ERC20Migrator: new token is the zero address");
require(newToken_.isMinter(address(this))); //solhint-disable-next-line max-line-length
require(newToken_.isMinter(address(this)), "ERC20Migrator: not a minter for new token");
_newToken = newToken_; _newToken = newToken_;
} }
...@@ -82,7 +83,7 @@ contract ERC20Migrator { ...@@ -82,7 +83,7 @@ contract ERC20Migrator {
* @param amount amount of tokens to be migrated * @param amount amount of tokens to be migrated
*/ */
function migrate(address account, uint256 amount) public { function migrate(address account, uint256 amount) public {
require(address(_newToken) != address(0)); require(address(_newToken) != address(0), "ERC20Migrator: migration not started");
_legacyToken.safeTransferFrom(account, address(this), amount); _legacyToken.safeTransferFrom(account, address(this), amount);
_newToken.mint(account, amount); _newToken.mint(account, amount);
} }
......
...@@ -101,8 +101,9 @@ contract ERC20Snapshot is ERC20 { ...@@ -101,8 +101,9 @@ contract ERC20Snapshot is ERC20 {
function _valueAt(uint256 snapshotId, Snapshots storage snapshots) function _valueAt(uint256 snapshotId, Snapshots storage snapshots)
private view returns (bool, uint256) private view returns (bool, uint256)
{ {
require(snapshotId > 0); require(snapshotId > 0, "ERC20Snapshot: id is 0");
require(snapshotId <= _currentSnapshotId.current()); // solhint-disable-next-line max-line-length
require(snapshotId <= _currentSnapshotId.current(), "ERC20Snapshot: nonexistent id");
uint256 index = snapshots.ids.findUpperBound(snapshotId); uint256 index = snapshots.ids.findUpperBound(snapshotId);
......
...@@ -51,7 +51,7 @@ contract SignatureBouncer is SignerRole { ...@@ -51,7 +51,7 @@ contract SignatureBouncer is SignerRole {
* @dev Requires that a valid signature of a signer was provided. * @dev Requires that a valid signature of a signer was provided.
*/ */
modifier onlyValidSignature(bytes memory signature) { modifier onlyValidSignature(bytes memory signature) {
require(_isValidSignature(msg.sender, signature)); require(_isValidSignature(msg.sender, signature), "SignatureBouncer: invalid signature for caller");
_; _;
} }
...@@ -59,7 +59,8 @@ contract SignatureBouncer is SignerRole { ...@@ -59,7 +59,8 @@ contract SignatureBouncer is SignerRole {
* @dev Requires that a valid signature with a specified method of a signer was provided. * @dev Requires that a valid signature with a specified method of a signer was provided.
*/ */
modifier onlyValidSignatureAndMethod(bytes memory signature) { modifier onlyValidSignatureAndMethod(bytes memory signature) {
require(_isValidSignatureAndMethod(msg.sender, signature)); // solhint-disable-next-line max-line-length
require(_isValidSignatureAndMethod(msg.sender, signature), "SignatureBouncer: invalid signature for caller and method");
_; _;
} }
...@@ -67,7 +68,8 @@ contract SignatureBouncer is SignerRole { ...@@ -67,7 +68,8 @@ contract SignatureBouncer is SignerRole {
* @dev Requires that a valid signature with a specified method and params of a signer was provided. * @dev Requires that a valid signature with a specified method and params of a signer was provided.
*/ */
modifier onlyValidSignatureAndData(bytes memory signature) { modifier onlyValidSignatureAndData(bytes memory signature) {
require(_isValidSignatureAndData(msg.sender, signature)); // solhint-disable-next-line max-line-length
require(_isValidSignatureAndData(msg.sender, signature), "SignatureBouncer: invalid signature for caller and data");
_; _;
} }
...@@ -97,7 +99,7 @@ contract SignatureBouncer is SignerRole { ...@@ -97,7 +99,7 @@ contract SignatureBouncer is SignerRole {
* @return bool * @return bool
*/ */
function _isValidSignatureAndData(address account, bytes memory signature) internal view returns (bool) { function _isValidSignatureAndData(address account, bytes memory signature) internal view returns (bool) {
require(msg.data.length > _SIGNATURE_SIZE); require(msg.data.length > _SIGNATURE_SIZE, "SignatureBouncer: data is too short");
bytes memory data = new bytes(msg.data.length - _SIGNATURE_SIZE); bytes memory data = new bytes(msg.data.length - _SIGNATURE_SIZE);
for (uint i = 0; i < data.length; i++) { for (uint i = 0; i < data.length; i++) {
......
...@@ -18,10 +18,10 @@ library SignedSafeMath { ...@@ -18,10 +18,10 @@ library SignedSafeMath {
return 0; return 0;
} }
require(!(a == -1 && b == INT256_MIN)); // This is the only case of overflow not detected by the check below require(!(a == -1 && b == INT256_MIN), "SignedSafeMath: multiplication overflow");
int256 c = a * b; int256 c = a * b;
require(c / a == b); require(c / a == b, "SignedSafeMath: multiplication overflow");
return c; return c;
} }
...@@ -30,8 +30,8 @@ library SignedSafeMath { ...@@ -30,8 +30,8 @@ library SignedSafeMath {
* @dev Integer division of two signed integers truncating the quotient, reverts on division by zero. * @dev Integer division of two signed integers truncating the quotient, reverts on division by zero.
*/ */
function div(int256 a, int256 b) internal pure returns (int256) { function div(int256 a, int256 b) internal pure returns (int256) {
require(b != 0); // Solidity only automatically asserts when dividing by 0 require(b != 0, "SignedSafeMath: division by zero");
require(!(b == -1 && a == INT256_MIN)); // This is the only case of overflow require(!(b == -1 && a == INT256_MIN), "SignedSafeMath: division overflow");
int256 c = a / b; int256 c = a / b;
...@@ -43,7 +43,7 @@ library SignedSafeMath { ...@@ -43,7 +43,7 @@ library SignedSafeMath {
*/ */
function sub(int256 a, int256 b) internal pure returns (int256) { function sub(int256 a, int256 b) internal pure returns (int256) {
int256 c = a - b; int256 c = a - b;
require((b >= 0 && c <= a) || (b < 0 && c > a)); require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow");
return c; return c;
} }
...@@ -53,7 +53,7 @@ library SignedSafeMath { ...@@ -53,7 +53,7 @@ library SignedSafeMath {
*/ */
function add(int256 a, int256 b) internal pure returns (int256) { function add(int256 a, int256 b) internal pure returns (int256) {
int256 c = a + b; int256 c = a + b;
require((b >= 0 && c >= a) || (b < 0 && c < a)); require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow");
return c; return c;
} }
......
...@@ -47,10 +47,12 @@ contract TokenVesting is Ownable { ...@@ -47,10 +47,12 @@ contract TokenVesting is Ownable {
* @param revocable whether the vesting is revocable or not * @param revocable whether the vesting is revocable or not
*/ */
constructor (address beneficiary, uint256 start, uint256 cliffDuration, uint256 duration, bool revocable) public { constructor (address beneficiary, uint256 start, uint256 cliffDuration, uint256 duration, bool revocable) public {
require(beneficiary != address(0)); require(beneficiary != address(0), "TokenVesting: beneficiary is the zero address");
require(cliffDuration <= duration); // solhint-disable-next-line max-line-length
require(duration > 0); require(cliffDuration <= duration, "TokenVesting: cliff is longer than duration");
require(start.add(duration) > block.timestamp); require(duration > 0, "TokenVesting: duration is 0");
// solhint-disable-next-line max-line-length
require(start.add(duration) > block.timestamp, "TokenVesting: final time is before current time");
_beneficiary = beneficiary; _beneficiary = beneficiary;
_revocable = revocable; _revocable = revocable;
...@@ -115,7 +117,7 @@ contract TokenVesting is Ownable { ...@@ -115,7 +117,7 @@ contract TokenVesting is Ownable {
function release(IERC20 token) public { function release(IERC20 token) public {
uint256 unreleased = _releasableAmount(token); uint256 unreleased = _releasableAmount(token);
require(unreleased > 0); require(unreleased > 0, "TokenVesting: no tokens are due");
_released[address(token)] = _released[address(token)].add(unreleased); _released[address(token)] = _released[address(token)].add(unreleased);
...@@ -130,8 +132,8 @@ contract TokenVesting is Ownable { ...@@ -130,8 +132,8 @@ contract TokenVesting is Ownable {
* @param token ERC20 token which is being vested * @param token ERC20 token which is being vested
*/ */
function revoke(IERC20 token) public onlyOwner { function revoke(IERC20 token) public onlyOwner {
require(_revocable); require(_revocable, "TokenVesting: cannot revoke");
require(!_revoked[address(token)]); require(!_revoked[address(token)], "TokenVesting: token already revoked");
uint256 balance = token.balanceOf(address(this)); uint256 balance = token.balanceOf(address(this));
......
...@@ -48,6 +48,6 @@ contract SampleCrowdsale is CappedCrowdsale, RefundableCrowdsale, MintedCrowdsal ...@@ -48,6 +48,6 @@ contract SampleCrowdsale is CappedCrowdsale, RefundableCrowdsale, MintedCrowdsal
{ {
//As goal needs to be met for a successful crowdsale //As goal needs to be met for a successful crowdsale
//the value needs to less or equal than a cap which is limit for accepted funds //the value needs to less or equal than a cap which is limit for accepted funds
require(goal <= cap); require(goal <= cap, "SampleCrowdSale: goal is greater than cap");
} }
} }
...@@ -37,7 +37,7 @@ contract ERC165 is IERC165 { ...@@ -37,7 +37,7 @@ contract ERC165 is IERC165 {
* @dev Internal method for registering an interface. * @dev Internal method for registering an interface.
*/ */
function _registerInterface(bytes4 interfaceId) internal { function _registerInterface(bytes4 interfaceId) internal {
require(interfaceId != 0xffffffff); require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
_supportedInterfaces[interfaceId] = true; _supportedInterfaces[interfaceId] = true;
} }
} }
...@@ -27,7 +27,7 @@ contract Pausable is PauserRole { ...@@ -27,7 +27,7 @@ contract Pausable is PauserRole {
* @dev Modifier to make a function callable only when the contract is not paused. * @dev Modifier to make a function callable only when the contract is not paused.
*/ */
modifier whenNotPaused() { modifier whenNotPaused() {
require(!_paused); require(!_paused, "Pausable: paused");
_; _;
} }
...@@ -35,7 +35,7 @@ contract Pausable is PauserRole { ...@@ -35,7 +35,7 @@ contract Pausable is PauserRole {
* @dev Modifier to make a function callable only when the contract is paused. * @dev Modifier to make a function callable only when the contract is paused.
*/ */
modifier whenPaused() { modifier whenPaused() {
require(_paused); require(_paused, "Pausable: not paused");
_; _;
} }
......
...@@ -17,7 +17,7 @@ library SafeMath { ...@@ -17,7 +17,7 @@ library SafeMath {
} }
uint256 c = a * b; uint256 c = a * b;
require(c / a == b); require(c / a == b, "SafeMath: multiplication overflow");
return c; return c;
} }
...@@ -27,7 +27,7 @@ library SafeMath { ...@@ -27,7 +27,7 @@ library SafeMath {
*/ */
function div(uint256 a, uint256 b) internal pure returns (uint256) { function div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0 // Solidity only automatically asserts when dividing by 0
require(b > 0); require(b > 0, "SafeMath: division by zero");
uint256 c = a / b; uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold // assert(a == b * c + a % b); // There is no case in which this doesn't hold
...@@ -38,7 +38,7 @@ library SafeMath { ...@@ -38,7 +38,7 @@ library SafeMath {
* @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend). * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/ */
function sub(uint256 a, uint256 b) internal pure returns (uint256) { function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a); require(b <= a, "SafeMath: subtraction overflow");
uint256 c = a - b; uint256 c = a - b;
return c; return c;
...@@ -49,7 +49,7 @@ library SafeMath { ...@@ -49,7 +49,7 @@ library SafeMath {
*/ */
function add(uint256 a, uint256 b) internal pure returns (uint256) { function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b; uint256 c = a + b;
require(c >= a); require(c >= a, "SafeMath: addition overflow");
return c; return c;
} }
...@@ -59,7 +59,7 @@ library SafeMath { ...@@ -59,7 +59,7 @@ library SafeMath {
* reverts when dividing by zero. * reverts when dividing by zero.
*/ */
function mod(uint256 a, uint256 b) internal pure returns (uint256) { function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0); require(b != 0, "SafeMath: modulo by zero");
return a % b; return a % b;
} }
} }
...@@ -42,7 +42,7 @@ contract SupportsInterfaceWithLookupMock is IERC165 { ...@@ -42,7 +42,7 @@ contract SupportsInterfaceWithLookupMock is IERC165 {
* @dev Private method for registering an interface. * @dev Private method for registering an interface.
*/ */
function _registerInterface(bytes4 interfaceId) internal { function _registerInterface(bytes4 interfaceId) internal {
require(interfaceId != 0xffffffff); require(interfaceId != 0xffffffff, "ERC165InterfacesSupported: invalid interface id");
_supportedInterfaces[interfaceId] = true; _supportedInterfaces[interfaceId] = true;
} }
} }
......
...@@ -16,7 +16,7 @@ contract ERC721ReceiverMock is IERC721Receiver { ...@@ -16,7 +16,7 @@ contract ERC721ReceiverMock is IERC721Receiver {
function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data) function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
public returns (bytes4) public returns (bytes4)
{ {
require(!_reverts); require(!_reverts, "ERC721ReceiverMock: reverting");
emit Received(operator, from, tokenId, data, gasleft()); emit Received(operator, from, tokenId, data, gasleft());
return _retval; return _retval;
} }
......
...@@ -4,6 +4,6 @@ contract ReentrancyAttack { ...@@ -4,6 +4,6 @@ contract ReentrancyAttack {
function callSender(bytes4 data) public { function callSender(bytes4 data) public {
// solhint-disable-next-line avoid-low-level-calls // solhint-disable-next-line avoid-low-level-calls
(bool success,) = msg.sender.call(abi.encodeWithSelector(data)); (bool success,) = msg.sender.call(abi.encodeWithSelector(data));
require(success); require(success, "ReentrancyAttack: failed call");
} }
} }
...@@ -26,7 +26,7 @@ contract ReentrancyMock is ReentrancyGuard { ...@@ -26,7 +26,7 @@ contract ReentrancyMock is ReentrancyGuard {
count(); count();
// solhint-disable-next-line avoid-low-level-calls // solhint-disable-next-line avoid-low-level-calls
(bool success,) = address(this).call(abi.encodeWithSignature("countThisRecursive(uint256)", n - 1)); (bool success,) = address(this).call(abi.encodeWithSignature("countThisRecursive(uint256)", n - 1));
require(success); require(success, "ReentrancyMock: failed call");
} }
} }
......
...@@ -26,7 +26,7 @@ contract ERC20ReturnFalseMock { ...@@ -26,7 +26,7 @@ contract ERC20ReturnFalseMock {
} }
function allowance(address, address) public view returns (uint256) { function allowance(address, address) public view returns (uint256) {
require(_dummy == 0); require(_dummy == 0); // Duummy read from a state variable so that the function is view
return 0; return 0;
} }
} }
......
...@@ -30,7 +30,7 @@ contract Ownable { ...@@ -30,7 +30,7 @@ contract Ownable {
* @dev Throws if called by any account other than the owner. * @dev Throws if called by any account other than the owner.
*/ */
modifier onlyOwner() { modifier onlyOwner() {
require(isOwner()); require(isOwner(), "Ownable: caller is not the owner");
_; _;
} }
...@@ -66,7 +66,7 @@ contract Ownable { ...@@ -66,7 +66,7 @@ contract Ownable {
* @param newOwner The address to transfer ownership to. * @param newOwner The address to transfer ownership to.
*/ */
function _transferOwnership(address newOwner) internal { function _transferOwnership(address newOwner) internal {
require(newOwner != address(0)); require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner); emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner; _owner = newOwner;
} }
......
...@@ -23,7 +23,7 @@ contract Secondary { ...@@ -23,7 +23,7 @@ contract Secondary {
* @dev Reverts if called from any account other than the primary. * @dev Reverts if called from any account other than the primary.
*/ */
modifier onlyPrimary() { modifier onlyPrimary() {
require(msg.sender == _primary); require(msg.sender == _primary, "Secondary: caller is not the primary account");
_; _;
} }
...@@ -39,7 +39,7 @@ contract Secondary { ...@@ -39,7 +39,7 @@ contract Secondary {
* @param recipient The address of new primary. * @param recipient The address of new primary.
*/ */
function transferPrimary(address recipient) public onlyPrimary { function transferPrimary(address recipient) public onlyPrimary {
require(recipient != address(0)); require(recipient != address(0), "Secondary: new primary is the zero address");
_primary = recipient; _primary = recipient;
emit PrimaryTransferred(_primary); emit PrimaryTransferred(_primary);
} }
......
...@@ -37,8 +37,9 @@ contract PaymentSplitter { ...@@ -37,8 +37,9 @@ contract PaymentSplitter {
* duplicates in `payees`. * duplicates in `payees`.
*/ */
constructor (address[] memory payees, uint256[] memory shares) public payable { constructor (address[] memory payees, uint256[] memory shares) public payable {
require(payees.length == shares.length); // solhint-disable-next-line max-line-length
require(payees.length > 0); require(payees.length == shares.length, "PaymentSplitter: payees and shares length mismatch");
require(payees.length > 0, "PaymentSplitter: no payees");
for (uint256 i = 0; i < payees.length; i++) { for (uint256 i = 0; i < payees.length; i++) {
_addPayee(payees[i], shares[i]); _addPayee(payees[i], shares[i]);
...@@ -98,12 +99,12 @@ contract PaymentSplitter { ...@@ -98,12 +99,12 @@ contract PaymentSplitter {
* total shares and their previous withdrawals. * total shares and their previous withdrawals.
*/ */
function release(address payable account) public { function release(address payable account) public {
require(_shares[account] > 0); require(_shares[account] > 0, "PaymentSplitter: account has no shares");
uint256 totalReceived = address(this).balance.add(_totalReleased); uint256 totalReceived = address(this).balance.add(_totalReleased);
uint256 payment = totalReceived.mul(_shares[account]).div(_totalShares).sub(_released[account]); uint256 payment = totalReceived.mul(_shares[account]).div(_totalShares).sub(_released[account]);
require(payment != 0); require(payment != 0, "PaymentSplitter: account is not due payment");
_released[account] = _released[account].add(payment); _released[account] = _released[account].add(payment);
_totalReleased = _totalReleased.add(payment); _totalReleased = _totalReleased.add(payment);
...@@ -118,9 +119,9 @@ contract PaymentSplitter { ...@@ -118,9 +119,9 @@ contract PaymentSplitter {
* @param shares_ The number of shares owned by the payee. * @param shares_ The number of shares owned by the payee.
*/ */
function _addPayee(address account, uint256 shares_) private { function _addPayee(address account, uint256 shares_) private {
require(account != address(0)); require(account != address(0), "PaymentSplitter: account is the zero address");
require(shares_ > 0); require(shares_ > 0, "PaymentSplitter: shares are 0");
require(_shares[account] == 0); require(_shares[account] == 0, "PaymentSplitter: account already has shares");
_payees.push(account); _payees.push(account);
_shares[account] = shares_; _shares[account] = shares_;
......
...@@ -16,7 +16,7 @@ contract ConditionalEscrow is Escrow { ...@@ -16,7 +16,7 @@ contract ConditionalEscrow is Escrow {
function withdrawalAllowed(address payee) public view returns (bool); function withdrawalAllowed(address payee) public view returns (bool);
function withdraw(address payable payee) public { function withdraw(address payable payee) public {
require(withdrawalAllowed(payee)); require(withdrawalAllowed(payee), "ConditionalEscrow: payee is not allowed to withdraw");
super.withdraw(payee); super.withdraw(payee);
} }
} }
...@@ -27,7 +27,7 @@ contract RefundEscrow is ConditionalEscrow { ...@@ -27,7 +27,7 @@ contract RefundEscrow is ConditionalEscrow {
* @param beneficiary The beneficiary of the deposits. * @param beneficiary The beneficiary of the deposits.
*/ */
constructor (address payable beneficiary) public { constructor (address payable beneficiary) public {
require(beneficiary != address(0)); require(beneficiary != address(0), "RefundEscrow: beneficiary is the zero address");
_beneficiary = beneficiary; _beneficiary = beneficiary;
_state = State.Active; _state = State.Active;
} }
...@@ -51,7 +51,7 @@ contract RefundEscrow is ConditionalEscrow { ...@@ -51,7 +51,7 @@ contract RefundEscrow is ConditionalEscrow {
* @param refundee The address funds will be sent to if a refund occurs. * @param refundee The address funds will be sent to if a refund occurs.
*/ */
function deposit(address refundee) public payable { function deposit(address refundee) public payable {
require(_state == State.Active); require(_state == State.Active, "RefundEscrow: can only deposit while active");
super.deposit(refundee); super.deposit(refundee);
} }
...@@ -60,7 +60,7 @@ contract RefundEscrow is ConditionalEscrow { ...@@ -60,7 +60,7 @@ contract RefundEscrow is ConditionalEscrow {
* further deposits. * further deposits.
*/ */
function close() public onlyPrimary { function close() public onlyPrimary {
require(_state == State.Active); require(_state == State.Active, "RefundEscrow: can only close while active");
_state = State.Closed; _state = State.Closed;
emit RefundsClosed(); emit RefundsClosed();
} }
...@@ -69,7 +69,7 @@ contract RefundEscrow is ConditionalEscrow { ...@@ -69,7 +69,7 @@ contract RefundEscrow is ConditionalEscrow {
* @dev Allows for refunds to take place, rejecting further deposits. * @dev Allows for refunds to take place, rejecting further deposits.
*/ */
function enableRefunds() public onlyPrimary { function enableRefunds() public onlyPrimary {
require(_state == State.Active); require(_state == State.Active, "RefundEscrow: can only enable refunds while active");
_state = State.Refunding; _state = State.Refunding;
emit RefundsEnabled(); emit RefundsEnabled();
} }
...@@ -78,7 +78,7 @@ contract RefundEscrow is ConditionalEscrow { ...@@ -78,7 +78,7 @@ contract RefundEscrow is ConditionalEscrow {
* @dev Withdraws the beneficiary's funds. * @dev Withdraws the beneficiary's funds.
*/ */
function beneficiaryWithdraw() public { function beneficiaryWithdraw() public {
require(_state == State.Closed); require(_state == State.Closed, "RefundEscrow: beneficiary can only withdraw while closed");
_beneficiary.transfer(address(this).balance); _beneficiary.transfer(address(this).balance);
} }
......
...@@ -125,7 +125,7 @@ contract ERC20 is IERC20 { ...@@ -125,7 +125,7 @@ contract ERC20 is IERC20 {
* @param value The amount to be transferred. * @param value The amount to be transferred.
*/ */
function _transfer(address from, address to, uint256 value) internal { function _transfer(address from, address to, uint256 value) internal {
require(to != address(0)); require(to != address(0), "ERC20: transfer to the zero address");
_balances[from] = _balances[from].sub(value); _balances[from] = _balances[from].sub(value);
_balances[to] = _balances[to].add(value); _balances[to] = _balances[to].add(value);
...@@ -140,7 +140,7 @@ contract ERC20 is IERC20 { ...@@ -140,7 +140,7 @@ contract ERC20 is IERC20 {
* @param value The amount that will be created. * @param value The amount that will be created.
*/ */
function _mint(address account, uint256 value) internal { function _mint(address account, uint256 value) internal {
require(account != address(0)); require(account != address(0), "ERC20: mint to the zero address");
_totalSupply = _totalSupply.add(value); _totalSupply = _totalSupply.add(value);
_balances[account] = _balances[account].add(value); _balances[account] = _balances[account].add(value);
...@@ -154,7 +154,7 @@ contract ERC20 is IERC20 { ...@@ -154,7 +154,7 @@ contract ERC20 is IERC20 {
* @param value The amount that will be burnt. * @param value The amount that will be burnt.
*/ */
function _burn(address account, uint256 value) internal { function _burn(address account, uint256 value) internal {
require(account != address(0)); require(account != address(0), "ERC20: burn from the zero address");
_totalSupply = _totalSupply.sub(value); _totalSupply = _totalSupply.sub(value);
_balances[account] = _balances[account].sub(value); _balances[account] = _balances[account].sub(value);
...@@ -168,8 +168,8 @@ contract ERC20 is IERC20 { ...@@ -168,8 +168,8 @@ contract ERC20 is IERC20 {
* @param value The number of tokens that can be spent. * @param value The number of tokens that can be spent.
*/ */
function _approve(address owner, address spender, uint256 value) internal { function _approve(address owner, address spender, uint256 value) internal {
require(spender != address(0)); require(owner != address(0), "ERC20: approve from the zero address");
require(owner != address(0)); require(spender != address(0), "ERC20: approve to the zero address");
_allowed[owner][spender] = value; _allowed[owner][spender] = value;
emit Approval(owner, spender, value); emit Approval(owner, spender, value);
......
...@@ -10,7 +10,7 @@ contract ERC20Capped is ERC20Mintable { ...@@ -10,7 +10,7 @@ contract ERC20Capped is ERC20Mintable {
uint256 private _cap; uint256 private _cap;
constructor (uint256 cap) public { constructor (uint256 cap) public {
require(cap > 0); require(cap > 0, "ERC20Capped: cap is 0");
_cap = cap; _cap = cap;
} }
...@@ -22,7 +22,7 @@ contract ERC20Capped is ERC20Mintable { ...@@ -22,7 +22,7 @@ contract ERC20Capped is ERC20Mintable {
} }
function _mint(address account, uint256 value) internal { function _mint(address account, uint256 value) internal {
require(totalSupply().add(value) <= _cap); require(totalSupply().add(value) <= _cap, "ERC20Capped: cap exceeded");
super._mint(account, value); super._mint(account, value);
} }
} }
...@@ -29,7 +29,10 @@ library SafeERC20 { ...@@ -29,7 +29,10 @@ library SafeERC20 {
// safeApprove should only be called when setting an initial allowance, // safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use // or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require((value == 0) || (token.allowance(address(this), spender) == 0)); // solhint-disable-next-line max-line-length
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
} }
...@@ -57,15 +60,16 @@ library SafeERC20 { ...@@ -57,15 +60,16 @@ library SafeERC20 {
// 1. The target address is checked to verify it contains contract code // 1. The target address is checked to verify it contains contract code
// 2. The call itself is made, and success asserted // 2. The call itself is made, and success asserted
// 3. The return value is decoded, which in turn checks the size of the returned data. // 3. The return value is decoded, which in turn checks the size of the returned data.
// solhint-disable-next-line max-line-length
require(address(token).isContract()); require(address(token).isContract(), "SafeERC20: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls // solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = address(token).call(data); (bool success, bytes memory returndata) = address(token).call(data);
require(success); require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional if (returndata.length > 0) { // Return data is optional
require(abi.decode(returndata, (bool))); // solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
} }
} }
} }
...@@ -21,7 +21,7 @@ contract TokenTimelock { ...@@ -21,7 +21,7 @@ contract TokenTimelock {
constructor (IERC20 token, address beneficiary, uint256 releaseTime) public { constructor (IERC20 token, address beneficiary, uint256 releaseTime) public {
// solhint-disable-next-line not-rely-on-time // solhint-disable-next-line not-rely-on-time
require(releaseTime > block.timestamp); require(releaseTime > block.timestamp, "TokenTimelock: release time is before current time");
_token = token; _token = token;
_beneficiary = beneficiary; _beneficiary = beneficiary;
_releaseTime = releaseTime; _releaseTime = releaseTime;
...@@ -53,10 +53,10 @@ contract TokenTimelock { ...@@ -53,10 +53,10 @@ contract TokenTimelock {
*/ */
function release() public { function release() public {
// solhint-disable-next-line not-rely-on-time // solhint-disable-next-line not-rely-on-time
require(block.timestamp >= _releaseTime); require(block.timestamp >= _releaseTime, "TokenTimelock: current time is before release time");
uint256 amount = _token.balanceOf(address(this)); uint256 amount = _token.balanceOf(address(this));
require(amount > 0); require(amount > 0, "TokenTimelock: no tokens to release");
_token.safeTransfer(_beneficiary, amount); _token.safeTransfer(_beneficiary, amount);
} }
......
...@@ -59,7 +59,8 @@ contract ERC721 is ERC165, IERC721 { ...@@ -59,7 +59,8 @@ contract ERC721 is ERC165, IERC721 {
* @return uint256 representing the amount owned by the passed address * @return uint256 representing the amount owned by the passed address
*/ */
function balanceOf(address owner) public view returns (uint256) { function balanceOf(address owner) public view returns (uint256) {
require(owner != address(0)); require(owner != address(0), "ERC721: balance query for the zero address");
return _ownedTokensCount[owner].current(); return _ownedTokensCount[owner].current();
} }
...@@ -70,7 +71,8 @@ contract ERC721 is ERC165, IERC721 { ...@@ -70,7 +71,8 @@ contract ERC721 is ERC165, IERC721 {
*/ */
function ownerOf(uint256 tokenId) public view returns (address) { function ownerOf(uint256 tokenId) public view returns (address) {
address owner = _tokenOwner[tokenId]; address owner = _tokenOwner[tokenId];
require(owner != address(0)); require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner; return owner;
} }
...@@ -84,8 +86,11 @@ contract ERC721 is ERC165, IERC721 { ...@@ -84,8 +86,11 @@ contract ERC721 is ERC165, IERC721 {
*/ */
function approve(address to, uint256 tokenId) public { function approve(address to, uint256 tokenId) public {
address owner = ownerOf(tokenId); address owner = ownerOf(tokenId);
require(to != owner); require(to != owner, "ERC721: transfer to current owner");
require(msg.sender == owner || isApprovedForAll(owner, msg.sender));
require(msg.sender == owner || isApprovedForAll(owner, msg.sender),
"ERC721: approve caller is not owner nor approved for all"
);
_tokenApprovals[tokenId] = to; _tokenApprovals[tokenId] = to;
emit Approval(owner, to, tokenId); emit Approval(owner, to, tokenId);
...@@ -98,7 +103,8 @@ contract ERC721 is ERC165, IERC721 { ...@@ -98,7 +103,8 @@ contract ERC721 is ERC165, IERC721 {
* @return address currently approved for the given token ID * @return address currently approved for the given token ID
*/ */
function getApproved(uint256 tokenId) public view returns (address) { function getApproved(uint256 tokenId) public view returns (address) {
require(_exists(tokenId)); require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId]; return _tokenApprovals[tokenId];
} }
...@@ -109,7 +115,8 @@ contract ERC721 is ERC165, IERC721 { ...@@ -109,7 +115,8 @@ contract ERC721 is ERC165, IERC721 {
* @param approved representing the status of the approval to be set * @param approved representing the status of the approval to be set
*/ */
function setApprovalForAll(address to, bool approved) public { function setApprovalForAll(address to, bool approved) public {
require(to != msg.sender); require(to != msg.sender, "ERC721: approve to caller");
_operatorApprovals[msg.sender][to] = approved; _operatorApprovals[msg.sender][to] = approved;
emit ApprovalForAll(msg.sender, to, approved); emit ApprovalForAll(msg.sender, to, approved);
} }
...@@ -133,7 +140,8 @@ contract ERC721 is ERC165, IERC721 { ...@@ -133,7 +140,8 @@ contract ERC721 is ERC165, IERC721 {
* @param tokenId uint256 ID of the token to be transferred * @param tokenId uint256 ID of the token to be transferred
*/ */
function transferFrom(address from, address to, uint256 tokenId) public { function transferFrom(address from, address to, uint256 tokenId) public {
require(_isApprovedOrOwner(msg.sender, tokenId)); //solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: transfer caller is not owner nor approved");
_transferFrom(from, to, tokenId); _transferFrom(from, to, tokenId);
} }
...@@ -167,7 +175,7 @@ contract ERC721 is ERC165, IERC721 { ...@@ -167,7 +175,7 @@ contract ERC721 is ERC165, IERC721 {
*/ */
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public { function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public {
transferFrom(from, to, tokenId); transferFrom(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data)); require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
} }
/** /**
...@@ -188,6 +196,7 @@ contract ERC721 is ERC165, IERC721 { ...@@ -188,6 +196,7 @@ contract ERC721 is ERC165, IERC721 {
* is an operator of the owner, or is the owner of the token * is an operator of the owner, or is the owner of the token
*/ */
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) { function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ownerOf(tokenId); address owner = ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
} }
...@@ -199,8 +208,8 @@ contract ERC721 is ERC165, IERC721 { ...@@ -199,8 +208,8 @@ contract ERC721 is ERC165, IERC721 {
* @param tokenId uint256 ID of the token to be minted * @param tokenId uint256 ID of the token to be minted
*/ */
function _mint(address to, uint256 tokenId) internal { function _mint(address to, uint256 tokenId) internal {
require(to != address(0)); require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId)); require(!_exists(tokenId), "ERC721: token already minted");
_tokenOwner[tokenId] = to; _tokenOwner[tokenId] = to;
_ownedTokensCount[to].increment(); _ownedTokensCount[to].increment();
...@@ -216,7 +225,7 @@ contract ERC721 is ERC165, IERC721 { ...@@ -216,7 +225,7 @@ contract ERC721 is ERC165, IERC721 {
* @param tokenId uint256 ID of the token being burned * @param tokenId uint256 ID of the token being burned
*/ */
function _burn(address owner, uint256 tokenId) internal { function _burn(address owner, uint256 tokenId) internal {
require(ownerOf(tokenId) == owner); require(ownerOf(tokenId) == owner, "ERC721: burn of token that is not own");
_clearApproval(tokenId); _clearApproval(tokenId);
...@@ -243,8 +252,8 @@ contract ERC721 is ERC165, IERC721 { ...@@ -243,8 +252,8 @@ contract ERC721 is ERC165, IERC721 {
* @param tokenId uint256 ID of the token to be transferred * @param tokenId uint256 ID of the token to be transferred
*/ */
function _transferFrom(address from, address to, uint256 tokenId) internal { function _transferFrom(address from, address to, uint256 tokenId) internal {
require(ownerOf(tokenId) == from); require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
require(to != address(0)); require(to != address(0), "ERC721: transfer to the zero address");
_clearApproval(tokenId); _clearApproval(tokenId);
......
...@@ -12,7 +12,8 @@ contract ERC721Burnable is ERC721 { ...@@ -12,7 +12,8 @@ contract ERC721Burnable is ERC721 {
* @param tokenId uint256 id of the ERC721 token to be burned. * @param tokenId uint256 id of the ERC721 token to be burned.
*/ */
function burn(uint256 tokenId) public { function burn(uint256 tokenId) public {
require(_isApprovedOrOwner(msg.sender, tokenId)); //solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721Burnable: caller is not owner nor approved");
_burn(tokenId); _burn(tokenId);
} }
} }
...@@ -45,7 +45,7 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { ...@@ -45,7 +45,7 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable {
* @return uint256 token ID at the given index of the tokens list owned by the requested address * @return uint256 token ID at the given index of the tokens list owned by the requested address
*/ */
function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) { function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) {
require(index < balanceOf(owner)); require(index < balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
return _ownedTokens[owner][index]; return _ownedTokens[owner][index];
} }
...@@ -64,7 +64,7 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { ...@@ -64,7 +64,7 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable {
* @return uint256 token ID at the given index of the tokens list * @return uint256 token ID at the given index of the tokens list
*/ */
function tokenByIndex(uint256 index) public view returns (uint256) { function tokenByIndex(uint256 index) public view returns (uint256) {
require(index < totalSupply()); require(index < totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index]; return _allTokens[index];
} }
......
...@@ -56,7 +56,7 @@ contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { ...@@ -56,7 +56,7 @@ contract ERC721Metadata is ERC165, ERC721, IERC721Metadata {
* @param tokenId uint256 ID of the token to query * @param tokenId uint256 ID of the token to query
*/ */
function tokenURI(uint256 tokenId) external view returns (string memory) { function tokenURI(uint256 tokenId) external view returns (string memory) {
require(_exists(tokenId)); require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
return _tokenURIs[tokenId]; return _tokenURIs[tokenId];
} }
...@@ -67,7 +67,7 @@ contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { ...@@ -67,7 +67,7 @@ contract ERC721Metadata is ERC165, ERC721, IERC721Metadata {
* @param uri string URI to assign * @param uri string URI to assign
*/ */
function _setTokenURI(uint256 tokenId, string memory uri) internal { function _setTokenURI(uint256 tokenId, string memory uri) internal {
require(_exists(tokenId)); require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
_tokenURIs[tokenId] = uri; _tokenURIs[tokenId] = uri;
} }
......
...@@ -27,6 +27,6 @@ contract ReentrancyGuard { ...@@ -27,6 +27,6 @@ contract ReentrancyGuard {
_guardCounter += 1; _guardCounter += 1;
uint256 localCounter = _guardCounter; uint256 localCounter = _guardCounter;
_; _;
require(localCounter == _guardCounter); require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call");
} }
} }
...@@ -9,7 +9,7 @@ contract('Roles', function ([_, authorized, otherAuthorized, other]) { ...@@ -9,7 +9,7 @@ contract('Roles', function ([_, authorized, otherAuthorized, other]) {
}); });
it('reverts when querying roles for the zero account', async function () { it('reverts when querying roles for the zero account', async function () {
await shouldFail.reverting(this.roles.has(ZERO_ADDRESS)); await shouldFail.reverting.withMessage(this.roles.has(ZERO_ADDRESS), 'Roles: account is the zero address');
}); });
context('initially', function () { context('initially', function () {
...@@ -28,11 +28,11 @@ contract('Roles', function ([_, authorized, otherAuthorized, other]) { ...@@ -28,11 +28,11 @@ contract('Roles', function ([_, authorized, otherAuthorized, other]) {
it('reverts when adding roles to an already assigned account', async function () { it('reverts when adding roles to an already assigned account', async function () {
await this.roles.add(authorized); await this.roles.add(authorized);
await shouldFail.reverting(this.roles.add(authorized)); await shouldFail.reverting.withMessage(this.roles.add(authorized), 'Roles: account already has role');
}); });
it('reverts when adding roles to the zero account', async function () { it('reverts when adding roles to the zero account', async function () {
await shouldFail.reverting(this.roles.add(ZERO_ADDRESS)); await shouldFail.reverting.withMessage(this.roles.add(ZERO_ADDRESS), 'Roles: account is the zero address');
}); });
}); });
}); });
...@@ -51,11 +51,11 @@ contract('Roles', function ([_, authorized, otherAuthorized, other]) { ...@@ -51,11 +51,11 @@ contract('Roles', function ([_, authorized, otherAuthorized, other]) {
}); });
it('reverts when removing unassigned roles', async function () { it('reverts when removing unassigned roles', async function () {
await shouldFail.reverting(this.roles.remove(other)); await shouldFail.reverting.withMessage(this.roles.remove(other), 'Roles: account does not have role');
}); });
it('reverts when removing roles from the zero account', async function () { it('reverts when removing roles from the zero account', async function () {
await shouldFail.reverting(this.roles.remove(ZERO_ADDRESS)); await shouldFail.reverting.withMessage(this.roles.remove(ZERO_ADDRESS), 'Roles: account is the zero address');
}); });
}); });
}); });
......
...@@ -39,7 +39,9 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [other], rolen ...@@ -39,7 +39,9 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [other], rolen
} }
it('reverts when querying roles for the null account', async function () { it('reverts when querying roles for the null account', async function () {
await shouldFail.reverting(this.contract[`is${rolename}`](ZERO_ADDRESS)); await shouldFail.reverting.withMessage(this.contract[`is${rolename}`](ZERO_ADDRESS),
'Roles: account is the zero address'
);
}); });
describe('access control', function () { describe('access control', function () {
...@@ -55,7 +57,9 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [other], rolen ...@@ -55,7 +57,9 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [other], rolen
const from = other; const from = other;
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.contract[`only${rolename}Mock`]({ from })); await shouldFail.reverting.withMessage(this.contract[`only${rolename}Mock`]({ from }),
`${rolename}Role: caller does not have the ${rolename} role`
);
}); });
}); });
}); });
...@@ -75,11 +79,15 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [other], rolen ...@@ -75,11 +79,15 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [other], rolen
}); });
it('reverts when adding role to an already assigned account', async function () { it('reverts when adding role to an already assigned account', async function () {
await shouldFail.reverting(this.contract[`add${rolename}`](authorized, { from })); await shouldFail.reverting.withMessage(this.contract[`add${rolename}`](authorized, { from }),
'Roles: account already has role'
);
}); });
it('reverts when adding role to the null account', async function () { it('reverts when adding role to the null account', async function () {
await shouldFail.reverting(this.contract[`add${rolename}`](ZERO_ADDRESS, { from })); await shouldFail.reverting.withMessage(this.contract[`add${rolename}`](ZERO_ADDRESS, { from }),
'Roles: account is the zero address'
);
}); });
}); });
}); });
...@@ -101,11 +109,15 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [other], rolen ...@@ -101,11 +109,15 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [other], rolen
}); });
it('reverts when removing from an unassigned account', async function () { it('reverts when removing from an unassigned account', async function () {
await shouldFail.reverting(this.contract[`remove${rolename}`](other, { from })); await shouldFail.reverting.withMessage(this.contract[`remove${rolename}`](other, { from }),
'Roles: account does not have role'
);
}); });
it('reverts when removing role from the null account', async function () { it('reverts when removing role from the null account', async function () {
await shouldFail.reverting(this.contract[`remove${rolename}`](ZERO_ADDRESS, { from })); await shouldFail.reverting.withMessage(this.contract[`remove${rolename}`](ZERO_ADDRESS, { from }),
'Roles: account is the zero address'
);
}); });
}); });
}); });
...@@ -122,7 +134,9 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [other], rolen ...@@ -122,7 +134,9 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [other], rolen
}); });
it('reverts when renouncing unassigned role', async function () { it('reverts when renouncing unassigned role', async function () {
await shouldFail.reverting(this.contract[`renounce${rolename}`]({ from: other })); await shouldFail.reverting.withMessage(this.contract[`renounce${rolename}`]({ from: other }),
'Roles: account does not have role'
);
}); });
}); });
}); });
......
...@@ -75,7 +75,9 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW ...@@ -75,7 +75,9 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW
describe('when token wallet is the zero address', function () { describe('when token wallet is the zero address', function () {
it('creation reverts', async function () { it('creation reverts', async function () {
this.token = await SimpleToken.new({ from: tokenWallet }); this.token = await SimpleToken.new({ from: tokenWallet });
await shouldFail.reverting(AllowanceCrowdsaleImpl.new(rate, wallet, this.token.address, ZERO_ADDRESS)); await shouldFail.reverting.withMessage(AllowanceCrowdsaleImpl.new(rate, wallet, this.token.address, ZERO_ADDRESS),
'AllowanceCrowdsale: token wallet is the zero address'
);
}); });
}); });
}); });
...@@ -14,7 +14,9 @@ contract('CappedCrowdsale', function ([_, wallet]) { ...@@ -14,7 +14,9 @@ contract('CappedCrowdsale', function ([_, wallet]) {
}); });
it('rejects a cap of zero', async function () { it('rejects a cap of zero', async function () {
await shouldFail.reverting(CappedCrowdsaleImpl.new(rate, wallet, this.token.address, 0)); await shouldFail.reverting.withMessage(CappedCrowdsaleImpl.new(rate, wallet, this.token.address, 0),
'CappedCrowdsale: cap is 0'
);
}); });
context('with crowdsale', function () { context('with crowdsale', function () {
...@@ -31,11 +33,11 @@ contract('CappedCrowdsale', function ([_, wallet]) { ...@@ -31,11 +33,11 @@ contract('CappedCrowdsale', function ([_, wallet]) {
it('should reject payments outside cap', async function () { it('should reject payments outside cap', async function () {
await this.crowdsale.send(cap); await this.crowdsale.send(cap);
await shouldFail.reverting(this.crowdsale.send(1)); await shouldFail.reverting.withMessage(this.crowdsale.send(1), 'CappedCrowdsale: cap exceeded');
}); });
it('should reject payments that exceed cap', async function () { it('should reject payments that exceed cap', async function () {
await shouldFail.reverting(this.crowdsale.send(cap.addn(1))); await shouldFail.reverting.withMessage(this.crowdsale.send(cap.addn(1)), 'CappedCrowdsale: cap exceeded');
}); });
}); });
......
...@@ -11,8 +11,9 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { ...@@ -11,8 +11,9 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) {
const expectedTokenAmount = rate.mul(value); const expectedTokenAmount = rate.mul(value);
it('requires a non-null token', async function () { it('requires a non-null token', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
Crowdsale.new(rate, wallet, ZERO_ADDRESS) Crowdsale.new(rate, wallet, ZERO_ADDRESS),
'Crowdsale: token is the zero address'
); );
}); });
...@@ -22,14 +23,14 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { ...@@ -22,14 +23,14 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) {
}); });
it('requires a non-zero rate', async function () { it('requires a non-zero rate', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
Crowdsale.new(0, wallet, this.token.address) Crowdsale.new(0, wallet, this.token.address), 'Crowdsale: rate is 0'
); );
}); });
it('requires a non-null wallet', async function () { it('requires a non-null wallet', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
Crowdsale.new(rate, ZERO_ADDRESS, this.token.address) Crowdsale.new(rate, ZERO_ADDRESS, this.token.address), 'Crowdsale: wallet is the zero address'
); );
}); });
...@@ -46,8 +47,8 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { ...@@ -46,8 +47,8 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) {
}); });
it('reverts on zero-valued payments', async function () { it('reverts on zero-valued payments', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.crowdsale.send(0, { from: purchaser }) this.crowdsale.send(0, { from: purchaser }), 'Crowdsale: weiAmount is 0'
); );
}); });
}); });
...@@ -58,14 +59,15 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { ...@@ -58,14 +59,15 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) {
}); });
it('reverts on zero-valued payments', async function () { it('reverts on zero-valued payments', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.crowdsale.buyTokens(investor, { value: 0, from: purchaser }) this.crowdsale.buyTokens(investor, { value: 0, from: purchaser }), 'Crowdsale: weiAmount is 0'
); );
}); });
it('requires a non-null beneficiary', async function () { it('requires a non-null beneficiary', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.crowdsale.buyTokens(ZERO_ADDRESS, { value: value, from: purchaser }) this.crowdsale.buyTokens(ZERO_ADDRESS, { value: value, from: purchaser }),
'Crowdsale: beneficiary is the zero address'
); );
}); });
}); });
......
...@@ -23,7 +23,9 @@ contract('FinalizableCrowdsale', function ([_, wallet, other]) { ...@@ -23,7 +23,9 @@ contract('FinalizableCrowdsale', function ([_, wallet, other]) {
}); });
it('cannot be finalized before ending', async function () { it('cannot be finalized before ending', async function () {
await shouldFail.reverting(this.crowdsale.finalize({ from: other })); await shouldFail.reverting.withMessage(this.crowdsale.finalize({ from: other }),
'FinalizableCrowdsale: not closed'
);
}); });
it('can be finalized by anyone after ending', async function () { it('can be finalized by anyone after ending', async function () {
...@@ -34,7 +36,9 @@ contract('FinalizableCrowdsale', function ([_, wallet, other]) { ...@@ -34,7 +36,9 @@ contract('FinalizableCrowdsale', function ([_, wallet, other]) {
it('cannot be finalized twice', async function () { it('cannot be finalized twice', async function () {
await time.increaseTo(this.afterClosingTime); await time.increaseTo(this.afterClosingTime);
await this.crowdsale.finalize({ from: other }); await this.crowdsale.finalize({ from: other });
await shouldFail.reverting(this.crowdsale.finalize({ from: other })); await shouldFail.reverting.withMessage(this.crowdsale.finalize({ from: other }),
'FinalizableCrowdsale: already finalized'
);
}); });
it('logs finalized', async function () { it('logs finalized', async function () {
......
...@@ -26,21 +26,21 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) ...@@ -26,21 +26,21 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser])
}); });
it('reverts with a final rate larger than the initial rate', async function () { it('reverts with a final rate larger than the initial rate', async function () {
await shouldFail.reverting(IncreasingPriceCrowdsaleImpl.new( await shouldFail.reverting.withMessage(IncreasingPriceCrowdsaleImpl.new(
this.startTime, this.closingTime, wallet, this.token.address, initialRate, initialRate.addn(1) this.startTime, this.closingTime, wallet, this.token.address, initialRate, initialRate.addn(1)
)); ), 'IncreasingPriceCrowdsale: initial rate is not greater than final rate');
}); });
it('reverts with a final rate equal to the initial rate', async function () { it('reverts with a final rate equal to the initial rate', async function () {
await shouldFail.reverting(IncreasingPriceCrowdsaleImpl.new( await shouldFail.reverting.withMessage(IncreasingPriceCrowdsaleImpl.new(
this.startTime, this.closingTime, wallet, this.token.address, initialRate, initialRate this.startTime, this.closingTime, wallet, this.token.address, initialRate, initialRate
)); ), 'IncreasingPriceCrowdsale: initial rate is not greater than final rate');
}); });
it('reverts with a final rate of zero', async function () { it('reverts with a final rate of zero', async function () {
await shouldFail.reverting(IncreasingPriceCrowdsaleImpl.new( await shouldFail.reverting.withMessage(IncreasingPriceCrowdsaleImpl.new(
this.startTime, this.closingTime, wallet, this.token.address, initialRate, 0 this.startTime, this.closingTime, wallet, this.token.address, initialRate, 0
)); ), 'IncreasingPriceCrowdsale: final rate is 0');
}); });
context('with crowdsale', function () { context('with crowdsale', function () {
...@@ -57,7 +57,9 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) ...@@ -57,7 +57,9 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser])
}); });
it('reverts when the base Crowdsale\'s rate function is called', async function () { it('reverts when the base Crowdsale\'s rate function is called', async function () {
await shouldFail.reverting(this.crowdsale.rate()); await shouldFail.reverting.withMessage(this.crowdsale.rate(),
'IncreasingPriceCrowdsale: rate() called'
);
}); });
it('returns a rate of 0 before the crowdsale starts', async function () { it('returns a rate of 0 before the crowdsale starts', async function () {
......
...@@ -34,7 +34,9 @@ contract('IndividuallyCappedCrowdsale', function ( ...@@ -34,7 +34,9 @@ contract('IndividuallyCappedCrowdsale', function (
}); });
it('reverts when a non-capper sets a cap', async function () { it('reverts when a non-capper sets a cap', async function () {
await shouldFail.reverting(this.crowdsale.setCap(alice, capAlice, { from: other })); await shouldFail.reverting.withMessage(this.crowdsale.setCap(alice, capAlice, { from: other }),
'CapperRole: caller does not have the Capper role'
);
}); });
context('with individual caps', function () { context('with individual caps', function () {
...@@ -52,21 +54,31 @@ contract('IndividuallyCappedCrowdsale', function ( ...@@ -52,21 +54,31 @@ contract('IndividuallyCappedCrowdsale', function (
it('should reject payments outside cap', async function () { it('should reject payments outside cap', async function () {
await this.crowdsale.buyTokens(alice, { value: capAlice }); await this.crowdsale.buyTokens(alice, { value: capAlice });
await shouldFail.reverting(this.crowdsale.buyTokens(alice, { value: 1 })); await shouldFail.reverting.withMessage(this.crowdsale.buyTokens(alice, { value: 1 }),
'IndividuallyCappedCrowdsale: beneficiary\'s cap exceeded'
);
}); });
it('should reject payments that exceed cap', async function () { it('should reject payments that exceed cap', async function () {
await shouldFail.reverting(this.crowdsale.buyTokens(alice, { value: capAlice.addn(1) })); await shouldFail.reverting.withMessage(this.crowdsale.buyTokens(alice, { value: capAlice.addn(1) }),
await shouldFail.reverting(this.crowdsale.buyTokens(bob, { value: capBob.addn(1) })); 'IndividuallyCappedCrowdsale: beneficiary\'s cap exceeded'
);
await shouldFail.reverting.withMessage(this.crowdsale.buyTokens(bob, { value: capBob.addn(1) }),
'IndividuallyCappedCrowdsale: beneficiary\'s cap exceeded'
);
}); });
it('should manage independent caps', async function () { it('should manage independent caps', async function () {
await this.crowdsale.buyTokens(alice, { value: lessThanCapAlice }); await this.crowdsale.buyTokens(alice, { value: lessThanCapAlice });
await shouldFail.reverting(this.crowdsale.buyTokens(bob, { value: lessThanCapAlice })); await shouldFail.reverting.withMessage(this.crowdsale.buyTokens(bob, { value: lessThanCapAlice }),
'IndividuallyCappedCrowdsale: beneficiary\'s cap exceeded'
);
}); });
it('should default to a cap of zero', async function () { it('should default to a cap of zero', async function () {
await shouldFail.reverting(this.crowdsale.buyTokens(charlie, { value: lessThanCapBoth })); await shouldFail.reverting.withMessage(this.crowdsale.buyTokens(charlie, { value: lessThanCapBoth }),
'IndividuallyCappedCrowdsale: beneficiary\'s cap exceeded'
);
}); });
}); });
......
...@@ -26,8 +26,12 @@ contract('PausableCrowdsale', function ([_, pauser, wallet, other]) { ...@@ -26,8 +26,12 @@ contract('PausableCrowdsale', function ([_, pauser, wallet, other]) {
}); });
it('purchases do not work', async function () { it('purchases do not work', async function () {
await shouldFail.reverting(this.crowdsale.sendTransaction({ from: other, value })); await shouldFail.reverting.withMessage(this.crowdsale.sendTransaction({ from: other, value }),
await shouldFail.reverting(this.crowdsale.buyTokens(other, { from: other, value })); 'Pausable: paused'
);
await shouldFail.reverting.withMessage(this.crowdsale.buyTokens(other, { from: other, value }),
'Pausable: paused'
);
}); });
context('after unpause', function () { context('after unpause', function () {
......
...@@ -41,7 +41,9 @@ contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { ...@@ -41,7 +41,9 @@ contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) {
}); });
it('does not allow beneficiaries to withdraw tokens before crowdsale ends', async function () { it('does not allow beneficiaries to withdraw tokens before crowdsale ends', async function () {
await shouldFail.reverting(this.crowdsale.withdrawTokens(investor)); await shouldFail.reverting.withMessage(this.crowdsale.withdrawTokens(investor),
'PostDeliveryCrowdsale: not closed'
);
}); });
context('after closing time', function () { context('after closing time', function () {
...@@ -57,7 +59,9 @@ contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { ...@@ -57,7 +59,9 @@ contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) {
it('rejects multiple withdrawals', async function () { it('rejects multiple withdrawals', async function () {
await this.crowdsale.withdrawTokens(investor); await this.crowdsale.withdrawTokens(investor);
await shouldFail.reverting(this.crowdsale.withdrawTokens(investor)); await shouldFail.reverting.withMessage(this.crowdsale.withdrawTokens(investor),
'PostDeliveryCrowdsale: beneficiary is not due any tokens'
);
}); });
}); });
}); });
......
...@@ -24,8 +24,9 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, other ...@@ -24,8 +24,9 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, other
}); });
it('rejects a goal of zero', async function () { it('rejects a goal of zero', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
RefundableCrowdsaleImpl.new(this.openingTime, this.closingTime, rate, wallet, this.token.address, 0) RefundableCrowdsaleImpl.new(this.openingTime, this.closingTime, rate, wallet, this.token.address, 0),
'RefundableCrowdsale: goal is 0'
); );
}); });
...@@ -40,7 +41,9 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, other ...@@ -40,7 +41,9 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, other
context('before opening time', function () { context('before opening time', function () {
it('denies refunds', async function () { it('denies refunds', async function () {
await shouldFail.reverting(this.crowdsale.claimRefund(investor)); await shouldFail.reverting.withMessage(this.crowdsale.claimRefund(investor),
'RefundableCrowdsale: not finalized'
);
}); });
}); });
...@@ -50,7 +53,9 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, other ...@@ -50,7 +53,9 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, other
}); });
it('denies refunds', async function () { it('denies refunds', async function () {
await shouldFail.reverting(this.crowdsale.claimRefund(investor)); await shouldFail.reverting.withMessage(this.crowdsale.claimRefund(investor),
'RefundableCrowdsale: not finalized'
);
}); });
context('with unreached goal', function () { context('with unreached goal', function () {
...@@ -84,7 +89,9 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, other ...@@ -84,7 +89,9 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, other
}); });
it('denies refunds', async function () { it('denies refunds', async function () {
await shouldFail.reverting(this.crowdsale.claimRefund(investor)); await shouldFail.reverting.withMessage(this.crowdsale.claimRefund(investor),
'RefundableCrowdsale: goal reached'
);
}); });
it('forwards funds to wallet', async function () { it('forwards funds to wallet', async function () {
......
...@@ -42,7 +42,9 @@ contract('RefundablePostDeliveryCrowdsale', function ([_, investor, wallet, purc ...@@ -42,7 +42,9 @@ contract('RefundablePostDeliveryCrowdsale', function ([_, investor, wallet, purc
}); });
it('does not allow beneficiaries to withdraw tokens before crowdsale ends', async function () { it('does not allow beneficiaries to withdraw tokens before crowdsale ends', async function () {
await shouldFail.reverting(this.crowdsale.withdrawTokens(investor)); await shouldFail.reverting.withMessage(this.crowdsale.withdrawTokens(investor),
'RefundablePostDeliveryCrowdsale: not finalized'
);
}); });
context('after closing time and finalization', function () { context('after closing time and finalization', function () {
...@@ -52,7 +54,9 @@ contract('RefundablePostDeliveryCrowdsale', function ([_, investor, wallet, purc ...@@ -52,7 +54,9 @@ contract('RefundablePostDeliveryCrowdsale', function ([_, investor, wallet, purc
}); });
it('rejects token withdrawals', async function () { it('rejects token withdrawals', async function () {
await shouldFail.reverting(this.crowdsale.withdrawTokens(investor)); await shouldFail.reverting.withMessage(this.crowdsale.withdrawTokens(investor),
'RefundablePostDeliveryCrowdsale: goal not reached'
);
}); });
}); });
}); });
...@@ -70,7 +74,9 @@ contract('RefundablePostDeliveryCrowdsale', function ([_, investor, wallet, purc ...@@ -70,7 +74,9 @@ contract('RefundablePostDeliveryCrowdsale', function ([_, investor, wallet, purc
}); });
it('does not allow beneficiaries to withdraw tokens before crowdsale ends', async function () { it('does not allow beneficiaries to withdraw tokens before crowdsale ends', async function () {
await shouldFail.reverting(this.crowdsale.withdrawTokens(investor)); await shouldFail.reverting.withMessage(this.crowdsale.withdrawTokens(investor),
'RefundablePostDeliveryCrowdsale: not finalized'
);
}); });
context('after closing time and finalization', function () { context('after closing time and finalization', function () {
...@@ -87,7 +93,9 @@ contract('RefundablePostDeliveryCrowdsale', function ([_, investor, wallet, purc ...@@ -87,7 +93,9 @@ contract('RefundablePostDeliveryCrowdsale', function ([_, investor, wallet, purc
it('rejects multiple withdrawals', async function () { it('rejects multiple withdrawals', async function () {
await this.crowdsale.withdrawTokens(investor); await this.crowdsale.withdrawTokens(investor);
await shouldFail.reverting(this.crowdsale.withdrawTokens(investor)); await shouldFail.reverting.withMessage(this.crowdsale.withdrawTokens(investor),
'PostDeliveryCrowdsale: beneficiary is not due any tokens'
);
}); });
}); });
}); });
......
...@@ -21,21 +21,21 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { ...@@ -21,21 +21,21 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) {
}); });
it('reverts if the opening time is in the past', async function () { it('reverts if the opening time is in the past', async function () {
await shouldFail.reverting(TimedCrowdsaleImpl.new( await shouldFail.reverting.withMessage(TimedCrowdsaleImpl.new(
(await time.latest()).sub(time.duration.days(1)), this.closingTime, rate, wallet, this.token.address (await time.latest()).sub(time.duration.days(1)), this.closingTime, rate, wallet, this.token.address
)); ), 'TimedCrowdsale: opening time is before current time');
}); });
it('reverts if the closing time is before the opening time', async function () { it('reverts if the closing time is before the opening time', async function () {
await shouldFail.reverting(TimedCrowdsaleImpl.new( await shouldFail.reverting.withMessage(TimedCrowdsaleImpl.new(
this.openingTime, this.openingTime.sub(time.duration.seconds(1)), rate, wallet, this.token.address this.openingTime, this.openingTime.sub(time.duration.seconds(1)), rate, wallet, this.token.address
)); ), 'TimedCrowdsale: opening time is not before closing time');
}); });
it('reverts if the closing time equals the opening time', async function () { it('reverts if the closing time equals the opening time', async function () {
await shouldFail.reverting(TimedCrowdsaleImpl.new( await shouldFail.reverting.withMessage(TimedCrowdsaleImpl.new(
this.openingTime, this.openingTime, rate, wallet, this.token.address this.openingTime, this.openingTime, rate, wallet, this.token.address
)); ), 'TimedCrowdsale: opening time is not before closing time');
}); });
context('with crowdsale', function () { context('with crowdsale', function () {
...@@ -56,8 +56,10 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { ...@@ -56,8 +56,10 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) {
describe('accepting payments', function () { describe('accepting payments', function () {
it('should reject payments before start', async function () { it('should reject payments before start', async function () {
(await this.crowdsale.isOpen()).should.equal(false); (await this.crowdsale.isOpen()).should.equal(false);
await shouldFail.reverting(this.crowdsale.send(value)); await shouldFail.reverting.withMessage(this.crowdsale.send(value), 'TimedCrowdsale: not open');
await shouldFail.reverting(this.crowdsale.buyTokens(investor, { from: purchaser, value: value })); await shouldFail.reverting.withMessage(this.crowdsale.buyTokens(investor, { from: purchaser, value: value }),
'TimedCrowdsale: not open'
);
}); });
it('should accept payments after start', async function () { it('should accept payments after start', async function () {
...@@ -69,25 +71,31 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { ...@@ -69,25 +71,31 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) {
it('should reject payments after end', async function () { it('should reject payments after end', async function () {
await time.increaseTo(this.afterClosingTime); await time.increaseTo(this.afterClosingTime);
await shouldFail.reverting(this.crowdsale.send(value)); await shouldFail.reverting.withMessage(this.crowdsale.send(value), 'TimedCrowdsale: not open');
await shouldFail.reverting(this.crowdsale.buyTokens(investor, { value: value, from: purchaser })); await shouldFail.reverting.withMessage(this.crowdsale.buyTokens(investor, { value: value, from: purchaser }),
'TimedCrowdsale: not open'
);
}); });
}); });
describe('extending closing time', function () { describe('extending closing time', function () {
it('should not reduce duration', async function () { it('should not reduce duration', async function () {
// Same date // Same date
await shouldFail.reverting(this.crowdsale.extendTime(this.closingTime)); await shouldFail.reverting.withMessage(this.crowdsale.extendTime(this.closingTime),
'TimedCrowdsale: new closing time is before current closing time'
);
// Prescending date // Prescending date
const newClosingTime = this.closingTime.sub(time.duration.seconds(1)); const newClosingTime = this.closingTime.sub(time.duration.seconds(1));
await shouldFail.reverting(this.crowdsale.extendTime(newClosingTime)); await shouldFail.reverting.withMessage(this.crowdsale.extendTime(newClosingTime),
'TimedCrowdsale: new closing time is before current closing time'
);
}); });
context('before crowdsale start', function () { context('before crowdsale start', function () {
beforeEach(async function () { beforeEach(async function () {
(await this.crowdsale.isOpen()).should.equal(false); (await this.crowdsale.isOpen()).should.equal(false);
await shouldFail.reverting(this.crowdsale.send(value)); await shouldFail.reverting.withMessage(this.crowdsale.send(value), 'TimedCrowdsale: not open');
}); });
it('it extends end time', async function () { it('it extends end time', async function () {
...@@ -126,7 +134,9 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { ...@@ -126,7 +134,9 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) {
it('it reverts', async function () { it('it reverts', async function () {
const newClosingTime = await time.latest(); const newClosingTime = await time.latest();
await shouldFail.reverting(this.crowdsale.extendTime(newClosingTime)); await shouldFail.reverting.withMessage(this.crowdsale.extendTime(newClosingTime),
'TimedCrowdsale: already closed'
);
}); });
}); });
}); });
......
...@@ -20,8 +20,12 @@ contract('WhitelistCrowdsale', function ([_, wallet, whitelister, whitelisted, o ...@@ -20,8 +20,12 @@ contract('WhitelistCrowdsale', function ([_, wallet, whitelister, whitelisted, o
} }
async function purchaseShouldFail (crowdsale, beneficiary, value) { async function purchaseShouldFail (crowdsale, beneficiary, value) {
await shouldFail.reverting(crowdsale.buyTokens(beneficiary, { from: beneficiary, value })); await shouldFail.reverting.withMessage(crowdsale.buyTokens(beneficiary, { from: beneficiary, value }),
await shouldFail.reverting(crowdsale.sendTransaction({ from: beneficiary, value })); 'WhitelistCrowdsale: beneficiary doesn\'t have the Whitelisted role'
);
await shouldFail.reverting.withMessage(crowdsale.sendTransaction({ from: beneficiary, value }),
'WhitelistCrowdsale: beneficiary doesn\'t have the Whitelisted role'
);
} }
context('with no whitelisted addresses', function () { context('with no whitelisted addresses', function () {
......
...@@ -118,8 +118,9 @@ contract('ECDSA', function ([_, other]) { ...@@ -118,8 +118,9 @@ contract('ECDSA', function ([_, other]) {
it.skip('reverts', async function () { it.skip('reverts', async function () {
// Create the signature // Create the signature
const signature = await web3.eth.sign(TEST_MESSAGE, other); const signature = await web3.eth.sign(TEST_MESSAGE, other);
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.ecdsa.recover(TEST_MESSAGE.substring(2), signature) this.ecdsa.recover(TEST_MESSAGE.substring(2), signature),
'Failure message'
); );
}); });
}); });
......
...@@ -39,7 +39,7 @@ contract('Counters', function () { ...@@ -39,7 +39,7 @@ contract('Counters', function () {
it('reverts if the current value is 0', async function () { it('reverts if the current value is 0', async function () {
await this.counter.decrement(); await this.counter.decrement();
await shouldFail.reverting(this.counter.decrement()); await shouldFail.reverting.withMessage(this.counter.decrement(), 'SafeMath: subtraction overflow');
}); });
it('can be called multiple times', async function () { it('can be called multiple times', async function () {
......
...@@ -21,10 +21,11 @@ contract('ERC1820Implementer', function ([_, registryFunder, implementee, other] ...@@ -21,10 +21,11 @@ contract('ERC1820Implementer', function ([_, registryFunder, implementee, other]
}); });
it('reverts when attempting to set as implementer in the registry', async function () { it('reverts when attempting to set as implementer in the registry', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.registry.setInterfaceImplementer( this.registry.setInterfaceImplementer(
implementee, this.interfaceA, this.implementer.address, { from: implementee } implementee, this.interfaceA, this.implementer.address, { from: implementee }
) ),
'Does not implement the interface'
); );
}); });
}); });
......
...@@ -9,7 +9,9 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) { ...@@ -9,7 +9,9 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) {
const totalSupply = new BN('200'); const totalSupply = new BN('200');
it('reverts with a null legacy token address', async function () { it('reverts with a null legacy token address', async function () {
await shouldFail.reverting(ERC20Migrator.new(ZERO_ADDRESS)); await shouldFail.reverting.withMessage(ERC20Migrator.new(ZERO_ADDRESS),
'ERC20Migrator: legacy token is the zero address'
);
}); });
describe('with tokens and migrator', function () { describe('with tokens and migrator', function () {
...@@ -25,11 +27,15 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) { ...@@ -25,11 +27,15 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) {
describe('beginMigration', function () { describe('beginMigration', function () {
it('reverts with a null new token address', async function () { it('reverts with a null new token address', async function () {
await shouldFail.reverting(this.migrator.beginMigration(ZERO_ADDRESS)); await shouldFail.reverting.withMessage(this.migrator.beginMigration(ZERO_ADDRESS),
'ERC20Migrator: new token is the zero address'
);
}); });
it('reverts if not a minter of the token', async function () { it('reverts if not a minter of the token', async function () {
await shouldFail.reverting(this.migrator.beginMigration(this.newToken.address)); await shouldFail.reverting.withMessage(this.migrator.beginMigration(this.newToken.address),
'ERC20Migrator: not a minter for new token'
);
}); });
it('succeeds if it is a minter of the token', async function () { it('succeeds if it is a minter of the token', async function () {
...@@ -40,7 +46,9 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) { ...@@ -40,7 +46,9 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) {
it('reverts the second time it is called', async function () { it('reverts the second time it is called', async function () {
await this.newToken.addMinter(this.migrator.address); await this.newToken.addMinter(this.migrator.address);
await this.migrator.beginMigration(this.newToken.address); await this.migrator.beginMigration(this.newToken.address);
await shouldFail.reverting(this.migrator.beginMigration(this.newToken.address)); await shouldFail.reverting.withMessage(this.migrator.beginMigration(this.newToken.address),
'ERC20Migrator: migration already started'
);
}); });
}); });
...@@ -58,7 +66,9 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) { ...@@ -58,7 +66,9 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) {
}); });
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.migrator.migrateAll(owner)); await shouldFail.reverting.withMessage(this.migrator.migrateAll(owner),
'ERC20Migrator: migration not started'
);
}); });
}); });
}); });
...@@ -72,7 +82,9 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) { ...@@ -72,7 +82,9 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) {
}); });
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.migrator.migrate(owner, amount)); await shouldFail.reverting.withMessage(this.migrator.migrate(owner, amount),
'ERC20Migrator: migration not started'
);
}); });
}); });
}); });
...@@ -174,7 +186,9 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) { ...@@ -174,7 +186,9 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) {
const amount = baseAmount.addn(1); const amount = baseAmount.addn(1);
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.migrator.migrate(owner, amount)); await shouldFail.reverting.withMessage(this.migrator.migrate(owner, amount),
'SafeERC20: low-level call failed'
);
}); });
}); });
}); });
......
...@@ -24,11 +24,11 @@ contract('ERC20Snapshot', function ([_, initialHolder, recipient, other]) { ...@@ -24,11 +24,11 @@ contract('ERC20Snapshot', function ([_, initialHolder, recipient, other]) {
describe('totalSupplyAt', function () { describe('totalSupplyAt', function () {
it('reverts with a snapshot id of 0', async function () { it('reverts with a snapshot id of 0', async function () {
await shouldFail.reverting(this.token.totalSupplyAt(0)); await shouldFail.reverting.withMessage(this.token.totalSupplyAt(0), 'ERC20Snapshot: id is 0');
}); });
it('reverts with a not-yet-created snapshot id', async function () { it('reverts with a not-yet-created snapshot id', async function () {
await shouldFail.reverting(this.token.totalSupplyAt(1)); await shouldFail.reverting.withMessage(this.token.totalSupplyAt(1), 'ERC20Snapshot: nonexistent id');
}); });
context('with initial snapshot', function () { context('with initial snapshot', function () {
...@@ -98,11 +98,11 @@ contract('ERC20Snapshot', function ([_, initialHolder, recipient, other]) { ...@@ -98,11 +98,11 @@ contract('ERC20Snapshot', function ([_, initialHolder, recipient, other]) {
describe('balanceOfAt', function () { describe('balanceOfAt', function () {
it('reverts with a snapshot id of 0', async function () { it('reverts with a snapshot id of 0', async function () {
await shouldFail.reverting(this.token.balanceOfAt(other, 0)); await shouldFail.reverting.withMessage(this.token.balanceOfAt(other, 0), 'ERC20Snapshot: id is 0');
}); });
it('reverts with a not-yet-created snapshot id', async function () { it('reverts with a not-yet-created snapshot id', async function () {
await shouldFail.reverting(this.token.balanceOfAt(other, 1)); await shouldFail.reverting.withMessage(this.token.balanceOfAt(other, 1), 'ERC20Snapshot: nonexistent id');
}); });
context('with initial snapshot', function () { context('with initial snapshot', function () {
......
...@@ -30,21 +30,23 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, other, authorize ...@@ -30,21 +30,23 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, other, authorize
}); });
it('does not allow invalid signature for sender', async function () { it('does not allow invalid signature for sender', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.sigBouncer.onlyWithValidSignature(INVALID_SIGNATURE, { from: authorizedUser }) this.sigBouncer.onlyWithValidSignature(INVALID_SIGNATURE, { from: authorizedUser }),
'SignatureBouncer: invalid signature for caller'
); );
}); });
it('does not allow valid signature for other sender', async function () { it('does not allow valid signature for other sender', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.sigBouncer.onlyWithValidSignature(await this.signFor(authorizedUser), { from: other }) this.sigBouncer.onlyWithValidSignature(await this.signFor(authorizedUser), { from: other }),
'SignatureBouncer: invalid signature for caller'
); );
}); });
it('does not allow valid signature for method for sender', async function () { it('does not allow valid signature for method for sender', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.sigBouncer.onlyWithValidSignature(await this.signFor(authorizedUser, 'onlyWithValidSignature'), this.sigBouncer.onlyWithValidSignature(await this.signFor(authorizedUser, 'onlyWithValidSignature'),
{ from: authorizedUser }) { from: authorizedUser }), 'SignatureBouncer: invalid signature for caller'
); );
}); });
}); });
...@@ -57,29 +59,32 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, other, authorize ...@@ -57,29 +59,32 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, other, authorize
}); });
it('does not allow invalid signature with correct method for sender', async function () { it('does not allow invalid signature with correct method for sender', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.sigBouncer.onlyWithValidSignatureAndMethod(INVALID_SIGNATURE, { from: authorizedUser }) this.sigBouncer.onlyWithValidSignatureAndMethod(INVALID_SIGNATURE, { from: authorizedUser }),
'SignatureBouncer: invalid signature for caller and method'
); );
}); });
it('does not allow valid signature with correct method for other sender', async function () { it('does not allow valid signature with correct method for other sender', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.sigBouncer.onlyWithValidSignatureAndMethod( this.sigBouncer.onlyWithValidSignatureAndMethod(
await this.signFor(authorizedUser, 'onlyWithValidSignatureAndMethod'), { from: other } await this.signFor(authorizedUser, 'onlyWithValidSignatureAndMethod'), { from: other }
) ),
'SignatureBouncer: invalid signature for caller and method'
); );
}); });
it('does not allow valid method signature with incorrect method for sender', async function () { it('does not allow valid method signature with incorrect method for sender', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.sigBouncer.onlyWithValidSignatureAndMethod(await this.signFor(authorizedUser, 'theWrongMethod'), this.sigBouncer.onlyWithValidSignatureAndMethod(await this.signFor(authorizedUser, 'theWrongMethod'),
{ from: authorizedUser }) { from: authorizedUser }), 'SignatureBouncer: invalid signature for caller and method'
); );
}); });
it('does not allow valid non-method signature method for sender', async function () { it('does not allow valid non-method signature method for sender', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.sigBouncer.onlyWithValidSignatureAndMethod(await this.signFor(authorizedUser), { from: authorizedUser }) this.sigBouncer.onlyWithValidSignatureAndMethod(await this.signFor(authorizedUser), { from: authorizedUser }),
'SignatureBouncer: invalid signature for caller and method'
); );
}); });
}); });
...@@ -92,40 +97,41 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, other, authorize ...@@ -92,40 +97,41 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, other, authorize
}); });
it('does not allow invalid signature with correct method and data for sender', async function () { it('does not allow invalid signature with correct method and data for sender', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE, INVALID_SIGNATURE, { from: authorizedUser }) this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE, INVALID_SIGNATURE, { from: authorizedUser }),
'SignatureBouncer: invalid signature for caller and data'
); );
}); });
it('does not allow valid signature with correct method and incorrect data for sender', async function () { it('does not allow valid signature with correct method and incorrect data for sender', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE + 10, this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE + 10,
await this.signFor(authorizedUser, 'onlyWithValidSignatureAndData', [UINT_VALUE]), await this.signFor(authorizedUser, 'onlyWithValidSignatureAndData', [UINT_VALUE]),
{ from: authorizedUser } { from: authorizedUser }
) ), 'SignatureBouncer: invalid signature for caller and data'
); );
}); });
it('does not allow valid signature with correct method and data for other sender', async function () { it('does not allow valid signature with correct method and data for other sender', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE, this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE,
await this.signFor(authorizedUser, 'onlyWithValidSignatureAndData', [UINT_VALUE]), await this.signFor(authorizedUser, 'onlyWithValidSignatureAndData', [UINT_VALUE]),
{ from: other } { from: other }
) ), 'SignatureBouncer: invalid signature for caller and data'
); );
}); });
it('does not allow valid non-method signature for sender', async function () { it('does not allow valid non-method signature for sender', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE, this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE,
await this.signFor(authorizedUser), { from: authorizedUser } await this.signFor(authorizedUser), { from: authorizedUser }
) ), 'SignatureBouncer: invalid signature for caller and data'
); );
}); });
it('does not allow msg.data shorter than SIGNATURE_SIZE', async function () { it('does not allow msg.data shorter than SIGNATURE_SIZE', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.sigBouncer.tooShortMsgData({ from: authorizedUser }) this.sigBouncer.tooShortMsgData({ from: authorizedUser }), 'SignatureBouncer: data is too short'
); );
}); });
}); });
......
...@@ -13,9 +13,9 @@ contract('SignedSafeMath', function () { ...@@ -13,9 +13,9 @@ contract('SignedSafeMath', function () {
(await fn(rhs, lhs)).should.be.bignumber.equal(expected); (await fn(rhs, lhs)).should.be.bignumber.equal(expected);
} }
async function testFailsCommutative (fn, lhs, rhs) { async function testFailsCommutative (fn, lhs, rhs, reason) {
await shouldFail.reverting(fn(lhs, rhs)); await shouldFail.reverting.withMessage(fn(lhs, rhs), reason);
await shouldFail.reverting(fn(rhs, lhs)); await shouldFail.reverting.withMessage(fn(rhs, lhs), reason);
} }
describe('add', function () { describe('add', function () {
...@@ -37,14 +37,14 @@ contract('SignedSafeMath', function () { ...@@ -37,14 +37,14 @@ contract('SignedSafeMath', function () {
const a = MAX_INT256; const a = MAX_INT256;
const b = new BN('1'); const b = new BN('1');
await testFailsCommutative(this.safeMath.add, a, b); await testFailsCommutative(this.safeMath.add, a, b, 'SignedSafeMath: addition overflow');
}); });
it('reverts on negative addition overflow', async function () { it('reverts on negative addition overflow', async function () {
const a = MIN_INT256; const a = MIN_INT256;
const b = new BN('-1'); const b = new BN('-1');
await testFailsCommutative(this.safeMath.add, a, b); await testFailsCommutative(this.safeMath.add, a, b, 'SignedSafeMath: addition overflow');
}); });
}); });
...@@ -69,14 +69,14 @@ contract('SignedSafeMath', function () { ...@@ -69,14 +69,14 @@ contract('SignedSafeMath', function () {
const a = MAX_INT256; const a = MAX_INT256;
const b = new BN('-1'); const b = new BN('-1');
await shouldFail.reverting(this.safeMath.sub(a, b)); await shouldFail.reverting.withMessage(this.safeMath.sub(a, b), 'SignedSafeMath: subtraction overflow');
}); });
it('reverts on negative subtraction overflow', async function () { it('reverts on negative subtraction overflow', async function () {
const a = MIN_INT256; const a = MIN_INT256;
const b = new BN('1'); const b = new BN('1');
await shouldFail.reverting(this.safeMath.sub(a, b)); await shouldFail.reverting.withMessage(this.safeMath.sub(a, b), 'SignedSafeMath: subtraction overflow');
}); });
}); });
...@@ -99,14 +99,14 @@ contract('SignedSafeMath', function () { ...@@ -99,14 +99,14 @@ contract('SignedSafeMath', function () {
const a = MAX_INT256; const a = MAX_INT256;
const b = new BN('2'); const b = new BN('2');
await testFailsCommutative(this.safeMath.mul, a, b); await testFailsCommutative(this.safeMath.mul, a, b, 'SignedSafeMath: multiplication overflow');
}); });
it('reverts when minimum integer is multiplied by -1', async function () { it('reverts when minimum integer is multiplied by -1', async function () {
const a = MIN_INT256; const a = MIN_INT256;
const b = new BN('-1'); const b = new BN('-1');
await testFailsCommutative(this.safeMath.mul, a, b); await testFailsCommutative(this.safeMath.mul, a, b, 'SignedSafeMath: multiplication overflow');
}); });
}); });
...@@ -137,14 +137,14 @@ contract('SignedSafeMath', function () { ...@@ -137,14 +137,14 @@ contract('SignedSafeMath', function () {
const a = new BN('-5678'); const a = new BN('-5678');
const b = new BN('0'); const b = new BN('0');
await shouldFail.reverting(this.safeMath.div(a, b)); await shouldFail.reverting.withMessage(this.safeMath.div(a, b), 'SignedSafeMath: division by zero');
}); });
it('reverts on overflow, negative second', async function () { it('reverts on overflow, negative second', async function () {
const a = new BN(MIN_INT256); const a = new BN(MIN_INT256);
const b = new BN('-1'); const b = new BN('-1');
await shouldFail.reverting(this.safeMath.div(a, b)); await shouldFail.reverting.withMessage(this.safeMath.div(a, b), 'SignedSafeMath: division overflow');
}); });
}); });
}); });
...@@ -20,21 +20,23 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { ...@@ -20,21 +20,23 @@ contract('TokenVesting', function ([_, owner, beneficiary]) {
cliffDuration.should.be.bignumber.that.is.at.least(duration); cliffDuration.should.be.bignumber.that.is.at.least(duration);
await shouldFail.reverting( await shouldFail.reverting.withMessage(
TokenVesting.new(beneficiary, this.start, cliffDuration, duration, true, { from: owner }) TokenVesting.new(beneficiary, this.start, cliffDuration, duration, true, { from: owner }),
'TokenVesting: cliff is longer than duration'
); );
}); });
it('reverts with a null beneficiary', async function () { it('reverts with a null beneficiary', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
TokenVesting.new(ZERO_ADDRESS, this.start, this.cliffDuration, this.duration, true, { from: owner }) TokenVesting.new(ZERO_ADDRESS, this.start, this.cliffDuration, this.duration, true, { from: owner }),
'TokenVesting: beneficiary is the zero address'
); );
}); });
it('reverts with a null duration', async function () { it('reverts with a null duration', async function () {
// cliffDuration should also be 0, since the duration must be larger than the cliff // cliffDuration should also be 0, since the duration must be larger than the cliff
await shouldFail.reverting( await shouldFail.reverting.withMessage(
TokenVesting.new(beneficiary, this.start, 0, 0, true, { from: owner }) TokenVesting.new(beneficiary, this.start, 0, 0, true, { from: owner }), 'TokenVesting: duration is 0'
); );
}); });
...@@ -42,8 +44,9 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { ...@@ -42,8 +44,9 @@ contract('TokenVesting', function ([_, owner, beneficiary]) {
const now = await time.latest(); const now = await time.latest();
this.start = now.sub(this.duration).sub(time.duration.minutes(1)); this.start = now.sub(this.duration).sub(time.duration.minutes(1));
await shouldFail.reverting( await shouldFail.reverting.withMessage(
TokenVesting.new(beneficiary, this.start, this.cliffDuration, this.duration, true, { from: owner }) TokenVesting.new(beneficiary, this.start, this.cliffDuration, this.duration, true, { from: owner }),
'TokenVesting: final time is before current time'
); );
}); });
...@@ -65,7 +68,9 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { ...@@ -65,7 +68,9 @@ contract('TokenVesting', function ([_, owner, beneficiary]) {
}); });
it('cannot be released before cliff', async function () { it('cannot be released before cliff', async function () {
await shouldFail.reverting(this.vesting.release(this.token.address)); await shouldFail.reverting.withMessage(this.vesting.release(this.token.address),
'TokenVesting: no tokens are due'
);
}); });
it('can be released after cliff', async function () { it('can be released after cliff', async function () {
...@@ -121,7 +126,9 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { ...@@ -121,7 +126,9 @@ contract('TokenVesting', function ([_, owner, beneficiary]) {
beneficiary, this.start, this.cliffDuration, this.duration, false, { from: owner } beneficiary, this.start, this.cliffDuration, this.duration, false, { from: owner }
); );
await shouldFail.reverting(vesting.revoke(this.token.address, { from: owner })); await shouldFail.reverting.withMessage(vesting.revoke(this.token.address, { from: owner }),
'TokenVesting: cannot revoke'
);
}); });
it('should return the non-vested tokens when revoked by owner', async function () { it('should return the non-vested tokens when revoked by owner', async function () {
...@@ -148,7 +155,9 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { ...@@ -148,7 +155,9 @@ contract('TokenVesting', function ([_, owner, beneficiary]) {
it('should fail to be revoked a second time', async function () { it('should fail to be revoked a second time', async function () {
await this.vesting.revoke(this.token.address, { from: owner }); await this.vesting.revoke(this.token.address, { from: owner });
await shouldFail.reverting(this.vesting.revoke(this.token.address, { from: owner })); await shouldFail.reverting.withMessage(this.vesting.revoke(this.token.address, { from: owner }),
'TokenVesting: token already revoked'
);
}); });
function vestedAmount (total, now, start, cliffDuration, duration) { function vestedAmount (total, now, start, cliffDuration, duration) {
......
...@@ -38,8 +38,10 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { ...@@ -38,8 +38,10 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) {
}); });
it('should not accept payments before start', async function () { it('should not accept payments before start', async function () {
await shouldFail.reverting(this.crowdsale.send(ether('1'))); await shouldFail.reverting.withMessage(this.crowdsale.send(ether('1')), 'TimedCrowdsale: not open');
await shouldFail.reverting(this.crowdsale.buyTokens(investor, { from: investor, value: ether('1') })); await shouldFail.reverting.withMessage(this.crowdsale.buyTokens(investor, { from: investor, value: ether('1') }),
'TimedCrowdsale: not open'
);
}); });
it('should accept payments during the sale', async function () { it('should accept payments during the sale', async function () {
...@@ -55,14 +57,16 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { ...@@ -55,14 +57,16 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) {
it('should reject payments after end', async function () { it('should reject payments after end', async function () {
await time.increaseTo(this.afterClosingTime); await time.increaseTo(this.afterClosingTime);
await shouldFail.reverting(this.crowdsale.send(ether('1'))); await shouldFail.reverting.withMessage(this.crowdsale.send(ether('1')), 'TimedCrowdsale: not open');
await shouldFail.reverting(this.crowdsale.buyTokens(investor, { value: ether('1'), from: investor })); await shouldFail.reverting.withMessage(this.crowdsale.buyTokens(investor, { value: ether('1'), from: investor }),
'TimedCrowdsale: not open'
);
}); });
it('should reject payments over cap', async function () { it('should reject payments over cap', async function () {
await time.increaseTo(this.openingTime); await time.increaseTo(this.openingTime);
await this.crowdsale.send(CAP); await this.crowdsale.send(CAP);
await shouldFail.reverting(this.crowdsale.send(1)); await shouldFail.reverting.withMessage(this.crowdsale.send(1), 'CappedCrowdsale: cap exceeded');
}); });
it('should allow finalization and transfer funds to wallet if the goal is reached', async function () { it('should allow finalization and transfer funds to wallet if the goal is reached', async function () {
...@@ -93,9 +97,9 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { ...@@ -93,9 +97,9 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) {
const HIGH_GOAL = ether('30'); const HIGH_GOAL = ether('30');
it('creation reverts', async function () { it('creation reverts', async function () {
await shouldFail.reverting(SampleCrowdsale.new( await shouldFail.reverting.withMessage(SampleCrowdsale.new(
this.openingTime, this.closingTime, RATE, wallet, CAP, this.token.address, HIGH_GOAL this.openingTime, this.closingTime, RATE, wallet, CAP, this.token.address, HIGH_GOAL
)); ), 'SampleCrowdSale: goal is greater than cap');
}); });
}); });
}); });
...@@ -9,7 +9,7 @@ contract('ERC165', function () { ...@@ -9,7 +9,7 @@ contract('ERC165', function () {
}); });
it('does not allow 0xffffffff', async function () { it('does not allow 0xffffffff', async function () {
await shouldFail.reverting(this.mock.registerInterface('0xffffffff')); await shouldFail.reverting.withMessage(this.mock.registerInterface('0xffffffff'), 'ERC165: invalid interface id');
}); });
shouldSupportInterfaces([ shouldSupportInterfaces([
......
...@@ -30,7 +30,9 @@ contract('Pausable', function ([_, pauser, otherPauser, other, ...otherAccounts] ...@@ -30,7 +30,9 @@ contract('Pausable', function ([_, pauser, otherPauser, other, ...otherAccounts]
}); });
it('cannot take drastic measure in non-pause', async function () { it('cannot take drastic measure in non-pause', async function () {
await shouldFail.reverting(this.pausable.drasticMeasure({ from: other })); await shouldFail.reverting.withMessage(this.pausable.drasticMeasure({ from: other }),
'Pausable: not paused'
);
(await this.pausable.drasticMeasureTaken()).should.equal(false); (await this.pausable.drasticMeasureTaken()).should.equal(false);
}); });
...@@ -41,7 +43,9 @@ contract('Pausable', function ([_, pauser, otherPauser, other, ...otherAccounts] ...@@ -41,7 +43,9 @@ contract('Pausable', function ([_, pauser, otherPauser, other, ...otherAccounts]
}); });
it('reverts when pausing from non-pauser', async function () { it('reverts when pausing from non-pauser', async function () {
await shouldFail.reverting(this.pausable.pause({ from: other })); await shouldFail.reverting.withMessage(this.pausable.pause({ from: other }),
'PauserRole: caller does not have the Pauser role'
);
}); });
context('when paused', function () { context('when paused', function () {
...@@ -54,7 +58,7 @@ contract('Pausable', function ([_, pauser, otherPauser, other, ...otherAccounts] ...@@ -54,7 +58,7 @@ contract('Pausable', function ([_, pauser, otherPauser, other, ...otherAccounts]
}); });
it('cannot perform normal process in pause', async function () { it('cannot perform normal process in pause', async function () {
await shouldFail.reverting(this.pausable.normalProcess({ from: other })); await shouldFail.reverting.withMessage(this.pausable.normalProcess({ from: other }), 'Pausable: paused');
}); });
it('can take a drastic measure in a pause', async function () { it('can take a drastic measure in a pause', async function () {
...@@ -63,7 +67,7 @@ contract('Pausable', function ([_, pauser, otherPauser, other, ...otherAccounts] ...@@ -63,7 +67,7 @@ contract('Pausable', function ([_, pauser, otherPauser, other, ...otherAccounts]
}); });
it('reverts when re-pausing', async function () { it('reverts when re-pausing', async function () {
await shouldFail.reverting(this.pausable.pause({ from: pauser })); await shouldFail.reverting.withMessage(this.pausable.pause({ from: pauser }), 'Pausable: paused');
}); });
describe('unpausing', function () { describe('unpausing', function () {
...@@ -73,7 +77,9 @@ contract('Pausable', function ([_, pauser, otherPauser, other, ...otherAccounts] ...@@ -73,7 +77,9 @@ contract('Pausable', function ([_, pauser, otherPauser, other, ...otherAccounts]
}); });
it('reverts when unpausing from non-pauser', async function () { it('reverts when unpausing from non-pauser', async function () {
await shouldFail.reverting(this.pausable.unpause({ from: other })); await shouldFail.reverting.withMessage(this.pausable.unpause({ from: other }),
'PauserRole: caller does not have the Pauser role'
);
}); });
context('when unpaused', function () { context('when unpaused', function () {
...@@ -92,11 +98,13 @@ contract('Pausable', function ([_, pauser, otherPauser, other, ...otherAccounts] ...@@ -92,11 +98,13 @@ contract('Pausable', function ([_, pauser, otherPauser, other, ...otherAccounts]
}); });
it('should prevent drastic measure', async function () { it('should prevent drastic measure', async function () {
await shouldFail.reverting(this.pausable.drasticMeasure({ from: other })); await shouldFail.reverting.withMessage(this.pausable.drasticMeasure({ from: other }),
'Pausable: not paused'
);
}); });
it('reverts when re-unpausing', async function () { it('reverts when re-unpausing', async function () {
await shouldFail.reverting(this.pausable.unpause({ from: pauser })); await shouldFail.reverting.withMessage(this.pausable.unpause({ from: pauser }), 'Pausable: not paused');
}); });
}); });
}); });
......
...@@ -13,9 +13,9 @@ contract('SafeMath', function () { ...@@ -13,9 +13,9 @@ contract('SafeMath', function () {
(await fn(rhs, lhs)).should.be.bignumber.equal(expected); (await fn(rhs, lhs)).should.be.bignumber.equal(expected);
} }
async function testFailsCommutative (fn, lhs, rhs) { async function testFailsCommutative (fn, lhs, rhs, reason) {
await shouldFail.reverting(fn(lhs, rhs)); await shouldFail.reverting.withMessage(fn(lhs, rhs), reason);
await shouldFail.reverting(fn(rhs, lhs)); await shouldFail.reverting.withMessage(fn(rhs, lhs), reason);
} }
describe('add', function () { describe('add', function () {
...@@ -30,7 +30,7 @@ contract('SafeMath', function () { ...@@ -30,7 +30,7 @@ contract('SafeMath', function () {
const a = MAX_UINT256; const a = MAX_UINT256;
const b = new BN('1'); const b = new BN('1');
await testFailsCommutative(this.safeMath.add, a, b); await testFailsCommutative(this.safeMath.add, a, b, 'SafeMath: addition overflow');
}); });
}); });
...@@ -46,7 +46,7 @@ contract('SafeMath', function () { ...@@ -46,7 +46,7 @@ contract('SafeMath', function () {
const a = new BN('1234'); const a = new BN('1234');
const b = new BN('5678'); const b = new BN('5678');
await shouldFail.reverting(this.safeMath.sub(a, b)); await shouldFail.reverting.withMessage(this.safeMath.sub(a, b), 'SafeMath: subtraction overflow');
}); });
}); });
...@@ -69,7 +69,7 @@ contract('SafeMath', function () { ...@@ -69,7 +69,7 @@ contract('SafeMath', function () {
const a = MAX_UINT256; const a = MAX_UINT256;
const b = new BN('2'); const b = new BN('2');
await testFailsCommutative(this.safeMath.mul, a, b); await testFailsCommutative(this.safeMath.mul, a, b, 'SafeMath: multiplication overflow');
}); });
}); });
...@@ -99,7 +99,7 @@ contract('SafeMath', function () { ...@@ -99,7 +99,7 @@ contract('SafeMath', function () {
const a = new BN('5678'); const a = new BN('5678');
const b = new BN('0'); const b = new BN('0');
await shouldFail.reverting(this.safeMath.div(a, b)); await shouldFail.reverting.withMessage(this.safeMath.div(a, b), 'SafeMath: division by zero');
}); });
}); });
...@@ -138,7 +138,7 @@ contract('SafeMath', function () { ...@@ -138,7 +138,7 @@ contract('SafeMath', function () {
const a = new BN('5678'); const a = new BN('5678');
const b = new BN('0'); const b = new BN('0');
await shouldFail.reverting(this.safeMath.mod(a, b)); await shouldFail.reverting.withMessage(this.safeMath.mod(a, b), 'SafeMath: modulo by zero');
}); });
}); });
}); });
...@@ -17,11 +17,17 @@ function shouldBehaveLikeOwnable (owner, [other]) { ...@@ -17,11 +17,17 @@ function shouldBehaveLikeOwnable (owner, [other]) {
}); });
it('should prevent non-owners from transferring', async function () { it('should prevent non-owners from transferring', async function () {
await shouldFail.reverting(this.ownable.transferOwnership(other, { from: other })); await shouldFail.reverting.withMessage(
this.ownable.transferOwnership(other, { from: other }),
'Ownable: caller is not the owner'
);
}); });
it('should guard ownership against stuck state', async function () { it('should guard ownership against stuck state', async function () {
await shouldFail.reverting(this.ownable.transferOwnership(ZERO_ADDRESS, { from: owner })); await shouldFail.reverting.withMessage(
this.ownable.transferOwnership(ZERO_ADDRESS, { from: owner }),
'Ownable: new owner is the zero address'
);
}); });
it('loses owner after renouncement', async function () { it('loses owner after renouncement', async function () {
...@@ -32,7 +38,10 @@ function shouldBehaveLikeOwnable (owner, [other]) { ...@@ -32,7 +38,10 @@ function shouldBehaveLikeOwnable (owner, [other]) {
}); });
it('should prevent non-owners from renouncement', async function () { it('should prevent non-owners from renouncement', async function () {
await shouldFail.reverting(this.ownable.renounceOwnership({ from: other })); await shouldFail.reverting.withMessage(
this.ownable.renounceOwnership({ from: other }),
'Ownable: caller is not the owner'
);
}); });
}); });
} }
......
...@@ -18,7 +18,9 @@ contract('Secondary', function ([_, primary, newPrimary, other]) { ...@@ -18,7 +18,9 @@ contract('Secondary', function ([_, primary, newPrimary, other]) {
}); });
it('reverts when anyone calls onlyPrimary functions', async function () { it('reverts when anyone calls onlyPrimary functions', async function () {
await shouldFail.reverting(this.secondary.onlyPrimaryMock({ from: other })); await shouldFail.reverting.withMessage(this.secondary.onlyPrimaryMock({ from: other }),
'Secondary: caller is not the primary account'
);
}); });
}); });
...@@ -30,11 +32,15 @@ contract('Secondary', function ([_, primary, newPrimary, other]) { ...@@ -30,11 +32,15 @@ contract('Secondary', function ([_, primary, newPrimary, other]) {
}); });
it('reverts when transferring to the null address', async function () { it('reverts when transferring to the null address', async function () {
await shouldFail.reverting(this.secondary.transferPrimary(ZERO_ADDRESS, { from: primary })); await shouldFail.reverting.withMessage(this.secondary.transferPrimary(ZERO_ADDRESS, { from: primary }),
'Secondary: new primary is the zero address'
);
}); });
it('reverts when called by anyone', async function () { it('reverts when called by anyone', async function () {
await shouldFail.reverting(this.secondary.transferPrimary(newPrimary, { from: other })); await shouldFail.reverting.withMessage(this.secondary.transferPrimary(newPrimary, { from: other }),
'Secondary: caller is not the primary account'
);
}); });
context('with new primary', function () { context('with new primary', function () {
...@@ -47,7 +53,9 @@ contract('Secondary', function ([_, primary, newPrimary, other]) { ...@@ -47,7 +53,9 @@ contract('Secondary', function ([_, primary, newPrimary, other]) {
}); });
it('reverts when the old primary account calls onlyPrimary functions', async function () { it('reverts when the old primary account calls onlyPrimary functions', async function () {
await shouldFail.reverting(this.secondary.onlyPrimaryMock({ from: primary })); await shouldFail.reverting.withMessage(this.secondary.onlyPrimaryMock({ from: primary }),
'Secondary: caller is not the primary account'
);
}); });
}); });
}); });
......
...@@ -7,27 +7,37 @@ contract('PaymentSplitter', function ([_, owner, payee1, payee2, payee3, nonpaye ...@@ -7,27 +7,37 @@ contract('PaymentSplitter', function ([_, owner, payee1, payee2, payee3, nonpaye
const amount = ether('1'); const amount = ether('1');
it('rejects an empty set of payees', async function () { it('rejects an empty set of payees', async function () {
await shouldFail.reverting(PaymentSplitter.new([], [])); await shouldFail.reverting.withMessage(PaymentSplitter.new([], []), 'PaymentSplitter: no payees');
}); });
it('rejects more payees than shares', async function () { it('rejects more payees than shares', async function () {
await shouldFail.reverting(PaymentSplitter.new([payee1, payee2, payee3], [20, 30])); await shouldFail.reverting.withMessage(PaymentSplitter.new([payee1, payee2, payee3], [20, 30]),
'PaymentSplitter: payees and shares length mismatch'
);
}); });
it('rejects more shares than payees', async function () { it('rejects more shares than payees', async function () {
await shouldFail.reverting(PaymentSplitter.new([payee1, payee2], [20, 30, 40])); await shouldFail.reverting.withMessage(PaymentSplitter.new([payee1, payee2], [20, 30, 40]),
'PaymentSplitter: payees and shares length mismatch'
);
}); });
it('rejects null payees', async function () { it('rejects null payees', async function () {
await shouldFail.reverting(PaymentSplitter.new([payee1, ZERO_ADDRESS], [20, 30])); await shouldFail.reverting.withMessage(PaymentSplitter.new([payee1, ZERO_ADDRESS], [20, 30]),
'PaymentSplitter: account is the zero address'
);
}); });
it('rejects zero-valued shares', async function () { it('rejects zero-valued shares', async function () {
await shouldFail.reverting(PaymentSplitter.new([payee1, payee2], [20, 0])); await shouldFail.reverting.withMessage(PaymentSplitter.new([payee1, payee2], [20, 0]),
'PaymentSplitter: shares are 0'
);
}); });
it('rejects repeated payees', async function () { it('rejects repeated payees', async function () {
await shouldFail.reverting(PaymentSplitter.new([payee1, payee1], [20, 30])); await shouldFail.reverting.withMessage(PaymentSplitter.new([payee1, payee1], [20, 30]),
'PaymentSplitter: account already has shares'
);
}); });
context('once deployed', function () { context('once deployed', function () {
...@@ -64,12 +74,16 @@ contract('PaymentSplitter', function ([_, owner, payee1, payee2, payee3, nonpaye ...@@ -64,12 +74,16 @@ contract('PaymentSplitter', function ([_, owner, payee1, payee2, payee3, nonpaye
}); });
it('should throw if no funds to claim', async function () { it('should throw if no funds to claim', async function () {
await shouldFail.reverting(this.contract.release(payee1)); await shouldFail.reverting.withMessage(this.contract.release(payee1),
'PaymentSplitter: account is not due payment'
);
}); });
it('should throw if non-payee want to claim', async function () { it('should throw if non-payee want to claim', async function () {
await send.ether(payer1, this.contract.address, amount); await send.ether(payer1, this.contract.address, amount);
await shouldFail.reverting(this.contract.release(nonpayee1)); await shouldFail.reverting.withMessage(this.contract.release(nonpayee1),
'PaymentSplitter: account has no shares'
);
}); });
it('should distribute funds to payees', async function () { it('should distribute funds to payees', async function () {
......
...@@ -26,7 +26,9 @@ contract('ConditionalEscrow', function ([_, owner, payee, ...otherAccounts]) { ...@@ -26,7 +26,9 @@ contract('ConditionalEscrow', function ([_, owner, payee, ...otherAccounts]) {
it('reverts on withdrawals', async function () { it('reverts on withdrawals', async function () {
await this.escrow.deposit(payee, { from: owner, value: amount }); await this.escrow.deposit(payee, { from: owner, value: amount });
await shouldFail.reverting(this.escrow.withdraw(payee, { from: owner })); await shouldFail.reverting.withMessage(this.escrow.withdraw(payee, { from: owner }),
'ConditionalEscrow: payee is not allowed to withdraw'
);
}); });
}); });
}); });
...@@ -18,7 +18,9 @@ function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { ...@@ -18,7 +18,9 @@ function shouldBehaveLikeEscrow (primary, [payee1, payee2]) {
}); });
it('only the primary account can deposit', async function () { it('only the primary account can deposit', async function () {
await shouldFail.reverting(this.escrow.deposit(payee1, { from: payee2 })); await shouldFail.reverting.withMessage(this.escrow.deposit(payee1, { from: payee2 }),
'Secondary: caller is not the primary account'
);
}); });
it('emits a deposited event', async function () { it('emits a deposited event', async function () {
...@@ -68,7 +70,9 @@ function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { ...@@ -68,7 +70,9 @@ function shouldBehaveLikeEscrow (primary, [payee1, payee2]) {
}); });
it('only the primary account can withdraw', async function () { it('only the primary account can withdraw', async function () {
await shouldFail.reverting(this.escrow.withdraw(payee1, { from: payee1 })); await shouldFail.reverting.withMessage(this.escrow.withdraw(payee1, { from: payee1 }),
'Secondary: caller is not the primary account'
);
}); });
it('emits a withdrawn event', async function () { it('emits a withdrawn event', async function () {
......
...@@ -8,8 +8,8 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee ...@@ -8,8 +8,8 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee
const refundees = [refundee1, refundee2]; const refundees = [refundee1, refundee2];
it('requires a non-null beneficiary', async function () { it('requires a non-null beneficiary', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
RefundEscrow.new(ZERO_ADDRESS, { from: primary }) RefundEscrow.new(ZERO_ADDRESS, { from: primary }), 'RefundEscrow: beneficiary is the zero address'
); );
}); });
...@@ -32,17 +32,23 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee ...@@ -32,17 +32,23 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee
it('does not refund refundees', async function () { it('does not refund refundees', async function () {
await this.escrow.deposit(refundee1, { from: primary, value: amount }); await this.escrow.deposit(refundee1, { from: primary, value: amount });
await shouldFail.reverting(this.escrow.withdraw(refundee1)); await shouldFail.reverting.withMessage(this.escrow.withdraw(refundee1),
'ConditionalEscrow: payee is not allowed to withdraw'
);
}); });
it('does not allow beneficiary withdrawal', async function () { it('does not allow beneficiary withdrawal', async function () {
await this.escrow.deposit(refundee1, { from: primary, value: amount }); await this.escrow.deposit(refundee1, { from: primary, value: amount });
await shouldFail.reverting(this.escrow.beneficiaryWithdraw()); await shouldFail.reverting.withMessage(this.escrow.beneficiaryWithdraw(),
'RefundEscrow: beneficiary can only withdraw while closed'
);
}); });
}); });
it('only the primary account can enter closed state', async function () { it('only the primary account can enter closed state', async function () {
await shouldFail.reverting(this.escrow.close({ from: beneficiary })); await shouldFail.reverting.withMessage(this.escrow.close({ from: beneficiary }),
'Secondary: caller is not the primary account'
);
const { logs } = await this.escrow.close({ from: primary }); const { logs } = await this.escrow.close({ from: primary });
expectEvent.inLogs(logs, 'RefundsClosed'); expectEvent.inLogs(logs, 'RefundsClosed');
...@@ -56,11 +62,15 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee ...@@ -56,11 +62,15 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee
}); });
it('rejects deposits', async function () { it('rejects deposits', async function () {
await shouldFail.reverting(this.escrow.deposit(refundee1, { from: primary, value: amount })); await shouldFail.reverting.withMessage(this.escrow.deposit(refundee1, { from: primary, value: amount }),
'RefundEscrow: can only deposit while active'
);
}); });
it('does not refund refundees', async function () { it('does not refund refundees', async function () {
await shouldFail.reverting(this.escrow.withdraw(refundee1)); await shouldFail.reverting.withMessage(this.escrow.withdraw(refundee1),
'ConditionalEscrow: payee is not allowed to withdraw'
);
}); });
it('allows beneficiary withdrawal', async function () { it('allows beneficiary withdrawal', async function () {
...@@ -70,16 +80,22 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee ...@@ -70,16 +80,22 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee
}); });
it('prevents entering the refund state', async function () { it('prevents entering the refund state', async function () {
await shouldFail.reverting(this.escrow.enableRefunds({ from: primary })); await shouldFail.reverting.withMessage(this.escrow.enableRefunds({ from: primary }),
'RefundEscrow: can only enable refunds while active'
);
}); });
it('prevents re-entering the closed state', async function () { it('prevents re-entering the closed state', async function () {
await shouldFail.reverting(this.escrow.close({ from: primary })); await shouldFail.reverting.withMessage(this.escrow.close({ from: primary }),
'RefundEscrow: can only close while active'
);
}); });
}); });
it('only the primary account can enter refund state', async function () { it('only the primary account can enter refund state', async function () {
await shouldFail.reverting(this.escrow.enableRefunds({ from: beneficiary })); await shouldFail.reverting.withMessage(this.escrow.enableRefunds({ from: beneficiary }),
'Secondary: caller is not the primary account'
);
const { logs } = await this.escrow.enableRefunds({ from: primary }); const { logs } = await this.escrow.enableRefunds({ from: primary });
expectEvent.inLogs(logs, 'RefundsEnabled'); expectEvent.inLogs(logs, 'RefundsEnabled');
...@@ -93,7 +109,9 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee ...@@ -93,7 +109,9 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee
}); });
it('rejects deposits', async function () { it('rejects deposits', async function () {
await shouldFail.reverting(this.escrow.deposit(refundee1, { from: primary, value: amount })); await shouldFail.reverting.withMessage(this.escrow.deposit(refundee1, { from: primary, value: amount }),
'RefundEscrow: can only deposit while active'
);
}); });
it('refunds refundees', async function () { it('refunds refundees', async function () {
...@@ -105,15 +123,21 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee ...@@ -105,15 +123,21 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee
}); });
it('does not allow beneficiary withdrawal', async function () { it('does not allow beneficiary withdrawal', async function () {
await shouldFail.reverting(this.escrow.beneficiaryWithdraw()); await shouldFail.reverting.withMessage(this.escrow.beneficiaryWithdraw(),
'RefundEscrow: beneficiary can only withdraw while closed'
);
}); });
it('prevents entering the closed state', async function () { it('prevents entering the closed state', async function () {
await shouldFail.reverting(this.escrow.close({ from: primary })); await shouldFail.reverting.withMessage(this.escrow.close({ from: primary }),
'RefundEscrow: can only close while active'
);
}); });
it('prevents re-entering the refund state', async function () { it('prevents re-entering the refund state', async function () {
await shouldFail.reverting(this.escrow.enableRefunds({ from: primary })); await shouldFail.reverting.withMessage(this.escrow.enableRefunds({ from: primary }),
'RefundEscrow: can only enable refunds while active'
);
}); });
}); });
}); });
......
...@@ -37,7 +37,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) { ...@@ -37,7 +37,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) {
const amount = initialSupply.addn(1); const amount = initialSupply.addn(1);
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.transfer(to, amount, { from: initialHolder })); await shouldFail.reverting.withMessage(this.token.transfer(to, amount, { from: initialHolder }),
'SafeMath: subtraction overflow'
);
}); });
}); });
...@@ -68,7 +70,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) { ...@@ -68,7 +70,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) {
const to = ZERO_ADDRESS; const to = ZERO_ADDRESS;
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.transfer(to, initialSupply, { from: initialHolder })); await shouldFail.reverting.withMessage(this.token.transfer(to, initialSupply, { from: initialHolder }),
'ERC20: transfer to the zero address'
);
}); });
}); });
}); });
...@@ -126,7 +130,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) { ...@@ -126,7 +130,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) {
const amount = initialSupply.addn(1); const amount = initialSupply.addn(1);
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.transferFrom(initialHolder, to, amount, { from: spender })); await shouldFail.reverting.withMessage(this.token.transferFrom(
initialHolder, to, amount, { from: spender }), 'SafeMath: subtraction overflow'
);
}); });
}); });
}); });
...@@ -140,7 +146,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) { ...@@ -140,7 +146,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) {
const amount = initialSupply; const amount = initialSupply;
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.transferFrom(initialHolder, to, amount, { from: spender })); await shouldFail.reverting.withMessage(this.token.transferFrom(
initialHolder, to, amount, { from: spender }), 'SafeMath: subtraction overflow'
);
}); });
}); });
...@@ -148,7 +156,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) { ...@@ -148,7 +156,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) {
const amount = initialSupply.addn(1); const amount = initialSupply.addn(1);
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.transferFrom(initialHolder, to, amount, { from: spender })); await shouldFail.reverting.withMessage(this.token.transferFrom(
initialHolder, to, amount, { from: spender }), 'SafeMath: subtraction overflow'
);
}); });
}); });
}); });
...@@ -163,7 +173,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) { ...@@ -163,7 +173,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) {
}); });
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.transferFrom(initialHolder, to, amount, { from: spender })); await shouldFail.reverting.withMessage(this.token.transferFrom(
initialHolder, to, amount, { from: spender }), 'ERC20: transfer to the zero address'
);
}); });
}); });
}); });
...@@ -175,7 +187,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) { ...@@ -175,7 +187,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) {
function shouldDecreaseApproval (amount) { function shouldDecreaseApproval (amount) {
describe('when there was no approved amount before', function () { describe('when there was no approved amount before', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.decreaseAllowance(spender, amount, { from: initialHolder })); await shouldFail.reverting.withMessage(this.token.decreaseAllowance(
spender, amount, { from: initialHolder }), 'SafeMath: subtraction overflow'
);
}); });
}); });
...@@ -208,8 +222,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) { ...@@ -208,8 +222,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) {
}); });
it('reverts when more than the full allowance is removed', async function () { it('reverts when more than the full allowance is removed', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.token.decreaseAllowance(spender, approvedAmount.addn(1), { from: initialHolder }) this.token.decreaseAllowance(spender, approvedAmount.addn(1), { from: initialHolder }),
'SafeMath: subtraction overflow'
); );
}); });
}); });
...@@ -233,7 +248,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) { ...@@ -233,7 +248,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) {
const spender = ZERO_ADDRESS; const spender = ZERO_ADDRESS;
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.decreaseAllowance(spender, amount, { from: initialHolder })); await shouldFail.reverting.withMessage(this.token.decreaseAllowance(
spender, amount, { from: initialHolder }, 'ERC20: approve to the zero address')
);
}); });
}); });
}); });
...@@ -315,16 +332,19 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) { ...@@ -315,16 +332,19 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) {
const spender = ZERO_ADDRESS; const spender = ZERO_ADDRESS;
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.increaseAllowance(spender, amount, { from: initialHolder })); await shouldFail.reverting.withMessage(
this.token.increaseAllowance(spender, amount, { from: initialHolder }), 'ERC20: approve to the zero address'
);
}); });
}); });
}); });
describe('_mint', function () { describe('_mint', function () {
const amount = new BN(50); const amount = new BN(50);
it('rejects a null account', async function () {
it('rejects a zero account', async function () { await shouldFail.reverting.withMessage(
await shouldFail.reverting(this.token.mint(ZERO_ADDRESS, amount)); this.token.mint(ZERO_ADDRESS, amount), 'ERC20: mint to the zero address'
);
}); });
describe('for a non zero account', function () { describe('for a non zero account', function () {
...@@ -354,13 +374,16 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) { ...@@ -354,13 +374,16 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) {
}); });
describe('_burn', function () { describe('_burn', function () {
it('rejects a zero account', async function () { it('rejects a null account', async function () {
await shouldFail.reverting(this.token.burn(ZERO_ADDRESS, new BN(1))); await shouldFail.reverting.withMessage(this.token.burn(ZERO_ADDRESS, new BN(1)),
'ERC20: burn from the zero address');
}); });
describe('for a non zero account', function () { describe('for a non zero account', function () {
it('rejects burning more than balance', async function () { it('rejects burning more than balance', async function () {
await shouldFail.reverting(this.token.burn(initialHolder, initialSupply.addn(1))); await shouldFail.reverting.withMessage(this.token.burn(
initialHolder, initialSupply.addn(1)), 'SafeMath: subtraction overflow'
);
}); });
const describeBurn = function (description, amount) { const describeBurn = function (description, amount) {
...@@ -405,17 +428,23 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) { ...@@ -405,17 +428,23 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) {
await this.token.approve(spender, allowance, { from: initialHolder }); await this.token.approve(spender, allowance, { from: initialHolder });
}); });
it('rejects a zero account', async function () { it('rejects a null account', async function () {
await shouldFail.reverting(this.token.burnFrom(ZERO_ADDRESS, new BN(1))); await shouldFail.reverting.withMessage(this.token.burnFrom(ZERO_ADDRESS, new BN(1)),
'ERC20: burn from the zero address'
);
}); });
describe('for a non zero account', function () { describe('for a non zero account', function () {
it('rejects burning more than allowance', async function () { it('rejects burning more than allowance', async function () {
await shouldFail.reverting(this.token.burnFrom(initialHolder, allowance.addn(1))); await shouldFail.reverting.withMessage(this.token.burnFrom(initialHolder, allowance.addn(1)),
'SafeMath: subtraction overflow'
);
}); });
it('rejects burning more than balance', async function () { it('rejects burning more than balance', async function () {
await shouldFail.reverting(this.token.burnFrom(initialHolder, initialSupply.addn(1))); await shouldFail.reverting.withMessage(this.token.burnFrom(initialHolder, initialSupply.addn(1)),
'SafeMath: subtraction overflow'
);
}); });
const describeBurnFrom = function (description, amount) { const describeBurnFrom = function (description, amount) {
...@@ -477,7 +506,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) { ...@@ -477,7 +506,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) {
describe('when the owner is the zero address', function () { describe('when the owner is the zero address', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.approveInternal(ZERO_ADDRESS, recipient, initialSupply)); await shouldFail.reverting.withMessage(this.token.approveInternal(ZERO_ADDRESS, recipient, initialSupply),
'ERC20: approve from the zero address'
);
}); });
}); });
}); });
...@@ -555,7 +586,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) { ...@@ -555,7 +586,9 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) {
describe('when the spender is the zero address', function () { describe('when the spender is the zero address', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(approve.call(this, owner, ZERO_ADDRESS, supply)); await shouldFail.reverting.withMessage(approve.call(this, owner, ZERO_ADDRESS, supply),
'ERC20: approve to the zero address'
);
}); });
}); });
} }
......
...@@ -8,8 +8,8 @@ contract('ERC20Capped', function ([_, minter, ...otherAccounts]) { ...@@ -8,8 +8,8 @@ contract('ERC20Capped', function ([_, minter, ...otherAccounts]) {
const cap = ether('1000'); const cap = ether('1000');
it('requires a non-zero cap', async function () { it('requires a non-zero cap', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
ERC20Capped.new(new BN(0), { from: minter }) ERC20Capped.new(new BN(0), { from: minter }), 'ERC20Capped: cap is 0'
); );
}); });
......
...@@ -42,7 +42,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA ...@@ -42,7 +42,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA
}); });
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.pause({ from })); await shouldFail.reverting.withMessage(this.token.pause({ from }), 'Pausable: paused');
}); });
}); });
}); });
...@@ -51,7 +51,9 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA ...@@ -51,7 +51,9 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA
const from = anotherAccount; const from = anotherAccount;
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.pause({ from })); await shouldFail.reverting.withMessage(this.token.pause({ from }),
'PauserRole: caller does not have the Pauser role'
);
}); });
}); });
}); });
...@@ -79,7 +81,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA ...@@ -79,7 +81,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA
describe('when the token is unpaused', function () { describe('when the token is unpaused', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.unpause({ from })); await shouldFail.reverting.withMessage(this.token.unpause({ from }), 'Pausable: not paused');
}); });
}); });
}); });
...@@ -88,7 +90,9 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA ...@@ -88,7 +90,9 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA
const from = anotherAccount; const from = anotherAccount;
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.unpause({ from })); await shouldFail.reverting.withMessage(this.token.unpause({ from }),
'PauserRole: caller does not have the Pauser role'
);
}); });
}); });
}); });
...@@ -134,7 +138,9 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA ...@@ -134,7 +138,9 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA
it('reverts when trying to transfer when paused', async function () { it('reverts when trying to transfer when paused', async function () {
await this.token.pause({ from: pauser }); await this.token.pause({ from: pauser });
await shouldFail.reverting(this.token.transfer(recipient, initialSupply, { from: pauser })); await shouldFail.reverting.withMessage(this.token.transfer(recipient, initialSupply, { from: pauser }),
'Pausable: paused'
);
}); });
}); });
...@@ -159,7 +165,9 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA ...@@ -159,7 +165,9 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA
it('reverts when trying to approve when paused', async function () { it('reverts when trying to approve when paused', async function () {
await this.token.pause({ from: pauser }); await this.token.pause({ from: pauser });
await shouldFail.reverting(this.token.approve(anotherAccount, allowance, { from: pauser })); await shouldFail.reverting.withMessage(this.token.approve(anotherAccount, allowance, { from: pauser }),
'Pausable: paused'
);
}); });
}); });
...@@ -190,7 +198,9 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA ...@@ -190,7 +198,9 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA
it('reverts when trying to transfer from when paused', async function () { it('reverts when trying to transfer from when paused', async function () {
await this.token.pause({ from: pauser }); await this.token.pause({ from: pauser });
await shouldFail.reverting(this.token.transferFrom(pauser, recipient, allowance, { from: anotherAccount })); await shouldFail.reverting.withMessage(this.token.transferFrom(
pauser, recipient, allowance, { from: anotherAccount }), 'Pausable: paused'
);
}); });
}); });
...@@ -220,7 +230,9 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA ...@@ -220,7 +230,9 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA
it('reverts when trying to transfer when paused', async function () { it('reverts when trying to transfer when paused', async function () {
await this.token.pause({ from: pauser }); await this.token.pause({ from: pauser });
await shouldFail.reverting(this.token.decreaseAllowance(anotherAccount, decrement, { from: pauser })); await shouldFail.reverting.withMessage(this.token.decreaseAllowance(
anotherAccount, decrement, { from: pauser }), 'Pausable: paused'
);
}); });
}); });
...@@ -250,7 +262,9 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA ...@@ -250,7 +262,9 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA
it('reverts when trying to increase approval when paused', async function () { it('reverts when trying to increase approval when paused', async function () {
await this.token.pause({ from: pauser }); await this.token.pause({ from: pauser });
await shouldFail.reverting(this.token.increaseAllowance(anotherAccount, increment, { from: pauser })); await shouldFail.reverting.withMessage(this.token.increaseAllowance(
anotherAccount, increment, { from: pauser }), 'Pausable: paused'
);
}); });
}); });
}); });
......
...@@ -11,7 +11,7 @@ contract('SafeERC20', function ([_, hasNoCode]) { ...@@ -11,7 +11,7 @@ contract('SafeERC20', function ([_, hasNoCode]) {
this.wrapper = await SafeERC20Wrapper.new(hasNoCode); this.wrapper = await SafeERC20Wrapper.new(hasNoCode);
}); });
shouldRevertOnAllCalls(); shouldRevertOnAllCalls('SafeERC20: call to non-contract');
}); });
describe('with token that returns false on all calls', function () { describe('with token that returns false on all calls', function () {
...@@ -19,7 +19,7 @@ contract('SafeERC20', function ([_, hasNoCode]) { ...@@ -19,7 +19,7 @@ contract('SafeERC20', function ([_, hasNoCode]) {
this.wrapper = await SafeERC20Wrapper.new((await ERC20ReturnFalseMock.new()).address); this.wrapper = await SafeERC20Wrapper.new((await ERC20ReturnFalseMock.new()).address);
}); });
shouldRevertOnAllCalls(); shouldRevertOnAllCalls('SafeERC20: ERC20 operation did not succeed');
}); });
describe('with token that returns true on all calls', function () { describe('with token that returns true on all calls', function () {
...@@ -39,24 +39,26 @@ contract('SafeERC20', function ([_, hasNoCode]) { ...@@ -39,24 +39,26 @@ contract('SafeERC20', function ([_, hasNoCode]) {
}); });
}); });
function shouldRevertOnAllCalls () { function shouldRevertOnAllCalls (reason) {
it('reverts on transfer', async function () { it('reverts on transfer', async function () {
await shouldFail.reverting(this.wrapper.transfer()); await shouldFail.reverting.withMessage(this.wrapper.transfer(), reason);
}); });
it('reverts on transferFrom', async function () { it('reverts on transferFrom', async function () {
await shouldFail.reverting(this.wrapper.transferFrom()); await shouldFail.reverting.withMessage(this.wrapper.transferFrom(), reason);
}); });
it('reverts on approve', async function () { it('reverts on approve', async function () {
await shouldFail.reverting(this.wrapper.approve(0)); await shouldFail.reverting.withMessage(this.wrapper.approve(0), reason);
}); });
it('reverts on increaseAllowance', async function () { it('reverts on increaseAllowance', async function () {
// [TODO] make sure it's reverting for the right reason
await shouldFail.reverting(this.wrapper.increaseAllowance(0)); await shouldFail.reverting(this.wrapper.increaseAllowance(0));
}); });
it('reverts on decreaseAllowance', async function () { it('reverts on decreaseAllowance', async function () {
// [TODO] make sure it's reverting for the right reason
await shouldFail.reverting(this.wrapper.decreaseAllowance(0)); await shouldFail.reverting(this.wrapper.decreaseAllowance(0));
}); });
} }
...@@ -89,7 +91,10 @@ function shouldOnlyRevertOnErrors () { ...@@ -89,7 +91,10 @@ function shouldOnlyRevertOnErrors () {
}); });
it('reverts when decreasing the allowance', async function () { it('reverts when decreasing the allowance', async function () {
await shouldFail.reverting(this.wrapper.decreaseAllowance(10)); await shouldFail.reverting.withMessage(
this.wrapper.decreaseAllowance(10),
'SafeMath: subtraction overflow'
);
}); });
}); });
...@@ -99,7 +104,10 @@ function shouldOnlyRevertOnErrors () { ...@@ -99,7 +104,10 @@ function shouldOnlyRevertOnErrors () {
}); });
it('reverts when approving a non-zero allowance', async function () { it('reverts when approving a non-zero allowance', async function () {
await shouldFail.reverting(this.wrapper.approve(20)); await shouldFail.reverting.withMessage(
this.wrapper.approve(20),
'SafeERC20: approve from non-zero to non-zero allowance'
);
}); });
it('doesn\'t revert when approving a zero allowance', async function () { it('doesn\'t revert when approving a zero allowance', async function () {
...@@ -115,7 +123,10 @@ function shouldOnlyRevertOnErrors () { ...@@ -115,7 +123,10 @@ function shouldOnlyRevertOnErrors () {
}); });
it('reverts when decreasing the allowance to a negative value', async function () { it('reverts when decreasing the allowance to a negative value', async function () {
await shouldFail.reverting(this.wrapper.decreaseAllowance(200)); await shouldFail.reverting.withMessage(
this.wrapper.decreaseAllowance(200),
'SafeMath: subtraction overflow'
);
}); });
}); });
}); });
......
...@@ -13,7 +13,7 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) { ...@@ -13,7 +13,7 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) {
it('rejects a release time in the past', async function () { it('rejects a release time in the past', async function () {
const pastReleaseTime = (await time.latest()).sub(time.duration.years(1)); const pastReleaseTime = (await time.latest()).sub(time.duration.years(1));
await shouldFail.reverting( await shouldFail.reverting.withMessage(
TokenTimelock.new(this.token.address, beneficiary, pastReleaseTime) TokenTimelock.new(this.token.address, beneficiary, pastReleaseTime)
); );
}); });
...@@ -32,12 +32,12 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) { ...@@ -32,12 +32,12 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) {
}); });
it('cannot be released before time limit', async function () { it('cannot be released before time limit', async function () {
await shouldFail.reverting(this.timelock.release()); await shouldFail.reverting.withMessage(this.timelock.release());
}); });
it('cannot be released just before time limit', async function () { it('cannot be released just before time limit', async function () {
await time.increaseTo(this.releaseTime.sub(time.duration.seconds(3))); await time.increaseTo(this.releaseTime.sub(time.duration.seconds(3)));
await shouldFail.reverting(this.timelock.release()); await shouldFail.reverting.withMessage(this.timelock.release());
}); });
it('can be released just after limit', async function () { it('can be released just after limit', async function () {
...@@ -55,7 +55,7 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) { ...@@ -55,7 +55,7 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) {
it('cannot be released twice', async function () { it('cannot be released twice', async function () {
await time.increaseTo(this.releaseTime.add(time.duration.years(1))); await time.increaseTo(this.releaseTime.add(time.duration.years(1)));
await this.timelock.release(); await this.timelock.release();
await shouldFail.reverting(this.timelock.release()); await shouldFail.reverting.withMessage(this.timelock.release());
(await this.token.balanceOf(beneficiary)).should.be.bignumber.equal(amount); (await this.token.balanceOf(beneficiary)).should.be.bignumber.equal(amount);
}); });
}); });
......
...@@ -35,7 +35,9 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { ...@@ -35,7 +35,9 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) {
const amount = initialBalance.addn(1); const amount = initialBalance.addn(1);
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.burn(amount, { from: owner })); await shouldFail.reverting.withMessage(this.token.burn(amount, { from: owner }),
'SafeMath: subtraction overflow'
);
}); });
}); });
}); });
...@@ -82,7 +84,9 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { ...@@ -82,7 +84,9 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) {
it('reverts', async function () { it('reverts', async function () {
await this.token.approve(burner, amount, { from: owner }); await this.token.approve(burner, amount, { from: owner });
await shouldFail.reverting(this.token.burnFrom(owner, amount, { from: burner })); await shouldFail.reverting.withMessage(this.token.burnFrom(owner, amount, { from: burner }),
'SafeMath: subtraction overflow'
);
}); });
}); });
...@@ -91,7 +95,9 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { ...@@ -91,7 +95,9 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) {
it('reverts', async function () { it('reverts', async function () {
await this.token.approve(burner, allowance, { from: owner }); await this.token.approve(burner, allowance, { from: owner });
await shouldFail.reverting(this.token.burnFrom(owner, allowance.addn(1), { from: burner })); await shouldFail.reverting.withMessage(this.token.burnFrom(owner, allowance.addn(1), { from: burner }),
'SafeMath: subtraction overflow'
);
}); });
}); });
}); });
......
...@@ -15,12 +15,12 @@ function shouldBehaveLikeERC20Capped (minter, [other], cap) { ...@@ -15,12 +15,12 @@ function shouldBehaveLikeERC20Capped (minter, [other], cap) {
it('should fail to mint if the amount exceeds the cap', async function () { it('should fail to mint if the amount exceeds the cap', async function () {
await this.token.mint(other, cap.subn(1), { from }); await this.token.mint(other, cap.subn(1), { from });
await shouldFail.reverting(this.token.mint(other, 2, { from })); await shouldFail.reverting.withMessage(this.token.mint(other, 2, { from }));
}); });
it('should fail to mint after cap is reached', async function () { it('should fail to mint after cap is reached', async function () {
await this.token.mint(other, cap, { from }); await this.token.mint(other, cap, { from });
await shouldFail.reverting(this.token.mint(other, 1, { from })); await shouldFail.reverting.withMessage(this.token.mint(other, 1, { from }));
}); });
}); });
} }
......
...@@ -40,7 +40,9 @@ function shouldBehaveLikeERC20Mintable (minter, [other]) { ...@@ -40,7 +40,9 @@ function shouldBehaveLikeERC20Mintable (minter, [other]) {
const from = other; const from = other;
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.mint(other, amount, { from })); await shouldFail.reverting.withMessage(this.token.mint(other, amount, { from }),
'MinterRole: caller does not have the Minter role'
);
}); });
}); });
}); });
......
...@@ -36,7 +36,9 @@ function shouldBehaveLikeERC721 ( ...@@ -36,7 +36,9 @@ function shouldBehaveLikeERC721 (
context('when querying the zero address', function () { context('when querying the zero address', function () {
it('throws', async function () { it('throws', async function () {
await shouldFail.reverting(this.token.balanceOf(ZERO_ADDRESS)); await shouldFail.reverting.withMessage(
this.token.balanceOf(ZERO_ADDRESS), 'ERC721: balance query for the zero address'
);
}); });
}); });
}); });
...@@ -54,7 +56,9 @@ function shouldBehaveLikeERC721 ( ...@@ -54,7 +56,9 @@ function shouldBehaveLikeERC721 (
const tokenId = unknownTokenId; const tokenId = unknownTokenId;
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.ownerOf(tokenId)); await shouldFail.reverting.withMessage(
this.token.ownerOf(tokenId), 'ERC721: owner query for nonexistent token'
);
}); });
}); });
}); });
...@@ -178,29 +182,36 @@ function shouldBehaveLikeERC721 ( ...@@ -178,29 +182,36 @@ function shouldBehaveLikeERC721 (
context('when the address of the previous owner is incorrect', function () { context('when the address of the previous owner is incorrect', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(transferFunction.call(this, other, other, tokenId, { from: owner }) await shouldFail.reverting.withMessage(
transferFunction.call(this, other, other, tokenId, { from: owner }),
'ERC721: transfer of token that is not own'
); );
}); });
}); });
context('when the sender is not authorized for the token id', function () { context('when the sender is not authorized for the token id', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(transferFunction.call(this, owner, other, tokenId, { from: other }) await shouldFail.reverting.withMessage(
transferFunction.call(this, owner, other, tokenId, { from: other }),
'ERC721: transfer caller is not owner nor approved'
); );
}); });
}); });
context('when the given token ID does not exist', function () { context('when the given token ID does not exist', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(transferFunction.call(this, owner, other, unknownTokenId, { from: owner }) await shouldFail.reverting.withMessage(
transferFunction.call(this, owner, other, unknownTokenId, { from: owner }),
'ERC721: operator query for nonexistent token'
); );
}); });
}); });
context('when the address to transfer the token to is the zero address', function () { context('when the address to transfer the token to is the zero address', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
transferFunction.call(this, owner, ZERO_ADDRESS, tokenId, { from: owner }) transferFunction.call(this, owner, ZERO_ADDRESS, tokenId, { from: owner }),
'ERC721: transfer to the zero address'
); );
}); });
}); });
...@@ -258,14 +269,15 @@ function shouldBehaveLikeERC721 ( ...@@ -258,14 +269,15 @@ function shouldBehaveLikeERC721 (
describe('with an invalid token id', function () { describe('with an invalid token id', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
transferFun.call( transferFun.call(
this, this,
owner, owner,
this.receiver.address, this.receiver.address,
unknownTokenId, unknownTokenId,
{ from: owner }, { from: owner },
) ),
'ERC721: operator query for nonexistent token'
); );
}); });
}); });
...@@ -283,8 +295,9 @@ function shouldBehaveLikeERC721 ( ...@@ -283,8 +295,9 @@ function shouldBehaveLikeERC721 (
describe('to a receiver contract returning unexpected value', function () { describe('to a receiver contract returning unexpected value', function () {
it('reverts', async function () { it('reverts', async function () {
const invalidReceiver = await ERC721ReceiverMock.new('0x42', false); const invalidReceiver = await ERC721ReceiverMock.new('0x42', false);
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner }) this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner }),
'ERC721: transfer to non ERC721Receiver implementer'
); );
}); });
}); });
...@@ -292,8 +305,9 @@ function shouldBehaveLikeERC721 ( ...@@ -292,8 +305,9 @@ function shouldBehaveLikeERC721 (
describe('to a receiver contract that throws', function () { describe('to a receiver contract that throws', function () {
it('reverts', async function () { it('reverts', async function () {
const invalidReceiver = await ERC721ReceiverMock.new(RECEIVER_MAGIC_VALUE, true); const invalidReceiver = await ERC721ReceiverMock.new(RECEIVER_MAGIC_VALUE, true);
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner }) this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner }),
'ERC721ReceiverMock: reverting'
); );
}); });
}); });
...@@ -301,8 +315,9 @@ function shouldBehaveLikeERC721 ( ...@@ -301,8 +315,9 @@ function shouldBehaveLikeERC721 (
describe('to a contract that does not implement the required function', function () { describe('to a contract that does not implement the required function', function () {
it('reverts', async function () { it('reverts', async function () {
const invalidReceiver = this.token; const invalidReceiver = this.token;
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner }) this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner }),
'VM Exception while processing transaction: revert'
); );
}); });
}); });
...@@ -390,22 +405,24 @@ function shouldBehaveLikeERC721 ( ...@@ -390,22 +405,24 @@ function shouldBehaveLikeERC721 (
context('when the address that receives the approval is the owner', function () { context('when the address that receives the approval is the owner', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.token.approve(owner, tokenId, { from: owner }) this.token.approve(owner, tokenId, { from: owner }), 'ERC721: transfer to current owner'
); );
}); });
}); });
context('when the sender does not own the given token ID', function () { context('when the sender does not own the given token ID', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.approve(approved, tokenId, { from: other })); await shouldFail.reverting.withMessage(this.token.approve(approved, tokenId, { from: other }),
'ERC721: approve caller is not owner nor approved');
}); });
}); });
context('when the sender is approved for the given token ID', function () { context('when the sender is approved for the given token ID', function () {
it('reverts', async function () { it('reverts', async function () {
await this.token.approve(approved, tokenId, { from: owner }); await this.token.approve(approved, tokenId, { from: owner });
await shouldFail.reverting(this.token.approve(anotherApproved, tokenId, { from: approved })); await shouldFail.reverting.withMessage(this.token.approve(anotherApproved, tokenId, { from: approved }),
'ERC721: approve caller is not owner nor approved for all');
}); });
}); });
...@@ -421,7 +438,8 @@ function shouldBehaveLikeERC721 ( ...@@ -421,7 +438,8 @@ function shouldBehaveLikeERC721 (
context('when the given token ID does not exist', function () { context('when the given token ID does not exist', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.approve(approved, unknownTokenId, { from: operator })); await shouldFail.reverting.withMessage(this.token.approve(approved, unknownTokenId, { from: operator }),
'ERC721: owner query for nonexistent token');
}); });
}); });
}); });
...@@ -499,7 +517,8 @@ function shouldBehaveLikeERC721 ( ...@@ -499,7 +517,8 @@ function shouldBehaveLikeERC721 (
context('when the operator is the owner', function () { context('when the operator is the owner', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.setApprovalForAll(owner, true, { from: owner })); await shouldFail.reverting.withMessage(this.token.setApprovalForAll(owner, true, { from: owner }),
'ERC721: approve to caller');
}); });
}); });
}); });
......
...@@ -15,8 +15,10 @@ contract('ERC721', function ([_, creator, tokenOwner, other, ...accounts]) { ...@@ -15,8 +15,10 @@ contract('ERC721', function ([_, creator, tokenOwner, other, ...accounts]) {
const tokenId = new BN('5042'); const tokenId = new BN('5042');
describe('_mint(address, uint256)', function () { describe('_mint(address, uint256)', function () {
it('reverts with a zero destination address', async function () { it('reverts with a null destination address', async function () {
await shouldFail.reverting(this.token.mint(ZERO_ADDRESS, tokenId)); await shouldFail.reverting.withMessage(
this.token.mint(ZERO_ADDRESS, tokenId), 'ERC721: mint to the zero address'
);
}); });
context('with minted token', async function () { context('with minted token', async function () {
...@@ -34,14 +36,16 @@ contract('ERC721', function ([_, creator, tokenOwner, other, ...accounts]) { ...@@ -34,14 +36,16 @@ contract('ERC721', function ([_, creator, tokenOwner, other, ...accounts]) {
}); });
it('reverts when adding a token id that already exists', async function () { it('reverts when adding a token id that already exists', async function () {
await shouldFail.reverting(this.token.mint(tokenOwner, tokenId)); await shouldFail.reverting.withMessage(this.token.mint(tokenOwner, tokenId), 'ERC721: token already minted');
}); });
}); });
}); });
describe('_burn(address, uint256)', function () { describe('_burn(address, uint256)', function () {
it('reverts when burning a non-existent token id', async function () { it('reverts when burning a non-existent token id', async function () {
await shouldFail.reverting(this.token.methods['burn(address,uint256)'](tokenOwner, tokenId)); await shouldFail.reverting.withMessage(
this.token.methods['burn(address,uint256)'](tokenOwner, tokenId), 'ERC721: owner query for nonexistent token'
);
}); });
context('with minted token', function () { context('with minted token', function () {
...@@ -50,7 +54,9 @@ contract('ERC721', function ([_, creator, tokenOwner, other, ...accounts]) { ...@@ -50,7 +54,9 @@ contract('ERC721', function ([_, creator, tokenOwner, other, ...accounts]) {
}); });
it('reverts when the account is not the owner', async function () { it('reverts when the account is not the owner', async function () {
await shouldFail.reverting(this.token.methods['burn(address,uint256)'](other, tokenId)); await shouldFail.reverting.withMessage(
this.token.methods['burn(address,uint256)'](other, tokenId), 'ERC721: burn of token that is not own'
);
}); });
context('with burnt token', function () { context('with burnt token', function () {
...@@ -64,11 +70,16 @@ contract('ERC721', function ([_, creator, tokenOwner, other, ...accounts]) { ...@@ -64,11 +70,16 @@ contract('ERC721', function ([_, creator, tokenOwner, other, ...accounts]) {
it('deletes the token', async function () { it('deletes the token', async function () {
(await this.token.balanceOf(tokenOwner)).should.be.bignumber.equal('0'); (await this.token.balanceOf(tokenOwner)).should.be.bignumber.equal('0');
await shouldFail.reverting(this.token.ownerOf(tokenId)); await shouldFail.reverting.withMessage(
this.token.ownerOf(tokenId), 'ERC721: owner query for nonexistent token'
);
}); });
it('reverts when burning a token id that has been deleted', async function () { it('reverts when burning a token id that has been deleted', async function () {
await shouldFail.reverting(this.token.methods['burn(address,uint256)'](tokenOwner, tokenId)); await shouldFail.reverting.withMessage(
this.token.methods['burn(address,uint256)'](tokenOwner, tokenId),
'ERC721: owner query for nonexistent token'
);
}); });
}); });
}); });
...@@ -76,7 +87,9 @@ contract('ERC721', function ([_, creator, tokenOwner, other, ...accounts]) { ...@@ -76,7 +87,9 @@ contract('ERC721', function ([_, creator, tokenOwner, other, ...accounts]) {
describe('_burn(uint256)', function () { describe('_burn(uint256)', function () {
it('reverts when burning a non-existent token id', async function () { it('reverts when burning a non-existent token id', async function () {
await shouldFail.reverting(this.token.methods['burn(uint256)'](tokenId)); await shouldFail.reverting.withMessage(
this.token.methods['burn(uint256)'](tokenId), 'ERC721: owner query for nonexistent token'
);
}); });
context('with minted token', function () { context('with minted token', function () {
...@@ -95,11 +108,15 @@ contract('ERC721', function ([_, creator, tokenOwner, other, ...accounts]) { ...@@ -95,11 +108,15 @@ contract('ERC721', function ([_, creator, tokenOwner, other, ...accounts]) {
it('deletes the token', async function () { it('deletes the token', async function () {
(await this.token.balanceOf(tokenOwner)).should.be.bignumber.equal('0'); (await this.token.balanceOf(tokenOwner)).should.be.bignumber.equal('0');
await shouldFail.reverting(this.token.ownerOf(tokenId)); await shouldFail.reverting.withMessage(
this.token.ownerOf(tokenId), 'ERC721: owner query for nonexistent token'
);
}); });
it('reverts when burning a token id that has been deleted', async function () { it('reverts when burning a token id that has been deleted', async function () {
await shouldFail.reverting(this.token.methods['burn(uint256)'](tokenId)); await shouldFail.reverting.withMessage(
this.token.methods['burn(uint256)'](tokenId), 'ERC721: owner query for nonexistent token'
);
}); });
}); });
}); });
......
...@@ -64,7 +64,9 @@ contract('ERC721Full', function ([ ...@@ -64,7 +64,9 @@ contract('ERC721Full', function ([
it('burns all tokens', async function () { it('burns all tokens', async function () {
await this.token.burn(secondTokenId, { from: owner }); await this.token.burn(secondTokenId, { from: owner });
(await this.token.totalSupply()).should.be.bignumber.equal('0'); (await this.token.totalSupply()).should.be.bignumber.equal('0');
await shouldFail.reverting(this.token.tokenByIndex(0)); await shouldFail.reverting.withMessage(
this.token.tokenByIndex(0), 'ERC721Enumerable: global index out of bounds'
);
}); });
}); });
...@@ -85,7 +87,9 @@ contract('ERC721Full', function ([ ...@@ -85,7 +87,9 @@ contract('ERC721Full', function ([
}); });
it('reverts when setting metadata for non existent token id', async function () { it('reverts when setting metadata for non existent token id', async function () {
await shouldFail.reverting(this.token.setTokenURI(nonExistentTokenId, sampleUri)); await shouldFail.reverting.withMessage(
this.token.setTokenURI(nonExistentTokenId, sampleUri), 'ERC721Metadata: URI set of nonexistent token'
);
}); });
it('can burn token with metadata', async function () { it('can burn token with metadata', async function () {
...@@ -99,7 +103,9 @@ contract('ERC721Full', function ([ ...@@ -99,7 +103,9 @@ contract('ERC721Full', function ([
}); });
it('reverts when querying metadata for non existent token id', async function () { it('reverts when querying metadata for non existent token id', async function () {
await shouldFail.reverting(this.token.tokenURI(nonExistentTokenId)); await shouldFail.reverting.withMessage(
this.token.tokenURI(nonExistentTokenId), 'ERC721Metadata: URI query for nonexistent token'
);
}); });
}); });
...@@ -127,13 +133,17 @@ contract('ERC721Full', function ([ ...@@ -127,13 +133,17 @@ contract('ERC721Full', function ([
describe('when the index is greater than or equal to the total tokens owned by the given address', function () { describe('when the index is greater than or equal to the total tokens owned by the given address', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.tokenOfOwnerByIndex(owner, 2)); await shouldFail.reverting.withMessage(
this.token.tokenOfOwnerByIndex(owner, 2), 'ERC721Enumerable: owner index out of bounds'
);
}); });
}); });
describe('when the given address does not own any token', function () { describe('when the given address does not own any token', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.tokenOfOwnerByIndex(another, 0)); await shouldFail.reverting.withMessage(
this.token.tokenOfOwnerByIndex(another, 0), 'ERC721Enumerable: owner index out of bounds'
);
}); });
}); });
...@@ -153,7 +163,9 @@ contract('ERC721Full', function ([ ...@@ -153,7 +163,9 @@ contract('ERC721Full', function ([
it('returns empty collection for original owner', async function () { it('returns empty collection for original owner', async function () {
(await this.token.balanceOf(owner)).should.be.bignumber.equal('0'); (await this.token.balanceOf(owner)).should.be.bignumber.equal('0');
await shouldFail.reverting(this.token.tokenOfOwnerByIndex(owner, 0)); await shouldFail.reverting.withMessage(
this.token.tokenOfOwnerByIndex(owner, 0), 'ERC721Enumerable: owner index out of bounds'
);
}); });
}); });
}); });
...@@ -167,7 +179,9 @@ contract('ERC721Full', function ([ ...@@ -167,7 +179,9 @@ contract('ERC721Full', function ([
}); });
it('should revert if index is greater than supply', async function () { it('should revert if index is greater than supply', async function () {
await shouldFail.reverting(this.token.tokenByIndex(2)); await shouldFail.reverting.withMessage(
this.token.tokenByIndex(2), 'ERC721Enumerable: global index out of bounds'
);
}); });
[firstTokenId, secondTokenId].forEach(function (tokenId) { [firstTokenId, secondTokenId].forEach(function (tokenId) {
......
...@@ -46,13 +46,18 @@ function shouldBehaveLikeMintAndBurnERC721 ( ...@@ -46,13 +46,18 @@ function shouldBehaveLikeMintAndBurnERC721 (
describe('when the given owner address is the zero address', function () { describe('when the given owner address is the zero address', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.mint(ZERO_ADDRESS, thirdTokenId, { from: minter })); await shouldFail.reverting.withMessage(
this.token.mint(ZERO_ADDRESS, thirdTokenId, { from: minter }),
'ERC721: mint to the zero address'
);
}); });
}); });
describe('when the given token ID was already tracked by this contract', function () { describe('when the given token ID was already tracked by this contract', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.mint(owner, firstTokenId, { from: minter })); await shouldFail.reverting.withMessage(this.token.mint(owner, firstTokenId, { from: minter }),
'ERC721: token already minted.'
);
}); });
}); });
}); });
...@@ -76,7 +81,10 @@ function shouldBehaveLikeMintAndBurnERC721 ( ...@@ -76,7 +81,10 @@ function shouldBehaveLikeMintAndBurnERC721 (
}); });
it('burns the given token ID and adjusts the balance of the owner', async function () { it('burns the given token ID and adjusts the balance of the owner', async function () {
await shouldFail.reverting(this.token.ownerOf(tokenId)); await shouldFail.reverting.withMessage(
this.token.ownerOf(tokenId),
'ERC721: owner query for nonexistent token'
);
(await this.token.balanceOf(owner)).should.be.bignumber.equal('1'); (await this.token.balanceOf(owner)).should.be.bignumber.equal('1');
}); });
...@@ -98,15 +106,17 @@ function shouldBehaveLikeMintAndBurnERC721 ( ...@@ -98,15 +106,17 @@ function shouldBehaveLikeMintAndBurnERC721 (
context('getApproved', function () { context('getApproved', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting(this.token.getApproved(tokenId)); await shouldFail.reverting.withMessage(
this.token.getApproved(tokenId), 'ERC721: approved query for nonexistent token'
);
}); });
}); });
}); });
describe('when the given token ID was not tracked by this contract', function () { describe('when the given token ID was not tracked by this contract', function () {
it('reverts', async function () { it('reverts', async function () {
await shouldFail.reverting( await shouldFail.reverting.withMessage(
this.token.burn(unknownTokenId, { from: creator }) this.token.burn(unknownTokenId, { from: creator }), 'ERC721: operator query for nonexistent token'
); );
}); });
}); });
......
...@@ -12,24 +12,34 @@ function shouldBehaveLikeERC721PausedToken (owner, [recipient, operator]) { ...@@ -12,24 +12,34 @@ function shouldBehaveLikeERC721PausedToken (owner, [recipient, operator]) {
}); });
it('reverts when trying to approve', async function () { it('reverts when trying to approve', async function () {
await shouldFail.reverting(this.token.approve(recipient, firstTokenId, { from: owner })); await shouldFail.reverting.withMessage(
this.token.approve(recipient, firstTokenId, { from: owner }), 'Pausable: paused'
);
}); });
it('reverts when trying to setApprovalForAll', async function () { it('reverts when trying to setApprovalForAll', async function () {
await shouldFail.reverting(this.token.setApprovalForAll(operator, true, { from: owner })); await shouldFail.reverting.withMessage(
this.token.setApprovalForAll(operator, true, { from: owner }), 'Pausable: paused'
);
}); });
it('reverts when trying to transferFrom', async function () { it('reverts when trying to transferFrom', async function () {
await shouldFail.reverting(this.token.transferFrom(owner, recipient, firstTokenId, { from: owner })); await shouldFail.reverting.withMessage(
this.token.transferFrom(owner, recipient, firstTokenId, { from: owner }), 'Pausable: paused'
);
}); });
it('reverts when trying to safeTransferFrom', async function () { it('reverts when trying to safeTransferFrom', async function () {
await shouldFail.reverting(this.token.safeTransferFrom(owner, recipient, firstTokenId, { from: owner })); await shouldFail.reverting.withMessage(
this.token.safeTransferFrom(owner, recipient, firstTokenId, { from: owner }), 'Pausable: paused'
);
}); });
it('reverts when trying to safeTransferFrom with data', async function () { it('reverts when trying to safeTransferFrom with data', async function () {
await shouldFail.reverting(this.token.methods['safeTransferFrom(address,address,uint256,bytes)']( await shouldFail.reverting.withMessage(
owner, recipient, firstTokenId, mockData, { from: owner }) this.token.methods['safeTransferFrom(address,address,uint256,bytes)'](
owner, recipient, firstTokenId, mockData, { from: owner }
), 'Pausable: paused'
); );
}); });
......
...@@ -11,7 +11,8 @@ contract('ReentrancyGuard', function () { ...@@ -11,7 +11,8 @@ contract('ReentrancyGuard', function () {
it('should not allow remote callback', async function () { it('should not allow remote callback', async function () {
const attacker = await ReentrancyAttack.new(); const attacker = await ReentrancyAttack.new();
await shouldFail.reverting(this.reentrancyMock.countAndCall(attacker.address)); await shouldFail.reverting.withMessage(
this.reentrancyMock.countAndCall(attacker.address), 'ReentrancyGuard: reentrant call');
}); });
// The following are more side-effects than intended behavior: // The following are more side-effects than intended behavior:
...@@ -19,10 +20,14 @@ contract('ReentrancyGuard', function () { ...@@ -19,10 +20,14 @@ contract('ReentrancyGuard', function () {
// in the side-effects. // in the side-effects.
it('should not allow local recursion', async function () { it('should not allow local recursion', async function () {
await shouldFail.reverting(this.reentrancyMock.countLocalRecursive(10)); await shouldFail.reverting.withMessage(
this.reentrancyMock.countLocalRecursive(10), 'ReentrancyGuard: reentrant call'
);
}); });
it('should not allow indirect local recursion', async function () { it('should not allow indirect local recursion', async function () {
await shouldFail.reverting(this.reentrancyMock.countThisRecursive(10)); await shouldFail.reverting.withMessage(
this.reentrancyMock.countThisRecursive(10), 'ReentrancyMock: failed call'
);
}); });
}); });
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment