From bf6d75d59916fbeba289524e8c8ed6602a7dc004 Mon Sep 17 00:00:00 2001 From: Josh Date: Fri, 4 Oct 2024 10:27:26 -0400 Subject: [PATCH] CI cleanup --- contracts/gas-snapshots/ccip.gas-snapshot | 27 ++ .../operatorforwarder.gas-snapshot | 18 +- .../ccip/test/legacy/TokenPoolAndProxy.t.sol | 76 +--- .../FactoryBurnMintERC20.t.sol | 360 ++++++++++++++++++ 4 files changed, 414 insertions(+), 67 deletions(-) create mode 100644 contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20.t.sol diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 38e3a72dfc..a361de5134 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -329,6 +329,33 @@ EtherSenderReceiverTest_validatedMessage:test_validatedMessage_emptyDataOverwrit EtherSenderReceiverTest_validatedMessage:test_validatedMessage_invalidTokenAmounts() (gas: 17925) EtherSenderReceiverTest_validatedMessage:test_validatedMessage_tokenOverwrittenToWeth() (gas: 25329) EtherSenderReceiverTest_validatedMessage:test_validatedMessage_validMessage_extraArgs() (gas: 26370) +FactoryBurnMintERC20approve:testApproveSuccess() (gas: 55767) +FactoryBurnMintERC20approve:testInvalidAddressReverts() (gas: 10709) +FactoryBurnMintERC20burn:testBasicBurnSuccess() (gas: 172380) +FactoryBurnMintERC20burn:testBurnFromZeroAddressReverts() (gas: 47384) +FactoryBurnMintERC20burn:testExceedsBalanceReverts() (gas: 21962) +FactoryBurnMintERC20burn:testSenderNotBurnerReverts() (gas: 13491) +FactoryBurnMintERC20burnFrom:testBurnFromSuccess() (gas: 58212) +FactoryBurnMintERC20burnFrom:testExceedsBalanceReverts() (gas: 36130) +FactoryBurnMintERC20burnFrom:testInsufficientAllowanceReverts() (gas: 22054) +FactoryBurnMintERC20burnFrom:testSenderNotBurnerReverts() (gas: 13491) +FactoryBurnMintERC20burnFromAlias:testBurnFromSuccess() (gas: 58187) +FactoryBurnMintERC20burnFromAlias:testExceedsBalanceReverts() (gas: 36094) +FactoryBurnMintERC20burnFromAlias:testInsufficientAllowanceReverts() (gas: 22009) +FactoryBurnMintERC20burnFromAlias:testSenderNotBurnerReverts() (gas: 13446) +FactoryBurnMintERC20constructor:testConstructorSuccess() (gas: 1495659) +FactoryBurnMintERC20decreaseApproval:testDecreaseApprovalSuccess() (gas: 31323) +FactoryBurnMintERC20grantMintAndBurnRoles:testGrantMintAndBurnRolesSuccess() (gas: 121439) +FactoryBurnMintERC20grantRole:testGrantBurnAccessSuccess() (gas: 53612) +FactoryBurnMintERC20grantRole:testGrantManySuccess() (gas: 963184) +FactoryBurnMintERC20grantRole:testGrantMintAccessSuccess() (gas: 94434) +FactoryBurnMintERC20increaseApproval:testIncreaseApprovalSuccess() (gas: 44368) +FactoryBurnMintERC20mint:testBasicMintSuccess() (gas: 149987) +FactoryBurnMintERC20mint:testMaxSupplyExceededReverts() (gas: 50703) +FactoryBurnMintERC20mint:testSenderNotMinterReverts() (gas: 11328) +FactoryBurnMintERC20supportsInterface:testConstructorSuccess() (gas: 11345) +FactoryBurnMintERC20transfer:testInvalidAddressReverts() (gas: 10707) +FactoryBurnMintERC20transfer:testTransferSuccess() (gas: 42427) FeeQuoter_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16686) FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16588) FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16630) diff --git a/contracts/gas-snapshots/operatorforwarder.gas-snapshot b/contracts/gas-snapshots/operatorforwarder.gas-snapshot index 0414f500c2..551fde38f3 100644 --- a/contracts/gas-snapshots/operatorforwarder.gas-snapshot +++ b/contracts/gas-snapshots/operatorforwarder.gas-snapshot @@ -2,14 +2,14 @@ FactoryTest:test_DeployNewForwarderAndTransferOwnership_Success() (gas: 1059722) FactoryTest:test_DeployNewForwarder_Success() (gas: 1048209) FactoryTest:test_DeployNewOperatorAndForwarder_Success() (gas: 4069305) FactoryTest:test_DeployNewOperator_Success() (gas: 3020464) -ForwarderTest:test_Forward_Success(uint256) (runs: 257, μ: 226979, ~: 227289) -ForwarderTest:test_MultiForward_Success(uint256,uint256) (runs: 257, μ: 258577, ~: 259120) -ForwarderTest:test_OwnerForward_Success() (gas: 30096) +ForwarderTest:test_Forward_Success(uint256) (runs: 256, μ: 226978, ~: 227289) +ForwarderTest:test_MultiForward_Success(uint256,uint256) (runs: 256, μ: 258575, ~: 259120) +ForwarderTest:test_OwnerForward_Success() (gas: 30118) ForwarderTest:test_SetAuthorizedSenders_Success() (gas: 160524) ForwarderTest:test_TransferOwnershipWithMessage_Success() (gas: 35123) -OperatorTest:test_CancelOracleRequest_Success() (gas: 274295) -OperatorTest:test_FulfillOracleRequest_Success() (gas: 330480) -OperatorTest:test_NotAuthorizedSender_Revert() (gas: 246628) -OperatorTest:test_OracleRequest_Success() (gas: 249843) -OperatorTest:test_SendRequestAndCancelRequest_Success(uint96) (runs: 257, μ: 386787, ~: 386790) -OperatorTest:test_SendRequest_Success(uint96) (runs: 257, μ: 303436, ~: 303439) \ No newline at end of file +OperatorTest:test_CancelOracleRequest_Success() (gas: 274436) +OperatorTest:test_FulfillOracleRequest_Success() (gas: 330603) +OperatorTest:test_NotAuthorizedSender_Revert() (gas: 246716) +OperatorTest:test_OracleRequest_Success() (gas: 250019) +OperatorTest:test_SendRequestAndCancelRequest_Success(uint96) (runs: 256, μ: 387121, ~: 387124) +OperatorTest:test_SendRequest_Success(uint96) (runs: 256, μ: 303612, ~: 303615) \ No newline at end of file diff --git a/contracts/src/v0.8/ccip/test/legacy/TokenPoolAndProxy.t.sol b/contracts/src/v0.8/ccip/test/legacy/TokenPoolAndProxy.t.sol index a721d37c64..9645d70b7a 100644 --- a/contracts/src/v0.8/ccip/test/legacy/TokenPoolAndProxy.t.sol +++ b/contracts/src/v0.8/ccip/test/legacy/TokenPoolAndProxy.t.sol @@ -361,12 +361,8 @@ contract TokenPoolAndProxy is EVM2EVMOnRampSetup { } function test_lockOrBurn_burnWithFromMint_Success() public { - s_pool = new BurnWithFromMintTokenPoolAndProxy( - s_token, - new address[](0), - address(s_mockRMN), - address(s_sourceRouter) - ); + s_pool = + new BurnWithFromMintTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), address(s_sourceRouter)); _configurePool(); _deployOldPool(); _assertLockOrBurnCorrect(); @@ -378,13 +374,8 @@ contract TokenPoolAndProxy is EVM2EVMOnRampSetup { } function test_lockOrBurn_lockRelease_Success() public { - s_pool = new LockReleaseTokenPoolAndProxy( - s_token, - new address[](0), - address(s_mockRMN), - false, - address(s_sourceRouter) - ); + s_pool = + new LockReleaseTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), false, address(s_sourceRouter)); _configurePool(); _deployOldPool(); _assertLockOrBurnCorrect(); @@ -400,17 +391,11 @@ contract TokenPoolAndProxy is EVM2EVMOnRampSetup { s_token.grantMintAndBurnRoles(address(s_legacyPool)); TokenPool1_2.RampUpdate[] memory onRampUpdates = new TokenPool1_2.RampUpdate[](1); - onRampUpdates[0] = TokenPool1_2.RampUpdate({ - ramp: address(s_pool), - allowed: true, - rateLimiterConfig: _getInboundRateLimiterConfig() - }); + onRampUpdates[0] = + TokenPool1_2.RampUpdate({ramp: address(s_pool), allowed: true, rateLimiterConfig: _getInboundRateLimiterConfig()}); TokenPool1_2.RampUpdate[] memory offRampUpdates = new TokenPool1_2.RampUpdate[](1); - offRampUpdates[0] = TokenPool1_2.RampUpdate({ - ramp: address(s_pool), - allowed: true, - rateLimiterConfig: _getInboundRateLimiterConfig() - }); + offRampUpdates[0] = + TokenPool1_2.RampUpdate({ramp: address(s_pool), allowed: true, rateLimiterConfig: _getInboundRateLimiterConfig()}); BurnMintTokenPool1_2(address(s_legacyPool)).applyRampUpdates(onRampUpdates, offRampUpdates); } @@ -521,13 +506,8 @@ contract TokenPoolAndProxy is EVM2EVMOnRampSetup { } function test_setPreviousPool_Success() public { - LockReleaseTokenPoolAndProxy pool = new LockReleaseTokenPoolAndProxy( - s_token, - new address[](0), - address(s_mockRMN), - true, - address(s_sourceRouter) - ); + LockReleaseTokenPoolAndProxy pool = + new LockReleaseTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), true, address(s_sourceRouter)); assertEq(pool.getPreviousPool(), address(0)); @@ -559,23 +539,13 @@ contract LockReleaseTokenPoolAndProxySetup is RouterSetup { RouterSetup.setUp(); s_token = new BurnMintERC677("LINK", "LNK", 18, 0); deal(address(s_token), OWNER, type(uint256).max); - s_lockReleaseTokenPoolAndProxy = new LockReleaseTokenPoolAndProxy( - s_token, - new address[](0), - address(s_mockRMN), - true, - address(s_sourceRouter) - ); + s_lockReleaseTokenPoolAndProxy = + new LockReleaseTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), true, address(s_sourceRouter)); s_allowedList.push(USER_1); s_allowedList.push(DUMMY_CONTRACT_ADDRESS); - s_lockReleaseTokenPoolAndProxyWithAllowList = new LockReleaseTokenPoolAndProxy( - s_token, - s_allowedList, - address(s_mockRMN), - true, - address(s_sourceRouter) - ); + s_lockReleaseTokenPoolAndProxyWithAllowList = + new LockReleaseTokenPoolAndProxy(s_token, s_allowedList, address(s_mockRMN), true, address(s_sourceRouter)); TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); chainUpdate[0] = TokenPool.ChainUpdate({ @@ -618,13 +588,8 @@ contract LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity is LockReleaseToken function test_CanAcceptLiquidity_Success() public { assertEq(true, s_lockReleaseTokenPoolAndProxy.canAcceptLiquidity()); - s_lockReleaseTokenPoolAndProxy = new LockReleaseTokenPoolAndProxy( - s_token, - new address[](0), - address(s_mockRMN), - false, - address(s_sourceRouter) - ); + s_lockReleaseTokenPoolAndProxy = + new LockReleaseTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), false, address(s_sourceRouter)); assertEq(false, s_lockReleaseTokenPoolAndProxy.canAcceptLiquidity()); } } @@ -656,13 +621,8 @@ contract LockReleaseTokenPoolPoolAndProxy_provideLiquidity is LockReleaseTokenPo } function test_LiquidityNotAccepted_Revert() public { - s_lockReleaseTokenPoolAndProxy = new LockReleaseTokenPoolAndProxy( - s_token, - new address[](0), - address(s_mockRMN), - false, - address(s_sourceRouter) - ); + s_lockReleaseTokenPoolAndProxy = + new LockReleaseTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), false, address(s_sourceRouter)); vm.expectRevert(LockReleaseTokenPoolAndProxy.LiquidityNotAccepted.selector); s_lockReleaseTokenPoolAndProxy.provideLiquidity(1); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20.t.sol new file mode 100644 index 0000000000..f64e4985f0 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20.t.sol @@ -0,0 +1,360 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {FactoryBurnMintERC20} from "../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; +import {BaseTest} from "../BaseTest.t.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; + +contract BurnMintERC20Setup is BaseTest { + event Transfer(address indexed from, address indexed to, uint256 value); + event MintAccessGranted(address indexed minter); + event BurnAccessGranted(address indexed burner); + event MintAccessRevoked(address indexed minter); + event BurnAccessRevoked(address indexed burner); + + FactoryBurnMintERC20 internal s_burnMintERC20; + + address internal s_mockPool = address(6243783892); + uint256 internal s_amount = 1e18; + + address internal s_alice; + + function setUp() public virtual override { + BaseTest.setUp(); + + s_alice = makeAddr("alice"); + + s_burnMintERC20 = new FactoryBurnMintERC20("Chainlink Token", "LINK", 18, 1e27, 0, s_alice); + + // Set s_mockPool to be a burner and minter + s_burnMintERC20.grantMintAndBurnRoles(s_mockPool); + deal(address(s_burnMintERC20), OWNER, s_amount); + } +} + +contract FactoryBurnMintERC20constructor is BurnMintERC20Setup { + function testConstructorSuccess() public { + string memory name = "Chainlink token v2"; + string memory symbol = "LINK2"; + uint8 decimals = 19; + uint256 maxSupply = 1e33; + + s_burnMintERC20 = new FactoryBurnMintERC20(name, symbol, decimals, maxSupply, 1e18, s_alice); + + assertEq(name, s_burnMintERC20.name()); + assertEq(symbol, s_burnMintERC20.symbol()); + assertEq(decimals, s_burnMintERC20.decimals()); + assertEq(maxSupply, s_burnMintERC20.maxSupply()); + + assertTrue(s_burnMintERC20.isMinter(s_alice)); + assertTrue(s_burnMintERC20.isBurner(s_alice)); + assertEq(s_burnMintERC20.balanceOf(s_alice), 1e18); + assertEq(s_burnMintERC20.totalSupply(), 1e18); + + } +} + +contract FactoryBurnMintERC20approve is BurnMintERC20Setup { + function testApproveSuccess() public { + uint256 balancePre = s_burnMintERC20.balanceOf(STRANGER); + uint256 sendingAmount = s_amount / 2; + + s_burnMintERC20.approve(STRANGER, sendingAmount); + + changePrank(STRANGER); + + s_burnMintERC20.transferFrom(OWNER, STRANGER, sendingAmount); + + assertEq(sendingAmount + balancePre, s_burnMintERC20.balanceOf(STRANGER)); + } + + // Reverts + + function testInvalidAddressReverts() public { + vm.expectRevert(); + + s_burnMintERC20.approve(address(s_burnMintERC20), s_amount); + } +} + +contract FactoryBurnMintERC20transfer is BurnMintERC20Setup { + function testTransferSuccess() public { + uint256 balancePre = s_burnMintERC20.balanceOf(STRANGER); + uint256 sendingAmount = s_amount / 2; + + s_burnMintERC20.transfer(STRANGER, sendingAmount); + + assertEq(sendingAmount + balancePre, s_burnMintERC20.balanceOf(STRANGER)); + } + + // Reverts + + function testInvalidAddressReverts() public { + vm.expectRevert(); + + s_burnMintERC20.transfer(address(s_burnMintERC20), s_amount); + } +} + +contract FactoryBurnMintERC20mint is BurnMintERC20Setup { + function testBasicMintSuccess() public { + uint256 balancePre = s_burnMintERC20.balanceOf(OWNER); + + s_burnMintERC20.grantMintAndBurnRoles(OWNER); + + vm.expectEmit(); + emit Transfer(address(0), OWNER, s_amount); + + s_burnMintERC20.mint(OWNER, s_amount); + + assertEq(balancePre + s_amount, s_burnMintERC20.balanceOf(OWNER)); + } + + // Revert + + function testSenderNotMinterReverts() public { + vm.expectRevert(abi.encodeWithSelector(FactoryBurnMintERC20.SenderNotMinter.selector, OWNER)); + s_burnMintERC20.mint(STRANGER, 1e18); + } + + function testMaxSupplyExceededReverts() public { + changePrank(s_mockPool); + + // Mint max supply + s_burnMintERC20.mint(OWNER, s_burnMintERC20.maxSupply()); + + vm.expectRevert(abi.encodeWithSelector(FactoryBurnMintERC20.MaxSupplyExceeded.selector, s_burnMintERC20.maxSupply() + 1)); + + // Attempt to mint 1 more than max supply + s_burnMintERC20.mint(OWNER, 1); + } +} + +contract FactoryBurnMintERC20burn is BurnMintERC20Setup { + function testBasicBurnSuccess() public { + s_burnMintERC20.grantBurnRole(OWNER); + deal(address(s_burnMintERC20), OWNER, s_amount); + + vm.expectEmit(); + emit Transfer(OWNER, address(0), s_amount); + + s_burnMintERC20.burn(s_amount); + + assertEq(0, s_burnMintERC20.balanceOf(OWNER)); + } + + // Revert + + function testSenderNotBurnerReverts() public { + vm.expectRevert(abi.encodeWithSelector(FactoryBurnMintERC20.SenderNotBurner.selector, OWNER)); + + s_burnMintERC20.burnFrom(STRANGER, s_amount); + } + + function testExceedsBalanceReverts() public { + changePrank(s_mockPool); + + vm.expectRevert("ERC20: burn amount exceeds balance"); + + s_burnMintERC20.burn(s_amount * 2); + } + + function testBurnFromZeroAddressReverts() public { + s_burnMintERC20.grantBurnRole(address(0)); + changePrank(address(0)); + + vm.expectRevert("ERC20: burn from the zero address"); + + s_burnMintERC20.burn(0); + } +} + +contract FactoryBurnMintERC20burnFromAlias is BurnMintERC20Setup { + function setUp() public virtual override { + BurnMintERC20Setup.setUp(); + } + + function testBurnFromSuccess() public { + s_burnMintERC20.approve(s_mockPool, s_amount); + + changePrank(s_mockPool); + + s_burnMintERC20.burn(OWNER, s_amount); + + assertEq(0, s_burnMintERC20.balanceOf(OWNER)); + } + + // Reverts + + function testSenderNotBurnerReverts() public { + vm.expectRevert(abi.encodeWithSelector(FactoryBurnMintERC20.SenderNotBurner.selector, OWNER)); + + s_burnMintERC20.burn(OWNER, s_amount); + } + + function testInsufficientAllowanceReverts() public { + changePrank(s_mockPool); + + vm.expectRevert("ERC20: insufficient allowance"); + + s_burnMintERC20.burn(OWNER, s_amount); + } + + function testExceedsBalanceReverts() public { + s_burnMintERC20.approve(s_mockPool, s_amount * 2); + + changePrank(s_mockPool); + + vm.expectRevert("ERC20: burn amount exceeds balance"); + + s_burnMintERC20.burn(OWNER, s_amount * 2); + } +} + +contract FactoryBurnMintERC20burnFrom is BurnMintERC20Setup { + function setUp() public virtual override { + BurnMintERC20Setup.setUp(); + } + + function testBurnFromSuccess() public { + s_burnMintERC20.approve(s_mockPool, s_amount); + + changePrank(s_mockPool); + + s_burnMintERC20.burnFrom(OWNER, s_amount); + + assertEq(0, s_burnMintERC20.balanceOf(OWNER)); + } + + // Reverts + + function testSenderNotBurnerReverts() public { + vm.expectRevert(abi.encodeWithSelector(FactoryBurnMintERC20.SenderNotBurner.selector, OWNER)); + + s_burnMintERC20.burnFrom(OWNER, s_amount); + } + + function testInsufficientAllowanceReverts() public { + changePrank(s_mockPool); + + vm.expectRevert("ERC20: insufficient allowance"); + + s_burnMintERC20.burnFrom(OWNER, s_amount); + } + + function testExceedsBalanceReverts() public { + s_burnMintERC20.approve(s_mockPool, s_amount * 2); + + changePrank(s_mockPool); + + vm.expectRevert("ERC20: burn amount exceeds balance"); + + s_burnMintERC20.burnFrom(OWNER, s_amount * 2); + } +} + +contract FactoryBurnMintERC20grantRole is BurnMintERC20Setup { + function testGrantMintAccessSuccess() public { + assertFalse(s_burnMintERC20.isMinter(STRANGER)); + + vm.expectEmit(); + emit MintAccessGranted(STRANGER); + + s_burnMintERC20.grantMintAndBurnRoles(STRANGER); + + assertTrue(s_burnMintERC20.isMinter(STRANGER)); + + vm.expectEmit(); + emit MintAccessRevoked(STRANGER); + + s_burnMintERC20.revokeMintRole(STRANGER); + + assertFalse(s_burnMintERC20.isMinter(STRANGER)); + } + + function testGrantBurnAccessSuccess() public { + assertFalse(s_burnMintERC20.isBurner(STRANGER)); + + vm.expectEmit(); + emit BurnAccessGranted(STRANGER); + + s_burnMintERC20.grantBurnRole(STRANGER); + + assertTrue(s_burnMintERC20.isBurner(STRANGER)); + + vm.expectEmit(); + emit BurnAccessRevoked(STRANGER); + + s_burnMintERC20.revokeBurnRole(STRANGER); + + assertFalse(s_burnMintERC20.isBurner(STRANGER)); + } + + function testGrantManySuccess() public { + // Since alice was already granted mint and burn roles in the setup, we will revoke them + // and then grant them again for the purposes of the test + s_burnMintERC20.revokeMintRole(s_alice); + s_burnMintERC20.revokeBurnRole(s_alice); + + uint256 numberOfPools = 10; + address[] memory permissionedAddresses = new address[](numberOfPools + 1); + permissionedAddresses[0] = s_mockPool; + + for (uint160 i = 0; i < numberOfPools; ++i) { + permissionedAddresses[i + 1] = address(i); + s_burnMintERC20.grantMintAndBurnRoles(address(i)); + } + + assertEq(permissionedAddresses, s_burnMintERC20.getBurners()); + assertEq(permissionedAddresses, s_burnMintERC20.getMinters()); + } +} + +contract FactoryBurnMintERC20grantMintAndBurnRoles is BurnMintERC20Setup { + function testGrantMintAndBurnRolesSuccess() public { + assertFalse(s_burnMintERC20.isMinter(STRANGER)); + assertFalse(s_burnMintERC20.isBurner(STRANGER)); + + vm.expectEmit(); + emit MintAccessGranted(STRANGER); + vm.expectEmit(); + emit BurnAccessGranted(STRANGER); + + s_burnMintERC20.grantMintAndBurnRoles(STRANGER); + + assertTrue(s_burnMintERC20.isMinter(STRANGER)); + assertTrue(s_burnMintERC20.isBurner(STRANGER)); + } +} + +contract FactoryBurnMintERC20decreaseApproval is BurnMintERC20Setup { + function testDecreaseApprovalSuccess() public { + s_burnMintERC20.approve(s_mockPool, s_amount); + uint256 allowance = s_burnMintERC20.allowance(OWNER, s_mockPool); + assertEq(allowance, s_amount); + s_burnMintERC20.decreaseApproval(s_mockPool, s_amount); + assertEq(s_burnMintERC20.allowance(OWNER, s_mockPool), allowance - s_amount); + } +} + +contract FactoryBurnMintERC20increaseApproval is BurnMintERC20Setup { + function testIncreaseApprovalSuccess() public { + s_burnMintERC20.approve(s_mockPool, s_amount); + uint256 allowance = s_burnMintERC20.allowance(OWNER, s_mockPool); + assertEq(allowance, s_amount); + s_burnMintERC20.increaseApproval(s_mockPool, s_amount); + assertEq(s_burnMintERC20.allowance(OWNER, s_mockPool), allowance + s_amount); + } +} + +contract FactoryBurnMintERC20supportsInterface is BurnMintERC20Setup { + function testConstructorSuccess() public view { + assertTrue(s_burnMintERC20.supportsInterface(type(IERC20).interfaceId)); + assertTrue(s_burnMintERC20.supportsInterface(type(IBurnMintERC20).interfaceId)); + assertTrue(s_burnMintERC20.supportsInterface(type(IERC165).interfaceId)); + } +}