From 9170b5cae6ab6f62000a6e3ca8aec5e728f63893 Mon Sep 17 00:00:00 2001 From: 0xLucian <0xluciandev@gmail.com> Date: Fri, 28 Jul 2023 18:16:37 +0300 Subject: [PATCH] refactor: Adhere to best practices --- contracts/PegStability/PegStability.sol | 185 ++++++++++++++++-------- tests/hardhat/Fork/pegStabilityTest.ts | 12 +- tests/hardhat/VAI/PegStability.ts | 130 +++++++++-------- 3 files changed, 204 insertions(+), 123 deletions(-) diff --git a/contracts/PegStability/PegStability.sol b/contracts/PegStability/PegStability.sol index 3b0a2f913..dfd03d9ba 100644 --- a/contracts/PegStability/PegStability.sol +++ b/contracts/PegStability/PegStability.sol @@ -7,7 +7,7 @@ import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeab import "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol"; import { ResilientOracleInterface } from "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol"; -interface VAI { +interface IVAI { function balanceOf(address usr) external returns (uint256); function transferFrom(address src, address dst, uint amount) external returns (bool); @@ -17,7 +17,7 @@ interface VAI { function burn(address usr, uint wad) external; } -interface DecimalProvider { +interface IDecimalProvider { function decimals() external view returns (uint8); } @@ -46,9 +46,9 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable uint256 public immutable ONE_DOLLAR; - /// @notice The address of the VAI token contract. + /// @notice VAI token contract. /// @custom:oz-upgrades-unsafe-allow state-variable-immutable - address public immutable VAI_ADDRESS; + IVAI public immutable VAI; /// @notice The address of the stable token contract. /// @custom:oz-upgrades-unsafe-allow state-variable-immutable @@ -88,7 +88,7 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { event FeeOutChanged(uint256 oldFeeOut, uint256 newFeeOut); /// @notice Event emitted when vaiMintCap state var is modified. - event VaiMintCapChanged(uint256 oldCap, uint256 newCap); + event VAIMintCapChanged(uint256 oldCap, uint256 newCap); /// @notice Event emitted when venusTreasury state var is modified. event VenusTreasuryChanged(address indexed oldTreasury, address indexed newTreasury); @@ -100,26 +100,65 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { event StableForVAISwapped(uint256 stableIn, uint256 vaiOut, uint256 fee); /// @notice Event emitted when stable token is swapped for VAI. - event VaiForStableSwapped(uint256 vaiBurnt, uint256 vaiFee, uint256 stableOut); + event VAIForStableSwapped(uint256 vaiBurnt, uint256 stableOut, uint256 vaiFee); + + /// @notice thrown when contract is in paused state + error Paused(); + + /// @notice thrown when attempted to pause an already paused contract + error AlreadyPaused(); + + /// @notice thrown when attempted to resume the contract if it is already resumed + error NotPaused(); + + /// @notice thrown when stable token has more than 18 decimals + error TooManyDecimals(); + + /// @notice thrown when fee is >= 100% + error InvalidFee(); + + /// @notice thrown when a zero address is passed as a function parameter + error ZeroAddress(); + + /// @notice thrown when a zero amount is passed as stable token amount parameter + error ZeroAmount(); + + /// @notice thrown when the user doesn't have enough VAI balance to provide for the amount of stable tokens he wishes to get + error NotEnoughVAI(); + + /// @notice thrown when the amount of VAI to be burnt exceeds the vaiMinted amount + error VAIMintedUnderflow(); + + /// @notice thrown when the VAI transfer to treasury fails + error VAITransferFail(); + + /// @notice thrown when VAI to be minted will go beyond the mintCap threshold + error VAIMintCapReached(); + /// @notice thrown when fee calculation will result in rounding down to 0 due to stable token amount being a too small number + error AmountTooSmall(); /** * @dev Prevents functions to execute when contract is paused. */ modifier isActive() { - require(!isPaused, "Contract is paused."); + if (isPaused) revert Paused(); _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor(address stableTokenAddress_, address vaiAddress_) { - ensureNonzeroAddress(stableTokenAddress_); - ensureNonzeroAddress(vaiAddress_); + _ensureNonzeroAddress(stableTokenAddress_); + _ensureNonzeroAddress(vaiAddress_); + + uint256 decimals_ = IDecimalProvider(stableTokenAddress_).decimals(); + + if (decimals_ > 18) { + revert TooManyDecimals(); + } - uint256 decimals_ = DecimalProvider(stableTokenAddress_).decimals(); - require(decimals_ <= 18, "too much decimals"); ONE_DOLLAR = 10 ** (36 - decimals_); // 1$ scaled to the decimals returned by our Oracle STABLE_TOKEN_ADDRESS = stableTokenAddress_; - VAI_ADDRESS = vaiAddress_; + VAI = IVAI(vaiAddress_); _disableInitializers(); } @@ -140,14 +179,15 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { uint256 feeOut_, uint256 vaiMintCap_ ) external initializer { - ensureNonzeroAddress(accessControlManager_); - ensureNonzeroAddress(venusTreasury_); - ensureNonzeroAddress(oracleAddress_); + _ensureNonzeroAddress(accessControlManager_); + _ensureNonzeroAddress(venusTreasury_); + _ensureNonzeroAddress(oracleAddress_); __AccessControlled_init(accessControlManager_); __ReentrancyGuard_init(); - require(feeIn_ < BASIS_POINTS_DIVISOR, "Invalid fee in."); - require(feeOut_ < BASIS_POINTS_DIVISOR, "Invalid fee out."); + if (feeIn_ >= BASIS_POINTS_DIVISOR || feeOut_ >= BASIS_POINTS_DIVISOR) { + revert InvalidFee(); + } feeIn = feeIn_; feeOut = feeOut_; @@ -164,34 +204,40 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { * @param stableTknAmount The amount of stable tokens to receive. * @return The amount of VAI received and burnt from the sender. */ - // @custom:event Emits VaiForStableSwapped event. + // @custom:event Emits VAIForStableSwapped event. function swapVAIForStable( address receiver, uint256 stableTknAmount ) external isActive nonReentrant returns (uint256) { - ensureNonzeroAddress(receiver); - require(stableTknAmount > 0, "Amount must be greater than zero."); + _ensureNonzeroAddress(receiver); + _ensureNonzeroAmount(stableTknAmount); // update oracle price and calculate USD value of the stable token amount scaled in 18 decimals oracle.updateAssetPrice(STABLE_TOKEN_ADDRESS); - uint256 stableTknAmountUSD = previewTokenUSDAmount(stableTknAmount, FeeDirection.OUT); + uint256 stableTknAmountUSD = _previewTokenUSDAmount(stableTknAmount, FeeDirection.OUT); uint256 fee = _calculateFee(stableTknAmountUSD, FeeDirection.OUT); - require(VAI(VAI_ADDRESS).balanceOf(msg.sender) >= stableTknAmountUSD + fee, "Not enough VAI."); - require(vaiMinted >= stableTknAmountUSD, "Can't burn more VAI than minted."); + if (VAI.balanceOf(msg.sender) < stableTknAmountUSD + fee) { + revert NotEnoughVAI(); + } + if (vaiMinted < stableTknAmountUSD) { + revert VAIMintedUnderflow(); + } unchecked { vaiMinted -= stableTknAmountUSD; } if (fee != 0) { - bool success = VAI(VAI_ADDRESS).transferFrom(msg.sender, venusTreasury, fee); - require(success, "VAI fee transfer failed."); + bool success = VAI.transferFrom(msg.sender, venusTreasury, fee); + if (!success) { + revert VAITransferFail(); + } } - VAI(VAI_ADDRESS).burn(msg.sender, stableTknAmountUSD); + VAI.burn(msg.sender, stableTknAmountUSD); IERC20Upgradeable(STABLE_TOKEN_ADDRESS).safeTransfer(receiver, stableTknAmount); - emit VaiForStableSwapped(stableTknAmountUSD, fee, stableTknAmount); + emit VAIForStableSwapped(stableTknAmountUSD, stableTknAmount, fee); return stableTknAmountUSD; } @@ -207,9 +253,8 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { address receiver, uint256 stableTknAmount ) external isActive nonReentrant returns (uint256) { - ensureNonzeroAddress(receiver); - require(stableTknAmount > 0, "Amount must be greater than zero."); - + _ensureNonzeroAddress(receiver); + _ensureNonzeroAmount(stableTknAmount); // transfer IN, supporting fee-on-transfer tokens uint256 balanceBefore = IERC20Upgradeable(STABLE_TOKEN_ADDRESS).balanceOf(address(this)); IERC20Upgradeable(STABLE_TOKEN_ADDRESS).safeTransferFrom(msg.sender, address(this), stableTknAmount); @@ -220,23 +265,25 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { // update oracle price and calculate USD value of the stable token amount scaled in 18 decimals oracle.updateAssetPrice(STABLE_TOKEN_ADDRESS); - uint256 actualTransferAmtInUSD = previewTokenUSDAmount(actualTransferAmt, FeeDirection.IN); + uint256 actualTransferAmtInUSD = _previewTokenUSDAmount(actualTransferAmt, FeeDirection.IN); //calculate feeIn uint256 fee = _calculateFee(actualTransferAmtInUSD, FeeDirection.IN); uint256 vaiToMint = actualTransferAmtInUSD - fee; - require(vaiMinted + actualTransferAmtInUSD <= vaiMintCap, "VAI mint cap reached."); + if (vaiMinted + actualTransferAmtInUSD > vaiMintCap) { + revert VAIMintCapReached(); + } unchecked { vaiMinted += actualTransferAmtInUSD; } // mint VAI to receiver - VAI(VAI_ADDRESS).mint(receiver, vaiToMint); + VAI.mint(receiver, vaiToMint); // mint VAI fee to venus treasury if (fee != 0) { - VAI(VAI_ADDRESS).mint(venusTreasury, fee); + VAI.mint(venusTreasury, fee); } emit StableForVAISwapped(actualTransferAmt, vaiToMint, fee); @@ -252,7 +299,9 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { // @custom:event Emits PSMPaused event. function pause() external { _checkAccessAllowed("pause()"); - require(!isPaused, "PSM is already paused."); + if (isPaused) { + revert AlreadyPaused(); + } isPaused = true; emit PSMPaused(msg.sender); } @@ -264,7 +313,9 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { // @custom:event Emits PSMResumed event. function resume() external { _checkAccessAllowed("resume()"); - require(isPaused, "PSM is not paused."); + if (!isPaused) { + revert NotPaused(); + } isPaused = false; emit PSMResumed(msg.sender); } @@ -278,7 +329,9 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { function setFeeIn(uint256 feeIn_) external { _checkAccessAllowed("setFeeIn(uint256)"); // feeIn = 10000 = 100% - require(feeIn_ < BASIS_POINTS_DIVISOR, "Invalid fee."); + if (feeIn_ >= BASIS_POINTS_DIVISOR) { + revert InvalidFee(); + } uint256 oldFeeIn = feeIn; feeIn = feeIn_; emit FeeInChanged(oldFeeIn, feeIn_); @@ -293,7 +346,9 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { function setFeeOut(uint256 feeOut_) external { _checkAccessAllowed("setFeeOut(uint256)"); // feeOut = 10000 = 100% - require(feeOut_ < BASIS_POINTS_DIVISOR, "Invalid fee."); + if (feeOut_ >= BASIS_POINTS_DIVISOR) { + revert InvalidFee(); + } uint256 oldFeeOut = feeOut; feeOut = feeOut_; emit FeeOutChanged(oldFeeOut, feeOut_); @@ -303,12 +358,12 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { * @dev Set the maximum amount of VAI that can be minted through this contract. * @param vaiMintCap_ The new maximum amount of VAI that can be minted. */ - // @custom:event Emits VaiMintCapChanged event. - function setVaiMintCap(uint256 vaiMintCap_) external { - _checkAccessAllowed("setVaiMintCap(uint256)"); - uint256 oldVaiMintCap = vaiMintCap; + // @custom:event Emits VAIMintCapChanged event. + function setVAIMintCap(uint256 vaiMintCap_) external { + _checkAccessAllowed("setVAIMintCap(uint256)"); + uint256 oldVAIMintCap = vaiMintCap; vaiMintCap = vaiMintCap_; - emit VaiMintCapChanged(oldVaiMintCap, vaiMintCap_); + emit VAIMintCapChanged(oldVAIMintCap, vaiMintCap_); } /** @@ -319,7 +374,7 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { // @custom:event Emits VenusTreasuryChanged event. function setVenusTreasury(address venusTreasury_) external { _checkAccessAllowed("setVenusTreasury(address)"); - ensureNonzeroAddress(venusTreasury_); + _ensureNonzeroAddress(venusTreasury_); address oldTreasuryAddress = venusTreasury; venusTreasury = venusTreasury_; emit VenusTreasuryChanged(oldTreasuryAddress, venusTreasury_); @@ -333,7 +388,7 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { // @custom:event Emits OracleChanged event. function setOracle(address oracleAddress_) external { _checkAccessAllowed("setOracle(address)"); - ensureNonzeroAddress(oracleAddress_); + _ensureNonzeroAddress(oracleAddress_); address oldOracleAddress = address(oracle); oracle = ResilientOracleInterface(oracleAddress_); emit OracleChanged(oldOracleAddress, oracleAddress_); @@ -353,12 +408,13 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { * @return The amount of VAI that would be taken from the user. */ function previewSwapVAIForStable(uint256 stableTknAmount) external view returns (uint256) { - require(stableTknAmount > 0, "Amount must be greater than zero."); - - uint256 stableTknAmountUSD = previewTokenUSDAmount(stableTknAmount, FeeDirection.OUT); + _ensureNonzeroAmount(stableTknAmount); + uint256 stableTknAmountUSD = _previewTokenUSDAmount(stableTknAmount, FeeDirection.OUT); uint256 fee = _calculateFee(stableTknAmountUSD, FeeDirection.OUT); - require(vaiMinted >= stableTknAmountUSD, "Can't burn more VAI than minted."); + if (vaiMinted < stableTknAmountUSD) { + revert VAIMintedUnderflow(); + } return stableTknAmountUSD + fee; } @@ -370,15 +426,16 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { * @return The amount of VAI that would be sent to the receiver. */ function previewSwapStableForVAI(uint256 stableTknAmount) external view returns (uint256) { - require(stableTknAmount > 0, "Amount must be greater than zero."); - - uint256 stableTknAmountUSD = previewTokenUSDAmount(stableTknAmount, FeeDirection.IN); + _ensureNonzeroAmount(stableTknAmount); + uint256 stableTknAmountUSD = _previewTokenUSDAmount(stableTknAmount, FeeDirection.IN); //calculate feeIn uint256 fee = _calculateFee(stableTknAmountUSD, FeeDirection.IN); uint256 vaiToMint = stableTknAmountUSD - fee; - require(vaiMinted + stableTknAmountUSD <= vaiMintCap, "VAI mint cap reached."); + if (vaiMinted + stableTknAmountUSD > vaiMintCap) { + revert VAIMintCapReached(); + } return vaiToMint; } @@ -389,8 +446,8 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { * @param direction The direction of the swap. * @return The USD value of the given amount of stable tokens scaled by 1e18 taking into account the direction of the swap */ - function previewTokenUSDAmount(uint256 amount, FeeDirection direction) internal view returns (uint256) { - return (amount * getPriceInUSD(direction)) / MANTISSA_ONE; + function _previewTokenUSDAmount(uint256 amount, FeeDirection direction) internal view returns (uint256) { + return (amount * _getPriceInUSD(direction)) / MANTISSA_ONE; } /** @@ -399,7 +456,7 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { * @param direction The direction of the swap: FeeDirection.IN or FeeDirection.OUT. * @return The price in USD, adjusted based on the selected direction. */ - function getPriceInUSD(FeeDirection direction) internal view returns (uint256) { + function _getPriceInUSD(FeeDirection direction) internal view returns (uint256) { // get price with a scale = (36 - asset_decimals) uint256 price = oracle.getPrice(STABLE_TOKEN_ADDRESS); @@ -430,7 +487,9 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { return 0; } else { // checking if the percent calculation will result in rounding down to 0 - require(amount * feePercent >= BASIS_POINTS_DIVISOR, "Amount too small."); + if (amount * feePercent < BASIS_POINTS_DIVISOR) { + revert AmountTooSmall(); + } return (amount * feePercent) / BASIS_POINTS_DIVISOR; } } @@ -439,7 +498,15 @@ contract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable { * @notice Checks that the address is not the zero address. * @param someone The address to check. */ - function ensureNonzeroAddress(address someone) private pure { - require(someone != address(0), "Can't be zero address."); + function _ensureNonzeroAddress(address someone) private pure { + if (someone == address(0)) revert ZeroAddress(); + } + + /** + * @notice Checks that the amount passed as stable tokens is bigger than zero + * @param amount The amount to validate + */ + function _ensureNonzeroAmount(uint256 amount) private pure { + if (amount == 0) revert ZeroAmount(); } } diff --git a/tests/hardhat/Fork/pegStabilityTest.ts b/tests/hardhat/Fork/pegStabilityTest.ts index 64523a731..e94b8a4c5 100644 --- a/tests/hardhat/Fork/pegStabilityTest.ts +++ b/tests/hardhat/Fork/pegStabilityTest.ts @@ -76,7 +76,7 @@ async function deployPegStability(stableToken: string): Promise { // * Flow Validation Functions * // ***************************** async function validateInitialization(psm: PegStability, stableToken: string) { - expect(await psm.VAI_ADDRESS()).to.equal(Contracts.VAI); + expect(await psm.VAI()).to.equal(Contracts.VAI); expect((await psm.STABLE_TOKEN_ADDRESS()).toLocaleLowerCase()).to.equal(stableToken.toLocaleLowerCase()); expect((await psm.venusTreasury()).toLocaleLowerCase()).to.equal(venusTreasury); expect(await psm.oracle()).to.equal(resilientOracle); @@ -87,7 +87,7 @@ async function validateInitialization(psm: PegStability, stableToken: string) { expect(await psm.isPaused()).to.be.false; expect(await psm.accessControlManager()).to.equal(acmAddress); } -async function swapStableForVaiAndValidate( +async function swapStableForVAIAndValidate( psm: PegStability, stableToken: FaucetToken, stableTokenPrice: BigNumber, @@ -110,7 +110,7 @@ async function swapStableForVaiAndValidate( await expect(tx).to.emit(psm, "StableForVAISwapped").withArgs(stableTokenAmount, vaiToMint, fee); } -async function swapVaiForStableAndValidate( +async function swapVAIForStableAndValidate( psm: PegStability, stableTokenName: string, stableTokenPrice: BigNumber, @@ -124,7 +124,7 @@ async function swapVaiForStableAndValidate( formatConsoleLog(`${stableTokenName} Price: ` + stableTokenPrice.toString()); await VAI.connect(vaiSigner).approve(psm.address, tokenAmountUsd); const tx = await psm.connect(vaiSigner).swapVAIForStable(VAI_HOLDER, convertToUnit(100, 18)); - await expect(tx).to.emit(psm, "VaiForStableSwapped").withArgs(tokenAmountUsd, 0, tokenAmount); + await expect(tx).to.emit(psm, "VAIForStableSwapped").withArgs(tokenAmountUsd, tokenAmount, 0); } async function validateReInitialization(psm: PegStability) { @@ -180,10 +180,10 @@ if (FORK_MAINNET) { }); describe("Swap", () => { it(`${stableTokenName} -> VAI`, async () => { - return swapStableForVaiAndValidate(psm, stableToken, stableTokenPrice, tokenSigner, tokenHolder, VAI); + return swapStableForVAIAndValidate(psm, stableToken, stableTokenPrice, tokenSigner, tokenHolder, VAI); }); it(`VAI -> ${stableTokenName}`, async () => { - return swapVaiForStableAndValidate(psm, stableTokenName, stableTokenPrice, VAI, vaiSigner); + return swapVAIForStableAndValidate(psm, stableTokenName, stableTokenPrice, VAI, vaiSigner); }); }); }); diff --git a/tests/hardhat/VAI/PegStability.ts b/tests/hardhat/VAI/PegStability.ts index ff7794a16..2dbfcb46b 100644 --- a/tests/hardhat/VAI/PegStability.ts +++ b/tests/hardhat/VAI/PegStability.ts @@ -64,7 +64,7 @@ async function pegStabilityFixture(tokenDecimals: number): Promise, adminAddress: string, pegStability: MockContract, @@ -86,7 +86,7 @@ async function swapStableForVaiAndVerify( await expect(tx).to.emit(pegStability, "StableForVAISwapped").withArgs(STABLE_TOKEN_AMOUNT, VAI_TO_SEND, VAI_FEE); } -async function swapVaiForStableAndVerify( +async function swapVAIForStableAndVerify( vai: FakeContract, adminAddress: string, USER_VAI_BALANCE: string, @@ -107,8 +107,8 @@ async function swapVaiForStableAndVerify( expect(vai.burn).to.have.been.calledOnceWith(adminAddress, VAI_TO_BURN); expect(stableToken.transfer).to.have.been.calledOnceWith(receiverAddress, STABLE_TOKEN_AMOUNT); await expect(tx) - .to.emit(pegStability, "VaiForStableSwapped") - .withArgs(VAI_TO_BURN, VAI_FEE_TO_TREASURY, STABLE_TOKEN_AMOUNT); + .to.emit(pegStability, "VAIForStableSwapped") + .withArgs(VAI_TO_BURN, STABLE_TOKEN_AMOUNT, VAI_FEE_TO_TREASURY); } describe("Peg Stability Module", () => { tokenDecimals.forEach(function (decimals) { @@ -186,7 +186,7 @@ describe("Peg Stability Module", () => { TEN_PERCENT, VAI_MINT_CAP, ), - ).to.be.rejectedWith("Can't be zero address"); + ).to.be.revertedWithCustomError(pegStability, "ZeroAddress"); }); it("treasury", async () => { await expect( @@ -198,7 +198,7 @@ describe("Peg Stability Module", () => { TEN_PERCENT, VAI_MINT_CAP, ), - ).to.be.rejectedWith("Can't be zero address"); + ).to.be.revertedWithCustomError(pegStability, "ZeroAddress"); }); it("stableToken", async () => { await expect( @@ -210,10 +210,10 @@ describe("Peg Stability Module", () => { TEN_PERCENT, VAI_MINT_CAP, ), - ).to.be.rejectedWith("Can't be zero address"); + ).to.be.revertedWithCustomError(pegStability, "ZeroAddress"); }); }); - describe("reverts is fee init value is invalid", () => { + describe("reverts if fee init value is invalid", () => { it("feeIn", async () => { await expect( pegStability.initialize( @@ -224,7 +224,7 @@ describe("Peg Stability Module", () => { TEN_PERCENT, VAI_MINT_CAP, ), - ).to.be.rejectedWith("Invalid fee in"); + ).to.be.revertedWithCustomError(pegStability, "InvalidFee"); }); it("feeOut", async () => { await expect( @@ -236,7 +236,7 @@ describe("Peg Stability Module", () => { HUNDERD_PERCENT, //invalid VAI_MINT_CAP, ), - ).to.be.rejectedWith("Invalid fee out"); + ).to.be.revertedWithCustomError(pegStability, "InvalidFee"); }); }); it("should initialize sucessfully", async () => { @@ -266,7 +266,7 @@ describe("Peg Stability Module", () => { it("should revert if already paused", async () => { acm.isAllowedToCall.whenCalledWith(adminAddress, "pause()").returns(true); await pegStability.setVariable("isPaused", true); - await expect(pegStability.pause()).to.be.revertedWith("PSM is already paused."); + await expect(pegStability.pause()).to.be.revertedWithCustomError(pegStability, "AlreadyPaused"); }); }); describe("resume()", () => { @@ -283,7 +283,7 @@ describe("Peg Stability Module", () => { it("should revert if already resumed", async () => { acm.isAllowedToCall.whenCalledWith(adminAddress, "resume()").returns(true); await pegStability.setVariable("isPaused", false); - await expect(pegStability.resume()).to.be.revertedWith("PSM is not paused."); + await expect(pegStability.resume()).to.be.revertedWithCustomError(pegStability, "NotPaused"); }); }); describe("setFeeIn(uint256)", () => { @@ -292,7 +292,10 @@ describe("Peg Stability Module", () => { }); it("should revert if fee is invalid", async () => { acm.isAllowedToCall.whenCalledWith(adminAddress, "setFeeIn(uint256)").returns(true); - await expect(pegStability.setFeeIn(HUNDERD_PERCENT)).to.be.revertedWith("Invalid fee."); + await expect(pegStability.setFeeIn(HUNDERD_PERCENT)).to.be.revertedWithCustomError( + pegStability, + "InvalidFee", + ); }); it("set the correct fee", async () => { acm.isAllowedToCall.whenCalledWith(adminAddress, "setFeeIn(uint256)").returns(true); @@ -309,7 +312,10 @@ describe("Peg Stability Module", () => { }); it("should revert if fee is invalid", async () => { acm.isAllowedToCall.whenCalledWith(adminAddress, "setFeeIn(uint256)").returns(true); - await expect(pegStability.setFeeIn(HUNDERD_PERCENT)).to.be.revertedWith("Invalid fee."); + await expect(pegStability.setFeeIn(HUNDERD_PERCENT)).to.be.revertedWithCustomError( + pegStability, + "InvalidFee", + ); }); it("set the correct fee", async () => { acm.isAllowedToCall.whenCalledWith(adminAddress, "setFeeOut(uint256)").returns(true); @@ -320,16 +326,16 @@ describe("Peg Stability Module", () => { expect(feeOut).to.equal(TWENTY_PERCENT); }); }); - describe("setVaiMintCap(uint256)", () => { + describe("setVAIMintCap(uint256)", () => { it("should revert if not authorised", async () => { - await expect(pegStability.setVaiMintCap(0)).to.be.revertedWithCustomError(pegStability, "Unauthorized"); + await expect(pegStability.setVAIMintCap(0)).to.be.revertedWithCustomError(pegStability, "Unauthorized"); }); it("should set the correct mint cap", async () => { const OLD_MINT_CAP = await pegStability.getVariable("vaiMintCap"); const NEW_MINT_CAP = convertToUnit(10, 18); - acm.isAllowedToCall.whenCalledWith(adminAddress, "setVaiMintCap(uint256)").returns(true); - await expect(pegStability.setVaiMintCap(NEW_MINT_CAP)) - .to.emit(pegStability, "VaiMintCapChanged") + acm.isAllowedToCall.whenCalledWith(adminAddress, "setVAIMintCap(uint256)").returns(true); + await expect(pegStability.setVAIMintCap(NEW_MINT_CAP)) + .to.emit(pegStability, "VAIMintCapChanged") .withArgs(OLD_MINT_CAP, NEW_MINT_CAP); expect(await pegStability.getVariable("vaiMintCap")).to.equal(NEW_MINT_CAP); }); @@ -343,8 +349,9 @@ describe("Peg Stability Module", () => { }); it("should revert if zero address", async () => { acm.isAllowedToCall.whenCalledWith(adminAddress, "setVenusTreasury(address)").returns(true); - await expect(pegStability.setVenusTreasury(ethers.constants.AddressZero)).to.be.revertedWith( - "Can't be zero address.", + await expect(pegStability.setVenusTreasury(ethers.constants.AddressZero)).to.be.revertedWithCustomError( + pegStability, + "ZeroAddress", ); }); it("should set the treasury address", async () => { @@ -365,8 +372,9 @@ describe("Peg Stability Module", () => { }); it("should revert if oracle address is zero", async () => { acm.isAllowedToCall.whenCalledWith(adminAddress, "setOracle(address)").returns(true); - await expect(pegStability.setOracle(ethers.constants.AddressZero)).to.be.revertedWith( - "Can't be zero address.", + await expect(pegStability.setOracle(ethers.constants.AddressZero)).to.be.revertedWithCustomError( + pegStability, + "ZeroAddress", ); }); it("should set the oracle", async () => { @@ -384,10 +392,16 @@ describe("Peg Stability Module", () => { await pegStability.setVariable("isPaused", true); }); it("should revert when paused and call swapVAIForStable(address,uint256)", async () => { - await expect(pegStability.swapVAIForStable(adminAddress, 100)).to.be.revertedWith("Contract is paused."); + await expect(pegStability.swapVAIForStable(adminAddress, 100)).to.be.revertedWithCustomError( + pegStability, + "Paused", + ); }); it("should revert when paused and call swapStableForVAI(address,uint256)", async () => { - await expect(pegStability.swapStableForVAI(adminAddress, 100)).to.be.revertedWith("Contract is paused."); + await expect(pegStability.swapStableForVAI(adminAddress, 100)).to.be.revertedWithCustomError( + pegStability, + "Paused", + ); }); }); describe("Swap functions", () => { @@ -397,32 +411,32 @@ describe("Peg Stability Module", () => { await pegStability.setVariable("vaiMinted", VAI_MINTED); }); it("should revert if receiver is zero address ", async () => { - await expect(pegStability.swapVAIForStable(ethers.constants.AddressZero, 100)).to.be.revertedWith( - "Can't be zero address.", - ); + await expect( + pegStability.swapVAIForStable(ethers.constants.AddressZero, 100), + ).to.be.revertedWithCustomError(pegStability, "ZeroAddress"); }); it("should revert if sender has insufficient VAI balance ", async () => { const USER_VAI_BALANCE = convertToUnit(109, 18); // USER NEEDS TO HAVE 110 VAI vai.balanceOf.whenCalledWith(adminAddress).returns(USER_VAI_BALANCE); - await expect(pegStability.swapVAIForStable(adminAddress, STABLE_TOKEN_AMOUNT)).to.be.revertedWith( - "Not enough VAI.", - ); + await expect( + pegStability.swapVAIForStable(adminAddress, STABLE_TOKEN_AMOUNT), + ).to.be.revertedWithCustomError(pegStability, "NotEnoughVAI"); }); it("should revert if VAI transfer fails ", async () => { const USER_VAI_BALANCE = convertToUnit(110, 18); vai.balanceOf.whenCalledWith(adminAddress).returns(USER_VAI_BALANCE); - await expect(pegStability.swapVAIForStable(adminAddress, STABLE_TOKEN_AMOUNT)).to.be.revertedWith( - "VAI fee transfer failed.", - ); + await expect( + pegStability.swapVAIForStable(adminAddress, STABLE_TOKEN_AMOUNT), + ).to.be.revertedWithCustomError(pegStability, "VAITransferFail"); }); it("should revert if VAI to be burnt > vaiMinted ", async () => { const STABLE_TOKEN_AMOUNT_DOUBLE = STABLE_TOKEN_AMOUNT.mul(2); const USER_VAI_BALANCE = convertToUnit(300, 18); vai.balanceOf.whenCalledWith(adminAddress).returns(USER_VAI_BALANCE); vai.transferFrom.returns(true); - await expect(pegStability.swapVAIForStable(adminAddress, STABLE_TOKEN_AMOUNT_DOUBLE)).to.be.revertedWith( - "Can't burn more VAI than minted.", - ); + await expect( + pegStability.swapVAIForStable(adminAddress, STABLE_TOKEN_AMOUNT_DOUBLE), + ).to.be.revertedWithCustomError(pegStability, "VAIMintedUnderflow"); }); describe("should sucessfully perform the swap", () => { beforeEach(async () => { @@ -433,7 +447,7 @@ describe("Peg Stability Module", () => { const VAI_FEE_TO_TREASURY = convertToUnit(10, 18); const VAI_TO_BURN = convertToUnit(100, 18); it("stable token = 1$ ", async () => { - await swapVaiForStableAndVerify( + await swapVAIForStableAndVerify( vai, adminAddress, USER_VAI_BALANCE, @@ -448,7 +462,7 @@ describe("Peg Stability Module", () => { }); it("stable token < 1$ ", async () => { priceOracle.getPrice.returns(TOKEN_PRICE_BELOW_ONE); // 0.9$ - await swapVaiForStableAndVerify( + await swapVAIForStableAndVerify( vai, adminAddress, USER_VAI_BALANCE, @@ -466,7 +480,7 @@ describe("Peg Stability Module", () => { const USER_VAI_BALANCE = convertToUnit(121, 18); // 121 (110 VAI + 11 VAI fee) const VAI_FEE_TO_TREASURY = convertToUnit(11, 18); const VAI_TO_BURN = convertToUnit(110, 18); - await swapVaiForStableAndVerify( + await swapVAIForStableAndVerify( vai, adminAddress, USER_VAI_BALANCE, @@ -491,7 +505,7 @@ describe("Peg Stability Module", () => { }); }); it("stable token = 1$ ", async () => { - await swapVaiForStableAndVerify( + await swapVAIForStableAndVerify( vai, adminAddress, USER_VAI_BALANCE, @@ -506,7 +520,7 @@ describe("Peg Stability Module", () => { }); it("stable token < 1$ ", async () => { priceOracle.getPrice.returns(TOKEN_PRICE_BELOW_ONE); // 0.9$ - await swapVaiForStableAndVerify( + await swapVAIForStableAndVerify( vai, adminAddress, USER_VAI_BALANCE, @@ -524,7 +538,7 @@ describe("Peg Stability Module", () => { const USER_VAI_BALANCE = convertToUnit(121, 18); // 121 (110 VAI + 11 VAI fee) const VAI_FEE_TO_TREASURY = "0"; const VAI_TO_BURN = convertToUnit(110, 18); - await swapVaiForStableAndVerify( + await swapVAIForStableAndVerify( vai, adminAddress, USER_VAI_BALANCE, @@ -545,9 +559,9 @@ describe("Peg Stability Module", () => { resetAllFakes(); }); it("should revert if receiver is zero address ", async () => { - await expect(pegStability.swapStableForVAI(ethers.constants.AddressZero, 100)).to.be.revertedWith( - "Can't be zero address.", - ); + await expect( + pegStability.swapStableForVAI(ethers.constants.AddressZero, 100), + ).to.be.revertedWithCustomError(pegStability, "ZeroAddress"); }); it("should revert if VAI mint cap will be reached ", async () => { const MINT_CAP = convertToUnit(99, 18); @@ -557,9 +571,9 @@ describe("Peg Stability Module", () => { .whenCalledWith(adminAddress, pegStability.address, STABLE_TOKEN_AMOUNT) .returns(true); stableToken.balanceOf.returnsAtCall(1, STABLE_TOKEN_AMOUNT); - await expect(pegStability.swapStableForVAI(adminAddress, STABLE_TOKEN_AMOUNT)).to.be.revertedWith( - "VAI mint cap reached.", - ); + await expect( + pegStability.swapStableForVAI(adminAddress, STABLE_TOKEN_AMOUNT), + ).to.be.revertedWithCustomError(pegStability, "VAIMintCapReached"); }); if (decimals == 18) { it("should revert if amount after transfer is too small ", async function () { @@ -569,9 +583,9 @@ describe("Peg Stability Module", () => { .whenCalledWith(adminAddress, pegStability.address, STABLE_TOKEN_AMOUNT) .returns(true); stableToken.balanceOf.returnsAtCall(1, TOO_SMALL_AMOUNT); - await expect(pegStability.swapStableForVAI(adminAddress, STABLE_TOKEN_AMOUNT)).to.be.revertedWith( - "Amount too small.", - ); + await expect( + pegStability.swapStableForVAI(adminAddress, STABLE_TOKEN_AMOUNT), + ).to.be.revertedWithCustomError(pegStability, "AmountTooSmall"); }); } describe("should sucessfully perform the swap", () => { @@ -582,7 +596,7 @@ describe("Peg Stability Module", () => { const VAI_FEE = convertToUnit(10, 18); const VAI_TO_SEND = convertToUnit(90, 18); it("stable token = 1$ ", async () => { - await swapStableForVaiAndVerify( + await swapStableForVAIAndVerify( stableToken, adminAddress, pegStability, @@ -596,7 +610,7 @@ describe("Peg Stability Module", () => { }); it("stable token > 1$ ", async () => { priceOracle.getPrice.returns(TOKEN_PRICE_ABOVE_ONE); - await swapStableForVaiAndVerify( + await swapStableForVAIAndVerify( stableToken, adminAddress, pegStability, @@ -612,7 +626,7 @@ describe("Peg Stability Module", () => { priceOracle.getPrice.returns(TOKEN_PRICE_BELOW_ONE); const VAI_FEE = convertToUnit(9, 18); const VAI_TO_SEND = convertToUnit(81, 18); - await swapStableForVaiAndVerify( + await swapStableForVAIAndVerify( stableToken, adminAddress, pegStability, @@ -637,7 +651,7 @@ describe("Peg Stability Module", () => { vai.mint.reset(); }); it("stable token = 1$ ", async () => { - await swapStableForVaiAndVerify( + await swapStableForVAIAndVerify( stableToken, adminAddress, pegStability, @@ -651,7 +665,7 @@ describe("Peg Stability Module", () => { }); it("stable token > 1$ ", async () => { priceOracle.getPrice.returns(TOKEN_PRICE_ABOVE_ONE); - await swapStableForVaiAndVerify( + await swapStableForVAIAndVerify( stableToken, adminAddress, pegStability, @@ -666,7 +680,7 @@ describe("Peg Stability Module", () => { it("stable token < 1$ ", async () => { priceOracle.getPrice.returns(TOKEN_PRICE_BELOW_ONE); const VAI_TO_SEND = convertToUnit(90, 18); - await swapStableForVaiAndVerify( + await swapStableForVAIAndVerify( stableToken, adminAddress, pegStability,