From d912448b3e293ea3dd00a453fc753862c7902cc5 Mon Sep 17 00:00:00 2001 From: iethena Date: Mon, 25 Nov 2024 15:48:46 +0000 Subject: [PATCH] token rename --- README.md | 20 +- .../{ustb/IUStb.sol => usdtb/IUSDtb.sol} | 2 +- .../IUSDtbDefinitions.sol} | 2 +- .../IUSDtbMinting.sol} | 18 +- .../IUSDtbMintingEvents.sol} | 12 +- contracts/{ustb/UStb.sol => usdtb/USDtb.sol} | 24 +- .../USDtbMinting.sol} | 110 +- test/foundry/USDtb.admin.t.sol | 180 ++ test/foundry/USDtb.transfers.t.sol | 1517 +++++++++++++++++ .../{UStbBaseSetup.sol => USDtbBaseSetup.sol} | 60 +- test/foundry/USDtbMinting.utils.sol | 61 + ...aseSetup.sol => USDtbMintingBaseSetup.sol} | 262 +-- test/foundry/UStb.admin.t.sol | 180 -- test/foundry/UStb.transfers.t.sol | 1517 ----------------- test/foundry/UStbMinting.utils.sol | 61 - ...nting.ACL.t.sol => USDtbMinting.ACL.t.sol} | 352 ++-- test/foundry/test/USDtbMinting.Delegate.t.sol | 243 +++ ...> USDtbMinting.SmartContractSigning.t.sol} | 48 +- .../test/USDtbMinting.StableRatios.t.sol | 209 +++ .../foundry/test/USDtbMinting.Whitelist.t.sol | 317 ++++ ...s.t.sol => USDtbMinting.blockLimits.t.sol} | 90 +- ...ing.core.t.sol => USDtbMinting.core.t.sol} | 242 +-- test/foundry/test/UStbMinting.Delegate.t.sol | 243 --- .../test/UStbMinting.StableRatios.t.sol | 209 --- test/foundry/test/UStbMinting.Whitelist.t.sol | 317 ---- 25 files changed, 3148 insertions(+), 3148 deletions(-) rename contracts/{ustb/IUStb.sol => usdtb/IUSDtb.sol} (86%) rename contracts/{ustb/IUStbDefinitions.sol => usdtb/IUSDtbDefinitions.sol} (97%) rename contracts/{ustb/IUStbMinting.sol => usdtb/IUSDtbMinting.sol} (85%) rename contracts/{ustb/IUStbMintingEvents.sol => usdtb/IUSDtbMintingEvents.sol} (93%) rename contracts/{ustb/UStb.sol => usdtb/USDtb.sol} (94%) rename contracts/{ustb/UStbMinting.sol => usdtb/USDtbMinting.sol} (87%) create mode 100644 test/foundry/USDtb.admin.t.sol create mode 100644 test/foundry/USDtb.transfers.t.sol rename test/foundry/{UStbBaseSetup.sol => USDtbBaseSetup.sol} (67%) create mode 100644 test/foundry/USDtbMinting.utils.sol rename test/foundry/{UStbMintingBaseSetup.sol => USDtbMintingBaseSetup.sol} (62%) delete mode 100644 test/foundry/UStb.admin.t.sol delete mode 100644 test/foundry/UStb.transfers.t.sol delete mode 100644 test/foundry/UStbMinting.utils.sol rename test/foundry/test/{UStbMinting.ACL.t.sol => USDtbMinting.ACL.t.sol} (55%) create mode 100644 test/foundry/test/USDtbMinting.Delegate.t.sol rename test/foundry/test/{UStbMinting.SmartContractSigning.t.sol => USDtbMinting.SmartContractSigning.t.sol} (58%) create mode 100644 test/foundry/test/USDtbMinting.StableRatios.t.sol create mode 100644 test/foundry/test/USDtbMinting.Whitelist.t.sol rename test/foundry/test/{UStbMinting.blockLimits.t.sol => USDtbMinting.blockLimits.t.sol} (61%) rename test/foundry/test/{UStbMinting.core.t.sol => USDtbMinting.core.t.sol} (50%) delete mode 100644 test/foundry/test/UStbMinting.Delegate.t.sol delete mode 100644 test/foundry/test/UStbMinting.StableRatios.t.sol delete mode 100644 test/foundry/test/UStbMinting.Whitelist.t.sol diff --git a/README.md b/README.md index fad62c7..7894530 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ -# UStb token and minting +# USDtb token and minting Contracts in scope: 1) `contracts/SingleAdminAccessControl.sol` 2) `contracts/SingleAdminAccessControlUpgradeable.sol` -3) `contracts/ustb/UStb.sol` -4) `contracts/ustb/UStbMinting.sol` +3) `contracts/usdtb/USDtb.sol` +4) `contracts/usdtb/USDtbMinting.sol` -## UStb token features +## USDtb token features **Overview**: An upgradeable ERC20 with mint and burn functionality and various transfer states that is controlled by a single admin address. @@ -31,17 +31,17 @@ The admin address can change the state at any time, without a timelock. There ar - `WHITELIST_ENABLED`: Only whitelisted addresses can send and receive this token. - `FULLY_ENABLED`: Only non-blacklisted addresses can send and receive this token. -## UStb minting features +## USDtb minting features -**Overview**: A contract defining the operations to mint and redeem UStb tokens based on signed orders that is controlled by a single admin. The price present in any mint/redeem orders are determined by an off-chain RFQ system controlled by Ethena, which a benefactor may accept and sign an order for. The minter/redeemer then has last look rights to be able to filter out any malicious orders and proceed with on-chain settlement. +**Overview**: A contract defining the operations to mint and redeem USDtb tokens based on signed orders that is controlled by a single admin. The price present in any mint/redeem orders are determined by an off-chain RFQ system controlled by Ethena, which a benefactor may accept and sign an order for. The minter/redeemer then has last look rights to be able to filter out any malicious orders and proceed with on-chain settlement. #### 1. Max mint/redeem per block by collateral -Implements the max amount of UStb that can be minted/redeemed in a single block using a certain type of collateral. The limit can be adjusted by the admin on a per collateral basis, regardless whether the collateral is active or not. +Implements the max amount of USDtb that can be minted/redeemed in a single block using a certain type of collateral. The limit can be adjusted by the admin on a per collateral basis, regardless whether the collateral is active or not. #### 2. Global max mint/redeem per block -In addition to mint/redeem limits by collateral, there is a global mint/redeem per block configuration that caps the amount of UStb that can be minted in a single block, regardless of the collateral used to mint UStb. The admin can adjust this configurations, regardless whether the collateral is active or not. +In addition to mint/redeem limits by collateral, there is a global mint/redeem per block configuration that caps the amount of USDtb that can be minted in a single block, regardless of the collateral used to mint USDtb. The admin can adjust this configurations, regardless whether the collateral is active or not. #### 3. Delegate signer @@ -53,11 +53,11 @@ Custodians are the only addresses that can receive collateral assets from the mi #### 5. Benefactor -An address holding collateral assets (benefactor) for a minting instruction that can receive UStb from the minting process. Benefactors are entities that have undergone KYC with Ethena and have been expressly registered by the admin to be able to participate in mint/redeem operations. +An address holding collateral assets (benefactor) for a minting instruction that can receive USDtb from the minting process. Benefactors are entities that have undergone KYC with Ethena and have been expressly registered by the admin to be able to participate in mint/redeem operations. #### 6. Beneficiary -An address holding collateral assets (benefactor) for a minting instruction can assign a different address (beneficiary) to receive UStb. +An address holding collateral assets (benefactor) for a minting instruction can assign a different address (beneficiary) to receive USDtb. #### 6. TokenType diff --git a/contracts/ustb/IUStb.sol b/contracts/usdtb/IUSDtb.sol similarity index 86% rename from contracts/ustb/IUStb.sol rename to contracts/usdtb/IUSDtb.sol index a26c009..ad3e055 100644 --- a/contracts/ustb/IUStb.sol +++ b/contracts/usdtb/IUSDtb.sol @@ -5,7 +5,7 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol"; -interface IUStb is IERC20, IERC20Permit, IERC20Metadata { +interface IUSDtb is IERC20, IERC20Permit, IERC20Metadata { function mint(address _to, uint256 _amount) external; function burnFrom(address account, uint256 amount) external; diff --git a/contracts/ustb/IUStbDefinitions.sol b/contracts/usdtb/IUSDtbDefinitions.sol similarity index 97% rename from contracts/ustb/IUStbDefinitions.sol rename to contracts/usdtb/IUSDtbDefinitions.sol index 1bcff77..493846e 100644 --- a/contracts/ustb/IUStbDefinitions.sol +++ b/contracts/usdtb/IUSDtbDefinitions.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.26; -interface IUStbDefinitions { +interface IUSDtbDefinitions { enum TransferState { FULLY_DISABLED, WHITELIST_ENABLED, diff --git a/contracts/ustb/IUStbMinting.sol b/contracts/usdtb/IUSDtbMinting.sol similarity index 85% rename from contracts/ustb/IUStbMinting.sol rename to contracts/usdtb/IUSDtbMinting.sol index 06ebf75..6730396 100644 --- a/contracts/ustb/IUStbMinting.sol +++ b/contracts/usdtb/IUSDtbMinting.sol @@ -3,9 +3,9 @@ pragma solidity 0.8.26; /* solhint-disable var-name-mixedcase */ -import "./IUStbMintingEvents.sol"; +import "./IUSDtbMintingEvents.sol"; -interface IUStbMinting is IUStbMintingEvents { +interface IUSDtbMinting is IUSDtbMintingEvents { enum Role { Minter, Redeemer @@ -51,7 +51,7 @@ interface IUStbMinting is IUStbMintingEvents { address beneficiary; address collateral_asset; uint128 collateral_amount; - uint128 ustb_amount; + uint128 usdtb_amount; } struct TokenConfig { @@ -66,21 +66,21 @@ interface IUStbMinting is IUStbMintingEvents { } struct BlockTotals { - /// @notice UStb minted per block / per asset per block + /// @notice USDtb minted per block / per asset per block uint128 mintedPerBlock; - /// @notice UStb redeemed per block / per asset per block + /// @notice USDtb redeemed per block / per asset per block uint128 redeemedPerBlock; } struct GlobalConfig { - /// @notice max UStb that can be minted across all assets within a single block. + /// @notice max USDtb that can be minted across all assets within a single block. uint128 globalMaxMintPerBlock; - /// @notice max UStb that can be redeemed across all assets within a single block. + /// @notice max USDtb that can be redeemed across all assets within a single block. uint128 globalMaxRedeemPerBlock; } error InvalidAddress(); - error InvalidUStbAddress(); + error InvalidUSDtbAddress(); error InvalidZeroAddress(); error InvalidAssetAddress(); error InvalidBenefactorAddress(); @@ -116,7 +116,7 @@ interface IUStbMinting is IUStbMintingEvents { function verifyStablesLimit( uint128 collateralAmount, - uint128 ustbAmount, + uint128 usdtbAmount, address collateralAsset, OrderType orderType ) external view returns (bool); diff --git a/contracts/ustb/IUStbMintingEvents.sol b/contracts/usdtb/IUSDtbMintingEvents.sol similarity index 93% rename from contracts/ustb/IUStbMintingEvents.sol rename to contracts/usdtb/IUSDtbMintingEvents.sol index 7014827..709f56c 100644 --- a/contracts/ustb/IUStbMintingEvents.sol +++ b/contracts/usdtb/IUSDtbMintingEvents.sol @@ -3,11 +3,11 @@ pragma solidity 0.8.26; /* solhint-disable var-name-mixedcase */ -interface IUStbMintingEvents { +interface IUSDtbMintingEvents { /// @notice Event emitted when contract receives ETH event Received(address, uint256); - /// @notice Event emitted when UStb is minted + /// @notice Event emitted when USDtb is minted event Mint( string indexed order_id, address indexed benefactor, @@ -15,7 +15,7 @@ interface IUStbMintingEvents { address minter, address collateral_asset, uint256 collateral_amount, - uint256 ustb_amount + uint256 usdtb_amount ); /// @notice Event emitted when funds are redeemed @@ -26,7 +26,7 @@ interface IUStbMintingEvents { address redeemer, address collateral_asset, uint256 collateral_amount, - uint256 ustb_amount + uint256 usdtb_amount ); /// @notice Event emitted when a supported asset is added @@ -56,8 +56,8 @@ interface IUStbMintingEvents { /// @notice Event emitted when assets are moved to custody provider wallet event CustodyTransfer(address indexed wallet, address indexed asset, uint256 amount); - /// @notice Event emitted when UStb is set - event UStbSet(address indexed UStb); + /// @notice Event emitted when USDtb is set + event USDtbSet(address indexed USDtb); /// @notice Event emitted when the max mint per block is changed event MaxMintPerBlockChanged(uint256 oldMaxMintPerBlock, uint256 newMaxMintPerBlock, address indexed asset); diff --git a/contracts/ustb/UStb.sol b/contracts/usdtb/USDtb.sol similarity index 94% rename from contracts/ustb/UStb.sol rename to contracts/usdtb/USDtb.sol index 37690fa..f20b623 100644 --- a/contracts/ustb/UStb.sol +++ b/contracts/usdtb/USDtb.sol @@ -6,22 +6,22 @@ import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20Burnable import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import "../SingleAdminAccessControlUpgradeable.sol"; -import "./IUStbDefinitions.sol"; +import "./IUSDtbDefinitions.sol"; /** - * @title UStb - * @notice UStb rwa token contract + * @title USDtb + * @notice USDtb rwa token contract */ -contract UStb is +contract USDtb is ERC20BurnableUpgradeable, ERC20PermitUpgradeable, - IUStbDefinitions, + IUSDtbDefinitions, ReentrancyGuardUpgradeable, SingleAdminAccessControlUpgradeable { using SafeERC20Upgradeable for IERC20Upgradeable; - /// @notice The role is allowed to mint UStb. To be pointed to UStb minting contract only. + /// @notice The role is allowed to mint USDtb. To be pointed to USDtb minting contract only. bytes32 public constant MINTER_CONTRACT = keccak256("MINTER_CONTRACT"); /// @notice Role that can handle Blacklisting, in addition to admin role. bytes32 public constant BLACKLIST_MANAGER_ROLE = keccak256("BLACKLIST_MANAGER_ROLE"); @@ -41,13 +41,13 @@ contract UStb is /* ------------- INITIALIZE ------------- */ /** - * @notice Initializer for UStb contract. + * @notice Initializer for USDtb contract. * @param admin The address of the admin role. - * @param minterContract The initial minterContract. Only this address can mint UStb + * @param minterContract The initial minterContract. Only this address can mint USDtb */ function initialize(address admin, address minterContract) public initializer { - __ERC20_init("UStb", "UStb"); - __ERC20Permit_init("UStb"); + __ERC20_init("USDtb", "USDtb"); + __ERC20Permit_init("USDtb"); __ReentrancyGuard_init(); if (admin == address(0) || minterContract == address(0)) revert ZeroAddressException(); transferState = TransferState.FULLY_ENABLED; @@ -105,7 +105,7 @@ contract UStb is } /** - * @dev Burns the blacklisted user UStb and mints to the desired owner address. + * @dev Burns the blacklisted user USDtb and mints to the desired owner address. * @param from The address to burn the entire balance, with the BLACKLISTED_ROLE * @param to The address to mint the entire balance of "from" parameter. */ @@ -132,7 +132,7 @@ contract UStb is } /** - * @notice Mints new UStb tokens + * @notice Mints new USDtb tokens * @param to The address to mint tokens to * @param amount The amount of tokens to mint * @dev Only callable by MINTER_CONTRACT role diff --git a/contracts/ustb/UStbMinting.sol b/contracts/usdtb/USDtbMinting.sol similarity index 87% rename from contracts/ustb/UStbMinting.sol rename to contracts/usdtb/USDtbMinting.sol index ed00d4e..1848761 100644 --- a/contracts/ustb/UStbMinting.sol +++ b/contracts/usdtb/USDtbMinting.sol @@ -10,15 +10,15 @@ import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "@openzeppelin/contracts/interfaces/IERC1271.sol"; -import "./IUStbMinting.sol"; -import "./IUStb.sol"; +import "./IUSDtbMinting.sol"; +import "./IUSDtb.sol"; import "../SingleAdminAccessControl.sol"; /** - * @title UStb Minting - * @notice This contract mints and redeems UStb, the RWA stablecoin backed by tokenized treasuries + * @title USDtb Minting + * @notice This contract mints and redeems USDtb, the RWA stablecoin backed by tokenized treasuries */ -contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard { +contract USDtbMinting is IUSDtbMinting, SingleAdminAccessControl, ReentrancyGuard { using SafeERC20 for IERC20; using EnumerableSet for EnumerableSet.AddressSet; @@ -30,7 +30,7 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard /// @notice order type bytes32 private constant ORDER_TYPE = keccak256( - "Order(string order_id,uint8 order_type,uint120 expiry,uint128 nonce,address benefactor,address beneficiary,address collateral_asset,uint128 collateral_amount,uint128 ustb_amount)" + "Order(string order_id,uint8 order_type,uint120 expiry,uint128 nonce,address benefactor,address beneficiary,address collateral_asset,uint128 collateral_amount,uint128 usdtb_amount)" ); /// @notice role enabling to invoke mint @@ -52,7 +52,7 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard address private constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; /// @notice EIP712 name - bytes32 private constant EIP_712_NAME = keccak256("UStbMinting"); + bytes32 private constant EIP_712_NAME = keccak256("USDtbMinting"); /// @notice holds EIP712 revision bytes32 private constant EIP712_REVISION = keccak256("1"); @@ -65,8 +65,8 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard /* --------------- STATE VARIABLES --------------- */ - /// @notice UStb stablecoin - IUStb public ustb; + /// @notice USDtb stablecoin + IUSDtb public usdtb; // @notice whitelisted benefactors EnumerableSet.AddressSet private _whitelistedBenefactors; @@ -95,10 +95,10 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard /// @notice global single block totals GlobalConfig public globalConfig; - /// @notice running total UStb minted/redeemed per single block + /// @notice running total USDtb minted/redeemed per single block mapping(uint256 => BlockTotals) public totalPerBlock; - /// @notice total UStb that can be minted/redeemed across all assets per single block. + /// @notice total USDtb that can be minted/redeemed across all assets per single block. mapping(uint256 => mapping(address => BlockTotals)) public totalPerBlockPerAsset; /// @notice configurations per token asset @@ -106,8 +106,8 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard /* --------------- MODIFIERS --------------- */ - /// @notice ensure that the already minted UStb in the actual block plus the amount to be minted is below the maximum mint amount - /// @param mintAmount The UStb amount to be minted + /// @notice ensure that the already minted USDtb in the actual block plus the amount to be minted is below the maximum mint amount + /// @param mintAmount The USDtb amount to be minted /// @param asset The asset to be minted modifier belowMaxMintPerBlock(uint128 mintAmount, address asset) { TokenConfig memory _config = tokenConfig[asset]; @@ -118,8 +118,8 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard _; } - /// @notice ensure that the already redeemed UStb in the actual block plus the amount to be redeemed is below the maximum redeem amount - /// @param redeemAmount The UStb amount to be redeemed + /// @notice ensure that the already redeemed USDtb in the actual block plus the amount to be redeemed is below the maximum redeem amount + /// @param redeemAmount The USDtb amount to be redeemed /// @param asset The asset to be redeemed modifier belowMaxRedeemPerBlock(uint128 redeemAmount, address asset) { TokenConfig memory _config = tokenConfig[asset]; @@ -130,18 +130,18 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard _; } - /// @notice ensure that the global, overall minted UStb in the actual block + /// @notice ensure that the global, overall minted USDtb in the actual block /// @notice plus the amount to be minted is below globalMaxMintPerBlock - /// @param mintAmount The UStb amount to be minted + /// @param mintAmount The USDtb amount to be minted modifier belowGlobalMaxMintPerBlock(uint128 mintAmount) { uint128 totalMintedThisBlock = totalPerBlock[uint128(block.number)].mintedPerBlock; if (totalMintedThisBlock + mintAmount > globalConfig.globalMaxMintPerBlock) revert GlobalMaxMintPerBlockExceeded(); _; } - /// @notice ensure that the global, overall redeemed UStb in the actual block + /// @notice ensure that the global, overall redeemed USDtb in the actual block /// @notice plus the amount to be redeemed is below globalMaxRedeemPerBlock - /// @param redeemAmount The UStb amount to be redeemed + /// @param redeemAmount The USDtb amount to be redeemed modifier belowGlobalMaxRedeemPerBlock(uint128 redeemAmount) { uint128 totalRedeemedThisBlock = totalPerBlock[block.number].redeemedPerBlock; if (totalRedeemedThisBlock + redeemAmount > globalConfig.globalMaxRedeemPerBlock) { @@ -177,7 +177,7 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard } } - // Set the global max UStb mint/redeem limits + // Set the global max USDtb mint/redeem limits globalConfig = _globalConfig; // Set the max mint/redeem limits per block for each asset @@ -218,20 +218,20 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard override nonReentrant onlyRole(MINTER_ROLE) - belowMaxMintPerBlock(order.ustb_amount, order.collateral_asset) - belowGlobalMaxMintPerBlock(order.ustb_amount) + belowMaxMintPerBlock(order.usdtb_amount, order.collateral_asset) + belowGlobalMaxMintPerBlock(order.usdtb_amount) { if (order.order_type != OrderType.MINT) revert InvalidOrder(); verifyOrder(order, signature); if (!verifyRoute(route)) revert InvalidRoute(); _deduplicateOrder(order.benefactor, order.nonce); // Add to the minted amount in this block - totalPerBlockPerAsset[block.number][order.collateral_asset].mintedPerBlock += order.ustb_amount; - totalPerBlock[block.number].mintedPerBlock += order.ustb_amount; + totalPerBlockPerAsset[block.number][order.collateral_asset].mintedPerBlock += order.usdtb_amount; + totalPerBlock[block.number].mintedPerBlock += order.usdtb_amount; _transferCollateral( order.collateral_amount, order.collateral_asset, order.benefactor, route.addresses, route.ratios ); - ustb.mint(order.beneficiary, order.ustb_amount); + usdtb.mint(order.beneficiary, order.usdtb_amount); emit Mint( order.order_id, order.benefactor, @@ -239,7 +239,7 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard msg.sender, order.collateral_asset, order.collateral_amount, - order.ustb_amount + order.usdtb_amount ); } @@ -253,16 +253,16 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard override nonReentrant onlyRole(REDEEMER_ROLE) - belowMaxRedeemPerBlock(order.ustb_amount, order.collateral_asset) - belowGlobalMaxRedeemPerBlock(order.ustb_amount) + belowMaxRedeemPerBlock(order.usdtb_amount, order.collateral_asset) + belowGlobalMaxRedeemPerBlock(order.usdtb_amount) { if (order.order_type != OrderType.REDEEM) revert InvalidOrder(); verifyOrder(order, signature); _deduplicateOrder(order.benefactor, order.nonce); // Add to the redeemed amount in this block - totalPerBlockPerAsset[block.number][order.collateral_asset].redeemedPerBlock += order.ustb_amount; - totalPerBlock[block.number].redeemedPerBlock += order.ustb_amount; - ustb.burnFrom(order.benefactor, order.ustb_amount); + totalPerBlockPerAsset[block.number][order.collateral_asset].redeemedPerBlock += order.usdtb_amount; + totalPerBlock[block.number].redeemedPerBlock += order.usdtb_amount; + usdtb.burnFrom(order.benefactor, order.usdtb_amount); _transferToBeneficiary(order.beneficiary, order.collateral_asset, order.collateral_amount); emit Redeem( order.order_id, @@ -271,17 +271,17 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard msg.sender, order.collateral_asset, order.collateral_amount, - order.ustb_amount + order.usdtb_amount ); } - /// @notice Sets the overall, global maximum UStb mint size per block + /// @notice Sets the overall, global maximum USDtb mint size per block function setGlobalMaxMintPerBlock(uint128 _globalMaxMintPerBlock) external onlyRole(DEFAULT_ADMIN_ROLE) { globalConfig.globalMaxMintPerBlock = _globalMaxMintPerBlock; emit GlobalMaxMintPerBlock(msg.sender, _globalMaxMintPerBlock); } - /// @notice Sets the overall, global maximum UStb redeem size per block + /// @notice Sets the overall, global maximum USDtb redeem size per block function setGlobalMaxRedeemPerBlock(uint128 _globalMaxRedeemPerBlock) external onlyRole(DEFAULT_ADMIN_ROLE) { globalConfig.globalMaxRedeemPerBlock = _globalMaxRedeemPerBlock; emit GlobalMaxRedeemPerBlock(msg.sender, _globalMaxRedeemPerBlock); @@ -377,7 +377,7 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard /// @notice Adds an custodian to the supported custodians list. function addCustodianAddress(address custodian) public onlyRole(DEFAULT_ADMIN_ROLE) { - if (custodian == address(0) || custodian == address(ustb) || !_custodianAddresses.add(custodian)) { + if (custodian == address(0) || custodian == address(usdtb) || !_custodianAddresses.add(custodian)) { revert InvalidCustodianAddress(); } emit CustodianAddressAdded(custodian); @@ -437,7 +437,7 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard order.beneficiary, order.collateral_asset, order.collateral_amount, - order.ustb_amount + order.usdtb_amount ); } @@ -474,12 +474,12 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard } TokenType typeOfToken = tokenConfig[order.collateral_asset].tokenType; if (typeOfToken == TokenType.STABLE) { - if (!verifyStablesLimit(order.collateral_amount, order.ustb_amount, order.collateral_asset, order.order_type)) { + if (!verifyStablesLimit(order.collateral_amount, order.usdtb_amount, order.collateral_asset, order.order_type)) { revert InvalidStablePrice(); } } if (order.beneficiary == address(0)) revert InvalidAddress(); - if (order.collateral_amount == 0 || order.ustb_amount == 0) revert InvalidAmount(); + if (order.collateral_amount == 0 || order.usdtb_amount == 0) revert InvalidAmount(); if (block.timestamp > order.expiry) revert SignatureExpired(); } @@ -518,32 +518,32 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard function verifyStablesLimit( uint128 collateralAmount, - uint128 ustbAmount, + uint128 usdtbAmount, address collateralAsset, OrderType orderType ) public view returns (bool) { - uint128 ustbDecimals = _getDecimals(address(ustb)); + uint128 usdtbDecimals = _getDecimals(address(usdtb)); uint128 collateralDecimals = _getDecimals(collateralAsset); uint128 normalizedCollateralAmount; uint128 scale = uint128( - ustbDecimals > collateralDecimals - ? 10 ** (ustbDecimals - collateralDecimals) - : 10 ** (collateralDecimals - ustbDecimals) + usdtbDecimals > collateralDecimals + ? 10 ** (usdtbDecimals - collateralDecimals) + : 10 ** (collateralDecimals - usdtbDecimals) ); - normalizedCollateralAmount = ustbDecimals > collateralDecimals ? collateralAmount * scale : collateralAmount / scale; + normalizedCollateralAmount = usdtbDecimals > collateralDecimals ? collateralAmount * scale : collateralAmount / scale; - uint128 difference = normalizedCollateralAmount > ustbAmount - ? normalizedCollateralAmount - ustbAmount - : ustbAmount - normalizedCollateralAmount; + uint128 difference = normalizedCollateralAmount > usdtbAmount + ? normalizedCollateralAmount - usdtbAmount + : usdtbAmount - normalizedCollateralAmount; - uint128 differenceInBps = (difference * STABLES_RATIO_MULTIPLIER) / ustbAmount; + uint128 differenceInBps = (difference * STABLES_RATIO_MULTIPLIER) / usdtbAmount; if (orderType == OrderType.MINT) { - return ustbAmount > normalizedCollateralAmount ? differenceInBps <= stablesDeltaLimit : true; + return usdtbAmount > normalizedCollateralAmount ? differenceInBps <= stablesDeltaLimit : true; } else { - return normalizedCollateralAmount > ustbAmount ? differenceInBps <= stablesDeltaLimit : true; + return normalizedCollateralAmount > usdtbAmount ? differenceInBps <= stablesDeltaLimit : true; } } @@ -603,7 +603,7 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard } function addSupportedAsset(address asset, TokenConfig memory _tokenConfig) external onlyRole(DEFAULT_ADMIN_ROLE) { - if (tokenConfig[asset].isActive || asset == address(0) || asset == address(ustb)) { + if (tokenConfig[asset].isActive || asset == address(0) || asset == address(usdtb)) { revert InvalidAssetAddress(); } _setTokenConfig(asset, _tokenConfig); @@ -649,10 +649,10 @@ contract UStbMinting is IUStbMinting, SingleAdminAccessControl, ReentrancyGuard stablesDeltaLimit = _stablesDeltaLimit; } - /// @notice set the UStb token address - function setUStbToken(IUStb _ustb) external onlyRole(DEFAULT_ADMIN_ROLE) { - ustb = _ustb; - emit UStbSet(address(_ustb)); + /// @notice set the USDtb token address + function setUSDtbToken(IUSDtb _usdtb) external onlyRole(DEFAULT_ADMIN_ROLE) { + usdtb = _usdtb; + emit USDtbSet(address(_usdtb)); } /// @notice get the decimals of a token diff --git a/test/foundry/USDtb.admin.t.sol b/test/foundry/USDtb.admin.t.sol new file mode 100644 index 0000000..8307c37 --- /dev/null +++ b/test/foundry/USDtb.admin.t.sol @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8; + +/* solhint-disable private-vars-leading-underscore */ +/* solhint-disable func-name-mixedcase */ +/* solhint-disable var-name-mixedcase */ + +import {console} from "forge-std/console.sol"; +import "forge-std/Test.sol"; +import {SigUtils} from "../utils/SigUtils.sol"; + +import "../../contracts/usdtb/USDtb.sol"; +import "../../contracts/usdtb/IUSDtbDefinitions.sol"; +import {USDtbBaseSetup} from "./USDtbBaseSetup.sol"; + +contract USDtbTest is USDtbBaseSetup { + function testRandomAddressGrantRevokeBlackistWhitelistRoleException() public { + vm.startPrank(alice); + vm.expectRevert(); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + vm.expectRevert(); + USDtbContract.revokeRole(BLACKLISTED_ROLE, alice); + vm.expectRevert(); + USDtbContract.addBlacklistAddress(new address[](0)); + vm.expectRevert(); + USDtbContract.removeBlacklistAddress(new address[](0)); + vm.expectRevert(); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + vm.expectRevert(); + USDtbContract.revokeRole(WHITELISTED_ROLE, alice); + vm.expectRevert(); + USDtbContract.addWhitelistAddress(new address[](0)); + vm.expectRevert(); + USDtbContract.removeWhitelistAddress(new address[](0)); + vm.stopPrank(); + } + + function testAdminCanGrantRevokeBlacklistRole() public { + vm.prank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + + // alice cannot send tokens + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(bob, _transferAmount); + vm.stopPrank(); + + // alice cannot receive tokens + vm.startPrank(greg); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(alice, _transferAmount); + vm.stopPrank(); + + assertEq(_amount, USDtbContract.balanceOf(alice)); + + vm.prank(newOwner); + USDtbContract.revokeRole(BLACKLISTED_ROLE, alice); + + vm.prank(alice); + USDtbContract.transfer(bob, _transferAmount); + assertEq(_amount - _transferAmount, USDtbContract.balanceOf(alice)); + } + + function testBlacklistManagerCanGrantRevokeBlacklistRole() public { + vm.prank(newOwner); + USDtbContract.grantRole(BLACKLIST_MANAGER_ROLE, newOwner); + + address[] memory toBlacklist = new address[](1); + toBlacklist[0] = alice; + vm.prank(newOwner); + USDtbContract.addBlacklistAddress(toBlacklist); + + // alice cannot send tokens + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(bob, _transferAmount); + vm.stopPrank(); + + // alice cannot receive tokens + vm.startPrank(greg); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(alice, _transferAmount); + vm.stopPrank(); + + assertEq(_amount, USDtbContract.balanceOf(alice)); + + vm.prank(newOwner); + USDtbContract.removeBlacklistAddress(toBlacklist); + + vm.prank(alice); + USDtbContract.transfer(bob, _transferAmount); + assertEq(_amount - _transferAmount, USDtbContract.balanceOf(alice)); + } + + function testAdminCanGrantRevokeWhitelistRole() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + + // alice can send tokens, bob can receive tokens + assertEq(_amount, USDtbContract.balanceOf(alice)); + vm.prank(alice); + USDtbContract.transfer(bob, _transferAmount); + assertEq(_amount - _transferAmount, USDtbContract.balanceOf(alice)); + assertEq(_amount + _transferAmount, USDtbContract.balanceOf(bob)); + + vm.prank(newOwner); + USDtbContract.revokeRole(WHITELISTED_ROLE, bob); + + // bob cannot receive tokens + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(bob, _transferAmount); + vm.stopPrank(); + + vm.prank(newOwner); + USDtbContract.revokeRole(WHITELISTED_ROLE, alice); + + // alice cannot send tokens + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(bob, _transferAmount); + vm.stopPrank(); + } + + function testWhitelistManagerCanGrantRevokeWhitelistRole() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELIST_MANAGER_ROLE, newOwner); + address[] memory toWhitelist = new address[](2); + toWhitelist[0] = alice; + toWhitelist[1] = bob; + USDtbContract.addWhitelistAddress(toWhitelist); + vm.stopPrank(); + + // alice can send tokens, bob can receive tokens + assertEq(_amount, USDtbContract.balanceOf(alice)); + vm.prank(alice); + USDtbContract.transfer(bob, _transferAmount); + assertEq(_amount - _transferAmount, USDtbContract.balanceOf(alice)); + assertEq(_amount + _transferAmount, USDtbContract.balanceOf(bob)); + + address[] memory toRemoveWhitelist = new address[](1); + toRemoveWhitelist[0] = bob; + vm.prank(newOwner); + USDtbContract.removeWhitelistAddress(toRemoveWhitelist); + + // bob cannot receive tokens + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(bob, _transferAmount); + vm.stopPrank(); + + toRemoveWhitelist[0] = alice; + vm.prank(newOwner); + USDtbContract.removeWhitelistAddress(toRemoveWhitelist); + + // alice cannot send tokens + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(bob, _transferAmount); + vm.stopPrank(); + } + + function testRenounceRoleExpectRevert() public { + vm.startPrank(newOwner); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.renounceRole(WHITELISTED_ROLE, DEAD_ADDRESS); + vm.stopPrank(); + } + + function testInvalidMinter() public { + vm.startPrank(bob); + vm.expectRevert(); + USDtbContract.mint(greg, _amount); + vm.stopPrank(); + } +} diff --git a/test/foundry/USDtb.transfers.t.sol b/test/foundry/USDtb.transfers.t.sol new file mode 100644 index 0000000..58ef176 --- /dev/null +++ b/test/foundry/USDtb.transfers.t.sol @@ -0,0 +1,1517 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8; + +/* solhint-disable private-vars-leading-underscore */ +/* solhint-disable func-name-mixedcase */ +/* solhint-disable var-name-mixedcase */ + +import {console} from "forge-std/console.sol"; +import "forge-std/Test.sol"; +import {SigUtils} from "../utils/SigUtils.sol"; + +import "../../contracts/usdtb/USDtb.sol"; +import "../../contracts/usdtb/IUSDtbDefinitions.sol"; +import {USDtbBaseSetup} from "./USDtbBaseSetup.sol"; + +contract USDtbTransferTest is USDtbBaseSetup { + function test_sender_bl_from_bl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_bl_from_bl_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_bl_from_bl_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_bl_from_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_bl_from_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_bl_from_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_from_bl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_from_bl_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_from_bl_to_fully_enabled_revert() public { + vm.prank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_from_to_fully_disabled_revert() public { + vm.prank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_from_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_from_to_fully_enabled_success() public { + vm.prank(bob); + USDtbContract.transfer(greg, _transferAmount); + assertEq(_amount + _transferAmount, USDtbContract.balanceOf(greg)); + } + + function test_sender_wl_from_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_wl_from_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_wl_from_to_fully_enabled_success() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.prank(alice); + USDtbContract.transferFrom(bob, greg, _transferAmount); + assertEq(_amount + _transferAmount, USDtbContract.balanceOf(greg)); + } + + function test_sender_from_wl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_from_wl_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_from_wl_to_fully_enabled_success() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + USDtbContract.transfer(greg, _transferAmount); + assertEq(_amount + _transferAmount, USDtbContract.balanceOf(greg)); + } + + function test_sender_wl_from_wl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_wl_from_wl_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_wl_from_wl_to_fully_enabled_success() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.prank(alice); + USDtbContract.transferFrom(bob, greg, _transferAmount); + assertEq(_amount + _transferAmount, USDtbContract.balanceOf(greg)); + } + + function test_sender_wl_from_bl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_wl_from_bl_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_wl_from_bl_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_bl_from_wl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_bl_from_wl_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_bl_from_wl_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_sender_bl_from_burn_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + } + + function test_sender_bl_from_burn_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + } + + function test_sender_bl_from_burn_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + } + + function test_sender_from_burn_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burn(_transferAmount); + vm.stopPrank(); + } + + function test_sender_from_burn_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burn(_transferAmount); + vm.stopPrank(); + } + + function test_sender_from_burn_fully_enabled_success() public { + vm.startPrank(bob); + USDtbContract.burn(_transferAmount); + vm.stopPrank(); + assertEq(_amount - _transferAmount, USDtbContract.balanceOf(bob)); + } + + function test_sender_wl_from_burn_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + } + + function test_sender_wl_from_burn_whitelist_enabled_reverts() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + } + + function test_sender_wl_from_burn_fully_enabled_success() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + assertEq(_amount - _transferAmount, USDtbContract.balanceOf(bob)); + } + + // -------------------- + + function test_bl_sender_bl_from_bl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_bl_from_bl_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_bl_from_bl_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_bl_from_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_bl_from_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_bl_from_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_from_bl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_from_bl_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_from_bl_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_from_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_from_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_from_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_wl_from_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_wl_from_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_wl_from_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_from_wl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_from_wl_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_from_wl_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_wl_from_wl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_wl_from_wl_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_wl_from_wl_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_wl_from_bl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_wl_from_bl_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_wl_from_bl_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_bl_from_wl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_bl_from_wl_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_bl_from_wl_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_bl_from_burn_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_bl_from_burn_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_bl_from_burn_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burn(_transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_from_burn_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_from_burn_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_from_burn_fully_enabled_revert() public { + vm.prank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_wl_from_burn_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_wl_from_burn_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + } + + function test_bl_sender_wl_from_burn_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + } + + // -------------------- + + function test_wl_sender_bl_from_bl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_bl_from_bl_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_bl_from_bl_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_bl_from_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_bl_from_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_bl_from_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_from_bl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_from_bl_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_from_bl_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_from_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_from_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_from_to_fully_enabled_success() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + assertEq(_amount + _transferAmount, USDtbContract.balanceOf(greg)); + } + + function test_wl_sender_wl_from_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_wl_from_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_wl_from_to_fully_enabled_success() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.startPrank(bob); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + assertEq(_amount + _transferAmount, USDtbContract.balanceOf(greg)); + } + + function test_wl_sender_from_wl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_from_wl_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_from_wl_to_fully_enabled_success() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + assertEq(_amount + _transferAmount, USDtbContract.balanceOf(greg)); + } + + function test_wl_sender_wl_from_wl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(bob, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_wl_from_wl_to_whitelist_enabled_success() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + assertEq(_amount + _transferAmount, USDtbContract.balanceOf(greg)); + } + + function test_wl_sender_wl_from_wl_to_fully_enabled_success() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + assertEq(_amount + _transferAmount, USDtbContract.balanceOf(greg)); + } + + function test_wl_sender_wl_from_bl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_wl_from_bl_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_wl_from_bl_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_bl_from_wl_to_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_bl_from_wl_to_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_bl_from_wl_to_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_bl_from_burn_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_bl_from_burn_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_bl_from_burn_fully_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transferFrom(bob, greg, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_from_burn_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_from_burn_whitelist_enabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_from_burn_fully_enabled_success() public { + vm.prank(newOwner); + USDtbContract.grantRole(WHITELISTED_ROLE, alice); + vm.prank(bob); + USDtbContract.approve(alice, _transferAmount); + vm.startPrank(alice); + USDtbContract.burnFrom(bob, _transferAmount); + vm.stopPrank(); + assertEq(_amount - _transferAmount, USDtbContract.balanceOf(bob)); + } + + function test_wl_sender_wl_from_burn_fully_disabled_revert() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.burn(_transferAmount); + vm.stopPrank(); + } + + function test_wl_sender_wl_from_burn_whitelist_enabled_success() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.burn(_transferAmount); + assertEq(_amount - _transferAmount, USDtbContract.balanceOf(bob)); + } + + function test_wl_sender_wl_from_burn_fully_enabled_success() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.burn(_transferAmount); + assertEq(_amount - _transferAmount, USDtbContract.balanceOf(bob)); + } + + // -------------------- + + function testTransferStateFullyDisabled() public { + vm.prank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + //Whitelist transfer enabled only - Fail expected as bob is not whitelisted + function testTransferStateWhitelistEnabledFail() public { + vm.prank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + //Whitelist transfer enabled only - Whitelist bob and transfer to non whitelisted. Fail expected + function testTransferStateWhitelistEnabledFail2() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + vm.stopPrank(); + vm.startPrank(bob); + vm.expectRevert(); + USDtbContract.transfer(greg, _transferAmount); + } + + function testTransferStateWhitelistEnabledFail3() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.startPrank(bob); + USDtbContract.approve(greg, _transferAmount); + vm.stopPrank(); + vm.startPrank(greg); + vm.expectRevert(); + USDtbContract.transferFrom(bob, greg, _transferAmount); + } + + //Whitelist transfer enabled only - Whitelist bob and greg. transfer from bob to greg + function testTransferStateWhitelistEnabledPass() public { + vm.startPrank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.grantRole(WHITELISTED_ROLE, greg); + vm.stopPrank(); + vm.prank(bob); + USDtbContract.transfer(greg, _transferAmount); + assertEq(_amount + _transferAmount, USDtbContract.balanceOf(greg)); + } + + function testTransferStateFullyEnabledBlacklistedFromExpectRevert() public { + vm.prank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + vm.prank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function testTransferStateFullyEnabledBlacklistedToExpectRevert() public { + vm.prank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.FULLY_DISABLED); + vm.prank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, greg); + vm.startPrank(bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.transfer(greg, _transferAmount); + vm.stopPrank(); + } + + function testRedistributeLockedAmountPass() public { + uint256 aliceBalance = USDtbContract.balanceOf(alice); + uint256 bobBalance = USDtbContract.balanceOf(bob); + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.redistributeLockedAmount(alice, bob); + vm.stopPrank(); + uint256 newBobBalance = USDtbContract.balanceOf(bob); + assertEq(aliceBalance + bobBalance, newBobBalance); + } + + function testRedistributeLockedAmountWhitelistEnabledPass() public { + vm.prank(newOwner); + USDtbContract.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + uint256 aliceBalance = USDtbContract.balanceOf(alice); + uint256 bobBalance = USDtbContract.balanceOf(bob); + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + USDtbContract.grantRole(WHITELISTED_ROLE, bob); + USDtbContract.redistributeLockedAmount(alice, bob); + vm.stopPrank(); + uint256 newBobBalance = USDtbContract.balanceOf(bob); + assertEq(aliceBalance + bobBalance, newBobBalance); + } + + function testRedistributeLockedAmountNotBlacklistedFromFails() public { + vm.startPrank(newOwner); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.redistributeLockedAmount(alice, bob); + vm.stopPrank(); + } + + function testRedistributeLockedAmountBlacklistedToFails() public { + vm.startPrank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, bob); + vm.expectRevert(IUSDtbDefinitions.OperationNotAllowed.selector); + USDtbContract.redistributeLockedAmount(alice, bob); + vm.stopPrank(); + } + + function testRedistributeLockedAmountNonAdmin() public { + vm.prank(newOwner); + USDtbContract.grantRole(BLACKLISTED_ROLE, alice); + vm.startPrank(bob); + vm.expectRevert(); + USDtbContract.redistributeLockedAmount(alice, bob); + vm.stopPrank(); + } + + function testRescueTokenAdmin() public { + vm.prank(alice); + USDtbContract.transfer(address(USDtbContract), _transferAmount); + assertEq(_amount - _transferAmount, USDtbContract.balanceOf(alice)); + vm.prank(newOwner); + USDtbContract.rescueTokens(address(USDtbContract), _transferAmount, greg); + assertEq(_amount + _transferAmount, USDtbContract.balanceOf(greg)); + } + + function testRescueTokenNonAdmin() public { + vm.prank(alice); + USDtbContract.transfer(address(USDtbContract), _transferAmount); + assertEq(_amount - _transferAmount, USDtbContract.balanceOf(alice)); + vm.startPrank(bob); + vm.expectRevert(); + USDtbContract.rescueTokens(address(USDtbContract), _transferAmount, greg); + } +} diff --git a/test/foundry/UStbBaseSetup.sol b/test/foundry/USDtbBaseSetup.sol similarity index 67% rename from test/foundry/UStbBaseSetup.sol rename to test/foundry/USDtbBaseSetup.sol index dcfc97b..228aba9 100644 --- a/test/foundry/UStbBaseSetup.sol +++ b/test/foundry/USDtbBaseSetup.sol @@ -15,37 +15,37 @@ import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.so import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; import {Upgrades} from "../../contracts/lib/Upgrades.sol"; -import {UStb} from "../../contracts/ustb/UStb.sol"; -import {IUStb} from "../../contracts/ustb/IUStb.sol"; +import {USDtb} from "../../contracts/usdtb/USDtb.sol"; +import {IUSDtb} from "../../contracts/usdtb/IUSDtb.sol"; import "../../test/utils/SigUtils.sol"; -contract UStbBaseSetup is Test { - struct UStbDeploymentAddresses { +contract USDtbBaseSetup is Test { + struct USDtbDeploymentAddresses { address proxyAddress; - address UStbImplementation; + address USDtbImplementation; address admin; address proxyAdminAddress; } - UStbDeploymentAddresses internal UStbDeploymentAddressesInstance; - ITransparentUpgradeableProxy internal UStbContractAsProxy; + USDtbDeploymentAddresses internal USDtbDeploymentAddressesInstance; + ITransparentUpgradeableProxy internal USDtbContractAsProxy; ProxyAdmin proxyAdminContract; - UStb internal UStbContract; + USDtb internal USDtbContract; uint256 internal proxyAdminOwnerPrivateKey; - uint256 internal UStbProxyStandardOwnerPrivateKey; + uint256 internal USDtbProxyStandardOwnerPrivateKey; uint256 internal newOwnerPrivateKey; uint256 internal minterPrivateKey; uint256 internal bobPrivateKey; uint256 internal gregPrivateKey; uint256 internal randomerPrivateKey; - uint256 internal UStbDeployerPrivateKey; + uint256 internal USDtbDeployerPrivateKey; uint256 internal minterContractPrivateKey; uint256 internal alicePrivateKey; address internal proxyAdminOwner; - address internal UStbProxyStandardOwner; + address internal USDtbProxyStandardOwner; address internal newOwner; address internal minter_contract; address internal minter; @@ -76,20 +76,20 @@ contract UStbBaseSetup is Test { function setUp() public virtual { proxyAdminOwnerPrivateKey = 0xA21CE; - UStbProxyStandardOwnerPrivateKey = 0xA11CE; + USDtbProxyStandardOwnerPrivateKey = 0xA11CE; newOwnerPrivateKey = 0xA14CE; minterPrivateKey = 0xB44DE; bobPrivateKey = 0x1DEA2; gregPrivateKey = 0x6ED; randomerPrivateKey = 0x1DECC; minterContractPrivateKey = 0x1DEA3; - UStbDeployerPrivateKey = uint256(keccak256(abi.encodePacked("UStbDeployer"))); + USDtbDeployerPrivateKey = uint256(keccak256(abi.encodePacked("USDtbDeployer"))); alicePrivateKey = 0xB44DE1; proxyAdminOwner = vm.addr(proxyAdminOwnerPrivateKey); // Wallet that is allowed to call the ownable methods of the implementation contract // this wallet is NOT the proxy admin owner who is allowed to call the proxy admin methods - UStbProxyStandardOwner = vm.addr(UStbProxyStandardOwnerPrivateKey); + USDtbProxyStandardOwner = vm.addr(USDtbProxyStandardOwnerPrivateKey); newOwner = vm.addr(newOwnerPrivateKey); minter = vm.addr(minterPrivateKey); bob = vm.addr(bobPrivateKey); @@ -98,7 +98,7 @@ contract UStbBaseSetup is Test { alice = vm.addr(alicePrivateKey); minter_contract = vm.addr(minterContractPrivateKey); - vm.label(UStbProxyStandardOwner, "UStbProxyStandardOwner"); + vm.label(USDtbProxyStandardOwner, "USDtbProxyStandardOwner"); vm.label(bob, "bob"); vm.label(randomer, "randomer"); vm.label(greg, "greg"); @@ -106,9 +106,9 @@ contract UStbBaseSetup is Test { vm.label(proxyAdminOwner, "proxyAdminOwner"); vm.label(alice, "alice"); - address deployerAddress = vm.addr(UStbDeployerPrivateKey); + address deployerAddress = vm.addr(USDtbDeployerPrivateKey); - vm.startBroadcast(UStbDeployerPrivateKey); + vm.startBroadcast(USDtbDeployerPrivateKey); proxyAdminContract = new ProxyAdmin(); @@ -117,29 +117,29 @@ contract UStbBaseSetup is Test { proxyAdminContract.transferOwnership(proxyAdminOwner); } - UStbDeploymentAddressesInstance.proxyAdminAddress = address(proxyAdminContract); + USDtbDeploymentAddressesInstance.proxyAdminAddress = address(proxyAdminContract); - UStbDeploymentAddressesInstance.proxyAddress = Upgrades.deployTransparentProxy( - "UStb.sol", - address(UStbDeploymentAddressesInstance.proxyAdminAddress), - abi.encodeCall(UStb.initialize, (newOwner, minter_contract)) + USDtbDeploymentAddressesInstance.proxyAddress = Upgrades.deployTransparentProxy( + "USDtb.sol", + address(USDtbDeploymentAddressesInstance.proxyAdminAddress), + abi.encodeCall(USDtb.initialize, (newOwner, minter_contract)) ); - UStbContractAsProxy = ITransparentUpgradeableProxy(payable(UStbDeploymentAddressesInstance.proxyAddress)); + USDtbContractAsProxy = ITransparentUpgradeableProxy(payable(USDtbDeploymentAddressesInstance.proxyAddress)); - UStbDeploymentAddressesInstance.UStbImplementation = - Upgrades.getImplementationAddress(UStbDeploymentAddressesInstance.proxyAddress); + USDtbDeploymentAddressesInstance.USDtbImplementation = + Upgrades.getImplementationAddress(USDtbDeploymentAddressesInstance.proxyAddress); - UStbDeploymentAddressesInstance.admin = Upgrades.getAdminAddress(UStbDeploymentAddressesInstance.proxyAddress); + USDtbDeploymentAddressesInstance.admin = Upgrades.getAdminAddress(USDtbDeploymentAddressesInstance.proxyAddress); - UStbContract = UStb(UStbDeploymentAddressesInstance.proxyAddress); + USDtbContract = USDtb(USDtbDeploymentAddressesInstance.proxyAddress); vm.stopBroadcast(); vm.startPrank(minter_contract); - UStbContract.mint(alice, _amount); - UStbContract.mint(bob, _amount); - UStbContract.mint(greg, _amount); + USDtbContract.mint(alice, _amount); + USDtbContract.mint(bob, _amount); + USDtbContract.mint(greg, _amount); vm.stopPrank(); } } diff --git a/test/foundry/USDtbMinting.utils.sol b/test/foundry/USDtbMinting.utils.sol new file mode 100644 index 0000000..31ac84d --- /dev/null +++ b/test/foundry/USDtbMinting.utils.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +/* solhint-disable func-name-mixedcase */ + +import "forge-std/console.sol"; +import "./USDtbMintingBaseSetup.sol"; + +// These functions are reused across multiple files +contract USDtbMintingUtils is USDtbMintingBaseSetup { + function maxMint_perBlock_exceeded_revert(uint128 excessiveMintAmount) public { + // This amount is always greater than the allowed max mint per block + (,, uint128 maxMintPerBlock,) = USDtbMintingContract.tokenConfig(address(stETHToken)); + + vm.assume(excessiveMintAmount > (maxMintPerBlock)); + (IUSDtbMinting.Order memory order, IUSDtbMinting.Signature memory takerSignature, IUSDtbMinting.Route memory route) = + mint_setup(excessiveMintAmount, _stETHToDeposit, stETHToken, 1, false); + + vm.prank(minter); + vm.expectRevert(MaxMintPerBlockExceeded); + USDtbMintingContract.mint(order, route, takerSignature); + + assertEq(usdtbToken.balanceOf(beneficiary), 0, "The beneficiary balance should be 0"); + assertEq(stETHToken.balanceOf(address(USDtbMintingContract)), 0, "The usdtb minting stETH balance should be 0"); + assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit, "Mismatch in stETH balance"); + } + + function maxRedeem_perBlock_exceeded_revert(uint128 excessiveRedeemAmount) public { + // Set the max mint per block to the same value as the max redeem in order to get to the redeem + vm.prank(owner); + USDtbMintingContract.setMaxMintPerBlock(excessiveRedeemAmount, address(stETHToken)); + + (IUSDtbMinting.Order memory redeemOrder, IUSDtbMinting.Signature memory takerSignature2) = + redeem_setup(excessiveRedeemAmount, _stETHToDeposit, stETHToken, 1, false); + + vm.startPrank(redeemer); + vm.expectRevert(MaxRedeemPerBlockExceeded); + USDtbMintingContract.redeem(redeemOrder, takerSignature2); + + assertEq(stETHToken.balanceOf(address(USDtbMintingContract)), _stETHToDeposit, "Mismatch in stETH balance"); + assertEq(stETHToken.balanceOf(beneficiary), 0, "Mismatch in stETH balance"); + assertEq(usdtbToken.balanceOf(beneficiary), excessiveRedeemAmount, "Mismatch in USDtb balance"); + + vm.stopPrank(); + } + + function executeMint(IERC20 collateralAsset) public { + (IUSDtbMinting.Order memory order, IUSDtbMinting.Signature memory takerSignature, IUSDtbMinting.Route memory route) = + mint_setup(_usdtbToMint, _stETHToDeposit, collateralAsset, 1, false); + + vm.prank(minter); + USDtbMintingContract.mint(order, route, takerSignature); + } + + function executeRedeem(IERC20 collateralAsset) public { + (IUSDtbMinting.Order memory redeemOrder, IUSDtbMinting.Signature memory takerSignature2) = + redeem_setup(_usdtbToMint, _stETHToDeposit, collateralAsset, 1, false); + vm.prank(redeemer); + USDtbMintingContract.redeem(redeemOrder, takerSignature2); + } +} diff --git a/test/foundry/UStbMintingBaseSetup.sol b/test/foundry/USDtbMintingBaseSetup.sol similarity index 62% rename from test/foundry/UStbMintingBaseSetup.sol rename to test/foundry/USDtbMintingBaseSetup.sol index 8d2b7b3..c4de791 100644 --- a/test/foundry/UStbMintingBaseSetup.sol +++ b/test/foundry/USDtbMintingBaseSetup.sol @@ -12,28 +12,28 @@ import {Utils} from "../utils/Utils.sol"; import {Upgrades} from "../../contracts/lib/Upgrades.sol"; import "../../contracts/mock/MockToken.sol"; -import "../../contracts/ustb/UStb.sol"; -import "../../contracts/ustb/IUStbMinting.sol"; -import "../../contracts/ustb/IUStbMintingEvents.sol"; -import "../../contracts/ustb/UStbMinting.sol"; +import "../../contracts/usdtb/USDtb.sol"; +import "../../contracts/usdtb/IUSDtbMinting.sol"; +import "../../contracts/usdtb/IUSDtbMintingEvents.sol"; +import "../../contracts/usdtb/USDtbMinting.sol"; import "../../contracts/interfaces/ISingleAdminAccessControl.sol"; -import "../../contracts/ustb/IUStbDefinitions.sol"; +import "../../contracts/usdtb/IUSDtbDefinitions.sol"; import "../../contracts/mock/MockMultisigWallet.sol"; -import "../../contracts/ustb/IUStbDefinitions.sol"; +import "../../contracts/usdtb/IUSDtbDefinitions.sol"; -contract UStbMintingBaseSetup is Test, IUStbMintingEvents, IUStbDefinitions { +contract USDtbMintingBaseSetup is Test, IUSDtbMintingEvents, IUSDtbDefinitions { Utils internal utils; - struct UStbDeploymentAddresses { + struct USDtbDeploymentAddresses { address proxyAddress; - address UStbImplementation; + address USDtbImplementation; address admin; address proxyAdminAddress; } - UStb internal ustbToken; - UStbDeploymentAddresses internal UStbDeploymentAddressesInstance; - ITransparentUpgradeableProxy internal UStbContractAsProxy; + USDtb internal usdtbToken; + USDtbDeploymentAddresses internal USDtbDeploymentAddressesInstance; + ITransparentUpgradeableProxy internal USDtbContractAsProxy; ProxyAdmin proxyAdminContract; MockToken internal stETHToken; @@ -42,14 +42,14 @@ contract UStbMintingBaseSetup is Test, IUStbMintingEvents, IUStbDefinitions { MockToken internal USDCToken; MockToken internal USDTToken; MockToken internal token; - UStbMinting internal UStbMintingContract; + USDtbMinting internal USDtbMintingContract; MockMultiSigWallet internal MultiSigWalletBenefactor; SigUtils internal sigUtils; - SigUtils internal sigUtilsUStb; + SigUtils internal sigUtilsUSDtb; uint256 internal proxyAdminOwnerPrivateKey; - uint256 internal UStbDeployerPrivateKey; - uint256 internal UStbProxyStandardOwnerPrivateKey; + uint256 internal USDtbDeployerPrivateKey; + uint256 internal USDtbProxyStandardOwnerPrivateKey; uint256 internal ownerPrivateKey; uint256 internal newOwnerPrivateKey; uint256 internal minterPrivateKey; @@ -71,8 +71,8 @@ contract UStbMintingBaseSetup is Test, IUStbMintingEvents, IUStbDefinitions { uint256 internal smartContractSigner3PrivateKey; address internal proxyAdminOwner; - address internal UStbProxyStandardOwner; - address internal UStbDeployerAddresses; + address internal USDtbProxyStandardOwner; + address internal USDtbDeployerAddresses; address internal owner; address internal newOwner; address internal minter; @@ -96,11 +96,11 @@ contract UStbMintingBaseSetup is Test, IUStbMintingEvents, IUStbDefinitions { address[] assets; address[] custodians; - IUStbMinting.TokenConfig[] tokenConfig; - IUStbMinting.GlobalConfig globalConfig; + IUSDtbMinting.TokenConfig[] tokenConfig; + IUSDtbMinting.GlobalConfig globalConfig; - IUStbMinting.TokenConfig stableConfig; - IUStbMinting.TokenConfig assetConfig; + IUSDtbMinting.TokenConfig stableConfig; + IUSDtbMinting.TokenConfig assetConfig; address internal NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; @@ -113,44 +113,44 @@ contract UStbMintingBaseSetup is Test, IUStbMintingEvents, IUStbDefinitions { bytes32 internal smartContractSignerRole = keccak256("SMART_CONTRACT_SIGNER_ROLE"); // error encodings - bytes internal InvalidAddress = abi.encodeWithSelector(IUStbMinting.InvalidAddress.selector); - bytes internal InvalidAssetAddress = abi.encodeWithSelector(IUStbMinting.InvalidAssetAddress.selector); - bytes internal InvalidOrder = abi.encodeWithSelector(IUStbMinting.InvalidOrder.selector); - bytes internal InvalidAmount = abi.encodeWithSelector(IUStbMinting.InvalidAmount.selector); - bytes internal InvalidRoute = abi.encodeWithSelector(IUStbMinting.InvalidRoute.selector); - bytes internal InvalidStablePrice = abi.encodeWithSelector(IUStbMinting.InvalidStablePrice.selector); + bytes internal InvalidAddress = abi.encodeWithSelector(IUSDtbMinting.InvalidAddress.selector); + bytes internal InvalidAssetAddress = abi.encodeWithSelector(IUSDtbMinting.InvalidAssetAddress.selector); + bytes internal InvalidOrder = abi.encodeWithSelector(IUSDtbMinting.InvalidOrder.selector); + bytes internal InvalidAmount = abi.encodeWithSelector(IUSDtbMinting.InvalidAmount.selector); + bytes internal InvalidRoute = abi.encodeWithSelector(IUSDtbMinting.InvalidRoute.selector); + bytes internal InvalidStablePrice = abi.encodeWithSelector(IUSDtbMinting.InvalidStablePrice.selector); bytes internal InvalidAdminChange = abi.encodeWithSelector(ISingleAdminAccessControl.InvalidAdminChange.selector); - bytes internal UnsupportedAsset = abi.encodeWithSelector(IUStbMinting.UnsupportedAsset.selector); - bytes internal BenefactorNotWhitelisted = abi.encodeWithSelector(IUStbMinting.BenefactorNotWhitelisted.selector); - bytes internal BeneficiaryNotApproved = abi.encodeWithSelector(IUStbMinting.BeneficiaryNotApproved.selector); - bytes internal InvalidEIP712Signature = abi.encodeWithSelector(IUStbMinting.InvalidEIP712Signature.selector); - bytes internal InvalidEIP1271Signature = abi.encodeWithSelector(IUStbMinting.InvalidEIP1271Signature.selector); - bytes internal InvalidNonce = abi.encodeWithSelector(IUStbMinting.InvalidNonce.selector); - bytes internal SignatureExpired = abi.encodeWithSelector(IUStbMinting.SignatureExpired.selector); - bytes internal MaxMintPerBlockExceeded = abi.encodeWithSelector(IUStbMinting.MaxMintPerBlockExceeded.selector); - bytes internal MaxRedeemPerBlockExceeded = abi.encodeWithSelector(IUStbMinting.MaxRedeemPerBlockExceeded.selector); + bytes internal UnsupportedAsset = abi.encodeWithSelector(IUSDtbMinting.UnsupportedAsset.selector); + bytes internal BenefactorNotWhitelisted = abi.encodeWithSelector(IUSDtbMinting.BenefactorNotWhitelisted.selector); + bytes internal BeneficiaryNotApproved = abi.encodeWithSelector(IUSDtbMinting.BeneficiaryNotApproved.selector); + bytes internal InvalidEIP712Signature = abi.encodeWithSelector(IUSDtbMinting.InvalidEIP712Signature.selector); + bytes internal InvalidEIP1271Signature = abi.encodeWithSelector(IUSDtbMinting.InvalidEIP1271Signature.selector); + bytes internal InvalidNonce = abi.encodeWithSelector(IUSDtbMinting.InvalidNonce.selector); + bytes internal SignatureExpired = abi.encodeWithSelector(IUSDtbMinting.SignatureExpired.selector); + bytes internal MaxMintPerBlockExceeded = abi.encodeWithSelector(IUSDtbMinting.MaxMintPerBlockExceeded.selector); + bytes internal MaxRedeemPerBlockExceeded = abi.encodeWithSelector(IUSDtbMinting.MaxRedeemPerBlockExceeded.selector); bytes internal GlobalMaxMintPerBlockExceeded = - abi.encodeWithSelector(IUStbMinting.GlobalMaxMintPerBlockExceeded.selector); + abi.encodeWithSelector(IUSDtbMinting.GlobalMaxMintPerBlockExceeded.selector); bytes internal GlobalMaxRedeemPerBlockExceeded = - abi.encodeWithSelector(IUStbMinting.GlobalMaxRedeemPerBlockExceeded.selector); + abi.encodeWithSelector(IUSDtbMinting.GlobalMaxRedeemPerBlockExceeded.selector); - // UStb error encodings - bytes internal ZeroAddressExceptionErr = abi.encodeWithSelector(IUStbDefinitions.ZeroAddressException.selector); - bytes internal CantRenounceOwnershipErr = abi.encodeWithSelector(IUStbDefinitions.CantRenounceOwnership.selector); + // USDtb error encodings + bytes internal ZeroAddressExceptionErr = abi.encodeWithSelector(IUSDtbDefinitions.ZeroAddressException.selector); + bytes internal CantRenounceOwnershipErr = abi.encodeWithSelector(IUSDtbDefinitions.CantRenounceOwnership.selector); bytes32 internal constant ROUTE_TYPE = keccak256("Route(address[] addresses,uint128[] ratios)"); bytes32 internal constant ORDER_TYPE = keccak256( - "Order(uint128 expiry,uint128 nonce,address benefactor,address beneficiary,address asset,uint128 collateral_amount,uint128 ustb_amount)" + "Order(uint128 expiry,uint128 nonce,address benefactor,address beneficiary,address asset,uint128 collateral_amount,uint128 usdtb_amount)" ); uint128 internal _slippageRange = 50000000000000000; uint128 internal _stETHToDeposit = 50 * 10 ** 18; uint128 internal _stETHToWithdraw = 30 * 10 ** 18; - uint128 internal _ustbToMint = 8.75 * 10 ** 23; + uint128 internal _usdtbToMint = 8.75 * 10 ** 23; uint128 internal _maxMintPerBlock = 10e23; uint128 internal _maxRedeemPerBlock = _maxMintPerBlock; - uint128 MAX_USDE_MINT_AND_REDEEM_PER_BLOCK = 2000000 * 10 ** 18; // 1 million UStb + uint128 MAX_USDE_MINT_AND_REDEEM_PER_BLOCK = 2000000 * 10 ** 18; // 1 million USDtb uint128 ASSET_MAX_USTB_MINT_AND_REDEEM_PER_BLOCK = 1000000 * 10 ** 18; uint128 STABLE_MAX_USTB_MINT_AND_REDEEM_PER_BLOCK = 1000000 * 10 ** 18; @@ -159,7 +159,7 @@ contract UStbMintingBaseSetup is Test, IUStbMintingEvents, IUStbDefinitions { // Declared at contract level to avoid stack too deep SigUtils.Permit public permit; - IUStbMinting.Order public mint; + IUSDtbMinting.Order public mint; /// @notice packs r, s, v into signature bytes function _packRsv(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) { @@ -192,8 +192,8 @@ contract UStbMintingBaseSetup is Test, IUStbMintingEvents, IUStbDefinitions { assets[5] = NATIVE_TOKEN; proxyAdminOwnerPrivateKey = 0xA21CE; - UStbProxyStandardOwnerPrivateKey = 0xA11CE; - UStbDeployerPrivateKey = 0xA14DE; + USDtbProxyStandardOwnerPrivateKey = 0xA11CE; + USDtbDeployerPrivateKey = 0xA14DE; ownerPrivateKey = 0xA11CE; newOwnerPrivateKey = 0xA14CE; minterPrivateKey = 0xB44DE; @@ -215,8 +215,8 @@ contract UStbMintingBaseSetup is Test, IUStbMintingEvents, IUStbDefinitions { smartContractSigner3PrivateKey = 0x1DE2D; proxyAdminOwner = vm.addr(proxyAdminOwnerPrivateKey); - UStbProxyStandardOwner = vm.addr(UStbProxyStandardOwnerPrivateKey); - UStbDeployerAddresses = vm.addr(UStbDeployerPrivateKey); + USDtbProxyStandardOwner = vm.addr(USDtbProxyStandardOwnerPrivateKey); + USDtbDeployerAddresses = vm.addr(USDtbDeployerPrivateKey); owner = vm.addr(ownerPrivateKey); newOwner = vm.addr(newOwnerPrivateKey); minter = vm.addr(minterPrivateKey); @@ -261,8 +261,8 @@ contract UStbMintingBaseSetup is Test, IUStbMintingEvents, IUStbDefinitions { for (uint256 i = 0; i <= 1; i++) { tokenConfig.push( - IUStbMinting.TokenConfig({ - tokenType: IUStbMinting.TokenType.STABLE, + IUSDtbMinting.TokenConfig({ + tokenType: IUSDtbMinting.TokenType.STABLE, maxMintPerBlock: STABLE_MAX_USTB_MINT_AND_REDEEM_PER_BLOCK, maxRedeemPerBlock: STABLE_MAX_USTB_MINT_AND_REDEEM_PER_BLOCK, isActive: true @@ -272,8 +272,8 @@ contract UStbMintingBaseSetup is Test, IUStbMintingEvents, IUStbDefinitions { for (uint256 j = 2; j <= 5; j++) { tokenConfig.push( - IUStbMinting.TokenConfig({ - tokenType: IUStbMinting.TokenType.ASSET, + IUSDtbMinting.TokenConfig({ + tokenType: IUSDtbMinting.TokenType.ASSET, maxMintPerBlock: ASSET_MAX_USTB_MINT_AND_REDEEM_PER_BLOCK, maxRedeemPerBlock: ASSET_MAX_USTB_MINT_AND_REDEEM_PER_BLOCK, isActive: true @@ -281,45 +281,45 @@ contract UStbMintingBaseSetup is Test, IUStbMintingEvents, IUStbDefinitions { ); } - stableConfig = IUStbMinting.TokenConfig({ - tokenType: IUStbMinting.TokenType.STABLE, + stableConfig = IUSDtbMinting.TokenConfig({ + tokenType: IUSDtbMinting.TokenType.STABLE, maxMintPerBlock: STABLE_MAX_USTB_MINT_AND_REDEEM_PER_BLOCK, maxRedeemPerBlock: STABLE_MAX_USTB_MINT_AND_REDEEM_PER_BLOCK, isActive: true }); - assetConfig = IUStbMinting.TokenConfig({ - tokenType: IUStbMinting.TokenType.ASSET, + assetConfig = IUSDtbMinting.TokenConfig({ + tokenType: IUSDtbMinting.TokenType.ASSET, maxMintPerBlock: ASSET_MAX_USTB_MINT_AND_REDEEM_PER_BLOCK, maxRedeemPerBlock: ASSET_MAX_USTB_MINT_AND_REDEEM_PER_BLOCK, isActive: true }); - globalConfig = IUStbMinting.GlobalConfig(MAX_USDE_MINT_AND_REDEEM_PER_BLOCK, MAX_USDE_MINT_AND_REDEEM_PER_BLOCK); + globalConfig = IUSDtbMinting.GlobalConfig(MAX_USDE_MINT_AND_REDEEM_PER_BLOCK, MAX_USDE_MINT_AND_REDEEM_PER_BLOCK); // Set the roles vm.startPrank(owner); - UStbMintingContract = new UStbMinting(assets, tokenConfig, globalConfig, custodians, owner); + USDtbMintingContract = new USDtbMinting(assets, tokenConfig, globalConfig, custodians, owner); - UStbMintingContract.setStablesDeltaLimit(100); + USDtbMintingContract.setStablesDeltaLimit(100); - UStbMintingContract.grantRole(gatekeeperRole, gatekeeper); - UStbMintingContract.grantRole(redeemerRole, redeemer); - UStbMintingContract.grantRole(collateralManagerRole, collateralManager); - UStbMintingContract.grantRole(minterRole, minter); + USDtbMintingContract.grantRole(gatekeeperRole, gatekeeper); + USDtbMintingContract.grantRole(redeemerRole, redeemer); + USDtbMintingContract.grantRole(collateralManagerRole, collateralManager); + USDtbMintingContract.grantRole(minterRole, minter); // Multi Sig - Smart Contract Based Signing MultiSigWalletBenefactor = new MockMultiSigWallet(owner, smartContractSigner1, smartContractSigner2); mockMultiSigWallet = address(MultiSigWalletBenefactor); - UStbMintingContract.addWhitelistedBenefactor(benefactor); - UStbMintingContract.addWhitelistedBenefactor(beneficiary); - UStbMintingContract.addWhitelistedBenefactor(trader1); - UStbMintingContract.addWhitelistedBenefactor(trader2); - UStbMintingContract.addWhitelistedBenefactor(redeemer); - UStbMintingContract.addWhitelistedBenefactor(mockMultiSigWallet); + USDtbMintingContract.addWhitelistedBenefactor(benefactor); + USDtbMintingContract.addWhitelistedBenefactor(beneficiary); + USDtbMintingContract.addWhitelistedBenefactor(trader1); + USDtbMintingContract.addWhitelistedBenefactor(trader2); + USDtbMintingContract.addWhitelistedBenefactor(redeemer); + USDtbMintingContract.addWhitelistedBenefactor(mockMultiSigWallet); // Add self as approved custodian - UStbMintingContract.addCustodianAddress(address(UStbMintingContract)); + USDtbMintingContract.addCustodianAddress(address(USDtbMintingContract)); // Mock Multi Sig assigned a quorum of three signers forming a composite benefactor MultiSigWalletBenefactor.grantRole(smartContractSignerRole, smartContractSigner1); @@ -331,33 +331,33 @@ contract UStbMintingBaseSetup is Test, IUStbMintingEvents, IUStbDefinitions { vm.stopPrank(); vm.startPrank(beneficiary); - UStbMintingContract.setApprovedBeneficiary(beneficiary, true); - UStbMintingContract.setApprovedBeneficiary(benefactor, true); + USDtbMintingContract.setApprovedBeneficiary(beneficiary, true); + USDtbMintingContract.setApprovedBeneficiary(benefactor, true); vm.stopPrank(); vm.startPrank(benefactor); - UStbMintingContract.setApprovedBeneficiary(beneficiary, true); - UStbMintingContract.setApprovedBeneficiary(benefactor, true); - UStbMintingContract.setApprovedBeneficiary(trader1, true); - UStbMintingContract.setApprovedBeneficiary(trader2, true); - UStbMintingContract.setApprovedBeneficiary(address(MultiSigWalletBenefactor), true); + USDtbMintingContract.setApprovedBeneficiary(beneficiary, true); + USDtbMintingContract.setApprovedBeneficiary(benefactor, true); + USDtbMintingContract.setApprovedBeneficiary(trader1, true); + USDtbMintingContract.setApprovedBeneficiary(trader2, true); + USDtbMintingContract.setApprovedBeneficiary(address(MultiSigWalletBenefactor), true); vm.stopPrank(); vm.startPrank(redeemer); - UStbMintingContract.setApprovedBeneficiary(redeemer, true); - UStbMintingContract.setApprovedBeneficiary(beneficiary, true); + USDtbMintingContract.setApprovedBeneficiary(redeemer, true); + USDtbMintingContract.setApprovedBeneficiary(beneficiary, true); vm.stopPrank(); vm.startPrank(address(MultiSigWalletBenefactor)); - UStbMintingContract.setApprovedBeneficiary(mockMultiSigWallet, true); - UStbMintingContract.setApprovedBeneficiary(beneficiary, true); + USDtbMintingContract.setApprovedBeneficiary(mockMultiSigWallet, true); + USDtbMintingContract.setApprovedBeneficiary(beneficiary, true); vm.stopPrank(); - // deploy UStb + // deploy USDtb - address deployerAddress = vm.addr(UStbDeployerPrivateKey); + address deployerAddress = vm.addr(USDtbDeployerPrivateKey); - vm.startBroadcast(UStbDeployerPrivateKey); + vm.startBroadcast(USDtbDeployerPrivateKey); proxyAdminContract = new ProxyAdmin(); @@ -366,27 +366,27 @@ contract UStbMintingBaseSetup is Test, IUStbMintingEvents, IUStbDefinitions { proxyAdminContract.transferOwnership(proxyAdminOwner); } - UStbDeploymentAddressesInstance.proxyAdminAddress = address(proxyAdminContract); + USDtbDeploymentAddressesInstance.proxyAdminAddress = address(proxyAdminContract); - UStbDeploymentAddressesInstance.proxyAddress = Upgrades.deployTransparentProxy( - "UStb.sol", - address(UStbDeploymentAddressesInstance.proxyAdminAddress), - abi.encodeCall(UStb.initialize, (newOwner, address(UStbMintingContract))) + USDtbDeploymentAddressesInstance.proxyAddress = Upgrades.deployTransparentProxy( + "USDtb.sol", + address(USDtbDeploymentAddressesInstance.proxyAdminAddress), + abi.encodeCall(USDtb.initialize, (newOwner, address(USDtbMintingContract))) ); - UStbContractAsProxy = ITransparentUpgradeableProxy(payable(UStbDeploymentAddressesInstance.proxyAddress)); + USDtbContractAsProxy = ITransparentUpgradeableProxy(payable(USDtbDeploymentAddressesInstance.proxyAddress)); - UStbDeploymentAddressesInstance.UStbImplementation = - Upgrades.getImplementationAddress(UStbDeploymentAddressesInstance.proxyAddress); + USDtbDeploymentAddressesInstance.USDtbImplementation = + Upgrades.getImplementationAddress(USDtbDeploymentAddressesInstance.proxyAddress); - UStbDeploymentAddressesInstance.admin = Upgrades.getAdminAddress(UStbDeploymentAddressesInstance.proxyAddress); + USDtbDeploymentAddressesInstance.admin = Upgrades.getAdminAddress(USDtbDeploymentAddressesInstance.proxyAddress); - ustbToken = UStb(UStbDeploymentAddressesInstance.proxyAddress); + usdtbToken = USDtb(USDtbDeploymentAddressesInstance.proxyAddress); vm.stopBroadcast(); - // Set UStb token as UStb Minting Token + // Set USDtb token as USDtb Minting Token vm.prank(owner); - UStbMintingContract.setUStbToken(IUStb(address(ustbToken))); + USDtbMintingContract.setUSDtbToken(IUSDtb(address(usdtbToken))); } function generateRandomOrderId() internal view returns (string memory) { @@ -399,29 +399,29 @@ contract UStbMintingBaseSetup is Test, IUStbMintingEvents, IUStbDefinitions { return string(abi.encodePacked(ORDER_ID_PREFIX, randomChars)); } - function _generateRouteTypeHash(IUStbMinting.Route memory route) internal pure returns (bytes32) { + function _generateRouteTypeHash(IUSDtbMinting.Route memory route) internal pure returns (bytes32) { return keccak256( abi.encode(ROUTE_TYPE, keccak256(abi.encodePacked(route.addresses)), keccak256(abi.encodePacked(route.ratios))) ); } - function signOrder(uint256 key, bytes32 digest, IUStbMinting.SignatureType sigType) + function signOrder(uint256 key, bytes32 digest, IUSDtbMinting.SignatureType sigType) public pure - returns (IUStbMinting.Signature memory) + returns (IUSDtbMinting.Signature memory) { (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, digest); bytes memory sigBytes = _packRsv(r, s, v); - IUStbMinting.Signature memory signature = - IUStbMinting.Signature({signature_type: sigType, signature_bytes: sigBytes}); + IUSDtbMinting.Signature memory signature = + IUSDtbMinting.Signature({signature_type: sigType, signature_bytes: sigBytes}); return signature; } // Generic mint setup reused in the tests to reduce lines of code function mint_setup( - uint128 ustbAmount, + uint128 usdtbAmount, uint128 collateralAmount, IERC20 collateralToken, uint128 nonce, @@ -429,89 +429,89 @@ contract UStbMintingBaseSetup is Test, IUStbMintingEvents, IUStbDefinitions { ) public returns ( - IUStbMinting.Order memory order, - IUStbMinting.Signature memory takerSignature, - IUStbMinting.Route memory route + IUSDtbMinting.Order memory order, + IUSDtbMinting.Signature memory takerSignature, + IUSDtbMinting.Route memory route ) { - order = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.MINT, + order = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.MINT, order_id: generateRandomOrderId(), expiry: uint120(uint128(block.timestamp + 10 minutes)), nonce: nonce, benefactor: benefactor, beneficiary: beneficiary, collateral_asset: address(collateralToken), - ustb_amount: ustbAmount, + usdtb_amount: usdtbAmount, collateral_amount: collateralAmount }); address[] memory targets = new address[](1); - targets[0] = address(UStbMintingContract); + targets[0] = address(USDtbMintingContract); uint128[] memory ratios = new uint128[](1); ratios[0] = 10_000; - route = IUStbMinting.Route({addresses: targets, ratios: ratios}); + route = IUSDtbMinting.Route({addresses: targets, ratios: ratios}); vm.startPrank(benefactor); - bytes32 digest1 = UStbMintingContract.hashOrder(order); - takerSignature = signOrder(benefactorPrivateKey, digest1, IUStbMinting.SignatureType.EIP712); - collateralToken.approve(address(UStbMintingContract), collateralAmount); + bytes32 digest1 = USDtbMintingContract.hashOrder(order); + takerSignature = signOrder(benefactorPrivateKey, digest1, IUSDtbMinting.SignatureType.EIP712); + collateralToken.approve(address(USDtbMintingContract), collateralAmount); vm.stopPrank(); if (!multipleMints) { - assertEq(ustbToken.balanceOf(beneficiary), 0, "Mismatch in UStb balance"); - assertEq(collateralToken.balanceOf(address(UStbMintingContract)), 0, "Mismatch in collateral balance"); + assertEq(usdtbToken.balanceOf(beneficiary), 0, "Mismatch in USDtb balance"); + assertEq(collateralToken.balanceOf(address(USDtbMintingContract)), 0, "Mismatch in collateral balance"); assertEq(collateralToken.balanceOf(benefactor), collateralAmount, "Mismatch in collateral balance"); } } // Generic redeem setup reused in the tests to reduce lines of code function redeem_setup( - uint128 ustbAmount, + uint128 usdtbAmount, uint128 collateralAmount, IERC20 collateralAsset, uint128 nonce, bool multipleRedeem - ) public returns (IUStbMinting.Order memory redeemOrder, IUStbMinting.Signature memory takerSignature2) { - (IUStbMinting.Order memory mintOrder, IUStbMinting.Signature memory takerSignature, IUStbMinting.Route memory route) - = mint_setup(ustbAmount, collateralAmount, collateralAsset, nonce, true); + ) public returns (IUSDtbMinting.Order memory redeemOrder, IUSDtbMinting.Signature memory takerSignature2) { + (IUSDtbMinting.Order memory mintOrder, IUSDtbMinting.Signature memory takerSignature, IUSDtbMinting.Route memory route) + = mint_setup(usdtbAmount, collateralAmount, collateralAsset, nonce, true); vm.prank(minter); - UStbMintingContract.mint(mintOrder, route, takerSignature); + USDtbMintingContract.mint(mintOrder, route, takerSignature); //redeem - redeemOrder = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.REDEEM, + redeemOrder = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.REDEEM, order_id: generateRandomOrderId(), expiry: uint120(uint128(block.timestamp + 10 minutes)), nonce: nonce + 1, benefactor: beneficiary, beneficiary: beneficiary, collateral_asset: address(collateralAsset), - ustb_amount: ustbAmount, + usdtb_amount: usdtbAmount, collateral_amount: collateralAmount }); // taker vm.startPrank(beneficiary); - ustbToken.approve(address(UStbMintingContract), ustbAmount); + usdtbToken.approve(address(USDtbMintingContract), usdtbAmount); - bytes32 digest3 = UStbMintingContract.hashOrder(redeemOrder); - takerSignature2 = signOrder(beneficiaryPrivateKey, digest3, IUStbMinting.SignatureType.EIP712); + bytes32 digest3 = USDtbMintingContract.hashOrder(redeemOrder); + takerSignature2 = signOrder(beneficiaryPrivateKey, digest3, IUSDtbMinting.SignatureType.EIP712); vm.stopPrank(); vm.startPrank(owner); - UStbMintingContract.grantRole(redeemerRole, redeemer); + USDtbMintingContract.grantRole(redeemerRole, redeemer); vm.stopPrank(); if (!multipleRedeem) { assertEq( - collateralAsset.balanceOf(address(UStbMintingContract)), collateralAmount, "Mismatch in collateral balance" + collateralAsset.balanceOf(address(USDtbMintingContract)), collateralAmount, "Mismatch in collateral balance" ); assertEq(collateralAsset.balanceOf(beneficiary), 0, "Mismatch in collateral balance"); - assertEq(ustbToken.balanceOf(beneficiary), ustbAmount, "Mismatch in UStb balance"); + assertEq(usdtbToken.balanceOf(beneficiary), usdtbAmount, "Mismatch in USDtb balance"); } } } diff --git a/test/foundry/UStb.admin.t.sol b/test/foundry/UStb.admin.t.sol deleted file mode 100644 index 1ced8cf..0000000 --- a/test/foundry/UStb.admin.t.sol +++ /dev/null @@ -1,180 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8; - -/* solhint-disable private-vars-leading-underscore */ -/* solhint-disable func-name-mixedcase */ -/* solhint-disable var-name-mixedcase */ - -import {console} from "forge-std/console.sol"; -import "forge-std/Test.sol"; -import {SigUtils} from "../utils/SigUtils.sol"; - -import "../../contracts/ustb/UStb.sol"; -import "../../contracts/ustb/IUStbDefinitions.sol"; -import {UStbBaseSetup} from "./UStbBaseSetup.sol"; - -contract UStbTest is UStbBaseSetup { - function testRandomAddressGrantRevokeBlackistWhitelistRoleException() public { - vm.startPrank(alice); - vm.expectRevert(); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - vm.expectRevert(); - UStbContract.revokeRole(BLACKLISTED_ROLE, alice); - vm.expectRevert(); - UStbContract.addBlacklistAddress(new address[](0)); - vm.expectRevert(); - UStbContract.removeBlacklistAddress(new address[](0)); - vm.expectRevert(); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - vm.expectRevert(); - UStbContract.revokeRole(WHITELISTED_ROLE, alice); - vm.expectRevert(); - UStbContract.addWhitelistAddress(new address[](0)); - vm.expectRevert(); - UStbContract.removeWhitelistAddress(new address[](0)); - vm.stopPrank(); - } - - function testAdminCanGrantRevokeBlacklistRole() public { - vm.prank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - - // alice cannot send tokens - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(bob, _transferAmount); - vm.stopPrank(); - - // alice cannot receive tokens - vm.startPrank(greg); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(alice, _transferAmount); - vm.stopPrank(); - - assertEq(_amount, UStbContract.balanceOf(alice)); - - vm.prank(newOwner); - UStbContract.revokeRole(BLACKLISTED_ROLE, alice); - - vm.prank(alice); - UStbContract.transfer(bob, _transferAmount); - assertEq(_amount - _transferAmount, UStbContract.balanceOf(alice)); - } - - function testBlacklistManagerCanGrantRevokeBlacklistRole() public { - vm.prank(newOwner); - UStbContract.grantRole(BLACKLIST_MANAGER_ROLE, newOwner); - - address[] memory toBlacklist = new address[](1); - toBlacklist[0] = alice; - vm.prank(newOwner); - UStbContract.addBlacklistAddress(toBlacklist); - - // alice cannot send tokens - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(bob, _transferAmount); - vm.stopPrank(); - - // alice cannot receive tokens - vm.startPrank(greg); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(alice, _transferAmount); - vm.stopPrank(); - - assertEq(_amount, UStbContract.balanceOf(alice)); - - vm.prank(newOwner); - UStbContract.removeBlacklistAddress(toBlacklist); - - vm.prank(alice); - UStbContract.transfer(bob, _transferAmount); - assertEq(_amount - _transferAmount, UStbContract.balanceOf(alice)); - } - - function testAdminCanGrantRevokeWhitelistRole() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - - // alice can send tokens, bob can receive tokens - assertEq(_amount, UStbContract.balanceOf(alice)); - vm.prank(alice); - UStbContract.transfer(bob, _transferAmount); - assertEq(_amount - _transferAmount, UStbContract.balanceOf(alice)); - assertEq(_amount + _transferAmount, UStbContract.balanceOf(bob)); - - vm.prank(newOwner); - UStbContract.revokeRole(WHITELISTED_ROLE, bob); - - // bob cannot receive tokens - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(bob, _transferAmount); - vm.stopPrank(); - - vm.prank(newOwner); - UStbContract.revokeRole(WHITELISTED_ROLE, alice); - - // alice cannot send tokens - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(bob, _transferAmount); - vm.stopPrank(); - } - - function testWhitelistManagerCanGrantRevokeWhitelistRole() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELIST_MANAGER_ROLE, newOwner); - address[] memory toWhitelist = new address[](2); - toWhitelist[0] = alice; - toWhitelist[1] = bob; - UStbContract.addWhitelistAddress(toWhitelist); - vm.stopPrank(); - - // alice can send tokens, bob can receive tokens - assertEq(_amount, UStbContract.balanceOf(alice)); - vm.prank(alice); - UStbContract.transfer(bob, _transferAmount); - assertEq(_amount - _transferAmount, UStbContract.balanceOf(alice)); - assertEq(_amount + _transferAmount, UStbContract.balanceOf(bob)); - - address[] memory toRemoveWhitelist = new address[](1); - toRemoveWhitelist[0] = bob; - vm.prank(newOwner); - UStbContract.removeWhitelistAddress(toRemoveWhitelist); - - // bob cannot receive tokens - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(bob, _transferAmount); - vm.stopPrank(); - - toRemoveWhitelist[0] = alice; - vm.prank(newOwner); - UStbContract.removeWhitelistAddress(toRemoveWhitelist); - - // alice cannot send tokens - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(bob, _transferAmount); - vm.stopPrank(); - } - - function testRenounceRoleExpectRevert() public { - vm.startPrank(newOwner); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.renounceRole(WHITELISTED_ROLE, DEAD_ADDRESS); - vm.stopPrank(); - } - - function testInvalidMinter() public { - vm.startPrank(bob); - vm.expectRevert(); - UStbContract.mint(greg, _amount); - vm.stopPrank(); - } -} diff --git a/test/foundry/UStb.transfers.t.sol b/test/foundry/UStb.transfers.t.sol deleted file mode 100644 index 7873997..0000000 --- a/test/foundry/UStb.transfers.t.sol +++ /dev/null @@ -1,1517 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8; - -/* solhint-disable private-vars-leading-underscore */ -/* solhint-disable func-name-mixedcase */ -/* solhint-disable var-name-mixedcase */ - -import {console} from "forge-std/console.sol"; -import "forge-std/Test.sol"; -import {SigUtils} from "../utils/SigUtils.sol"; - -import "../../contracts/ustb/UStb.sol"; -import "../../contracts/ustb/IUStbDefinitions.sol"; -import {UStbBaseSetup} from "./UStbBaseSetup.sol"; - -contract UStbTransferTest is UStbBaseSetup { - function test_sender_bl_from_bl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_bl_from_bl_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_bl_from_bl_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_bl_from_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_bl_from_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_bl_from_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_from_bl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_from_bl_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_from_bl_to_fully_enabled_revert() public { - vm.prank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_from_to_fully_disabled_revert() public { - vm.prank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_from_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_from_to_fully_enabled_success() public { - vm.prank(bob); - UStbContract.transfer(greg, _transferAmount); - assertEq(_amount + _transferAmount, UStbContract.balanceOf(greg)); - } - - function test_sender_wl_from_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_wl_from_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_wl_from_to_fully_enabled_success() public { - vm.startPrank(newOwner); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.prank(alice); - UStbContract.transferFrom(bob, greg, _transferAmount); - assertEq(_amount + _transferAmount, UStbContract.balanceOf(greg)); - } - - function test_sender_from_wl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_from_wl_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_from_wl_to_fully_enabled_success() public { - vm.startPrank(newOwner); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - UStbContract.transfer(greg, _transferAmount); - assertEq(_amount + _transferAmount, UStbContract.balanceOf(greg)); - } - - function test_sender_wl_from_wl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_wl_from_wl_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_wl_from_wl_to_fully_enabled_success() public { - vm.startPrank(newOwner); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.prank(alice); - UStbContract.transferFrom(bob, greg, _transferAmount); - assertEq(_amount + _transferAmount, UStbContract.balanceOf(greg)); - } - - function test_sender_wl_from_bl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_wl_from_bl_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_wl_from_bl_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_bl_from_wl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_bl_from_wl_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_bl_from_wl_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_sender_bl_from_burn_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - } - - function test_sender_bl_from_burn_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - } - - function test_sender_bl_from_burn_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - } - - function test_sender_from_burn_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burn(_transferAmount); - vm.stopPrank(); - } - - function test_sender_from_burn_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burn(_transferAmount); - vm.stopPrank(); - } - - function test_sender_from_burn_fully_enabled_success() public { - vm.startPrank(bob); - UStbContract.burn(_transferAmount); - vm.stopPrank(); - assertEq(_amount - _transferAmount, UStbContract.balanceOf(bob)); - } - - function test_sender_wl_from_burn_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - } - - function test_sender_wl_from_burn_whitelist_enabled_reverts() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - } - - function test_sender_wl_from_burn_fully_enabled_success() public { - vm.startPrank(newOwner); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - assertEq(_amount - _transferAmount, UStbContract.balanceOf(bob)); - } - - // -------------------- - - function test_bl_sender_bl_from_bl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_bl_from_bl_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_bl_from_bl_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_bl_from_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_bl_from_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_bl_from_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_from_bl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_from_bl_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_from_bl_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_from_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_from_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_from_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_wl_from_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_wl_from_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_wl_from_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_from_wl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_from_wl_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_from_wl_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_wl_from_wl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_wl_from_wl_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_wl_from_wl_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_wl_from_bl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_wl_from_bl_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_wl_from_bl_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_bl_from_wl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_bl_from_wl_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_bl_from_wl_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_bl_from_burn_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_bl_from_burn_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_bl_from_burn_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burn(_transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_from_burn_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_from_burn_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_from_burn_fully_enabled_revert() public { - vm.prank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_wl_from_burn_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_wl_from_burn_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - } - - function test_bl_sender_wl_from_burn_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - } - - // -------------------- - - function test_wl_sender_bl_from_bl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_bl_from_bl_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_bl_from_bl_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_bl_from_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_bl_from_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_bl_from_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_from_bl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_from_bl_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_from_bl_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_from_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_from_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_from_to_fully_enabled_success() public { - vm.startPrank(newOwner); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - assertEq(_amount + _transferAmount, UStbContract.balanceOf(greg)); - } - - function test_wl_sender_wl_from_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_wl_from_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_wl_from_to_fully_enabled_success() public { - vm.startPrank(newOwner); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.startPrank(bob); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - assertEq(_amount + _transferAmount, UStbContract.balanceOf(greg)); - } - - function test_wl_sender_from_wl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_from_wl_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_from_wl_to_fully_enabled_success() public { - vm.startPrank(newOwner); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - assertEq(_amount + _transferAmount, UStbContract.balanceOf(greg)); - } - - function test_wl_sender_wl_from_wl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(bob, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_wl_from_wl_to_whitelist_enabled_success() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - assertEq(_amount + _transferAmount, UStbContract.balanceOf(greg)); - } - - function test_wl_sender_wl_from_wl_to_fully_enabled_success() public { - vm.startPrank(newOwner); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - assertEq(_amount + _transferAmount, UStbContract.balanceOf(greg)); - } - - function test_wl_sender_wl_from_bl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_wl_from_bl_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_wl_from_bl_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_bl_from_wl_to_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_bl_from_wl_to_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_bl_from_wl_to_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_bl_from_burn_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_bl_from_burn_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_bl_from_burn_fully_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transferFrom(bob, greg, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_from_burn_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_from_burn_whitelist_enabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - vm.stopPrank(); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_from_burn_fully_enabled_success() public { - vm.prank(newOwner); - UStbContract.grantRole(WHITELISTED_ROLE, alice); - vm.prank(bob); - UStbContract.approve(alice, _transferAmount); - vm.startPrank(alice); - UStbContract.burnFrom(bob, _transferAmount); - vm.stopPrank(); - assertEq(_amount - _transferAmount, UStbContract.balanceOf(bob)); - } - - function test_wl_sender_wl_from_burn_fully_disabled_revert() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.burn(_transferAmount); - vm.stopPrank(); - } - - function test_wl_sender_wl_from_burn_whitelist_enabled_success() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.burn(_transferAmount); - assertEq(_amount - _transferAmount, UStbContract.balanceOf(bob)); - } - - function test_wl_sender_wl_from_burn_fully_enabled_success() public { - vm.startPrank(newOwner); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.prank(bob); - UStbContract.burn(_transferAmount); - assertEq(_amount - _transferAmount, UStbContract.balanceOf(bob)); - } - - // -------------------- - - function testTransferStateFullyDisabled() public { - vm.prank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - //Whitelist transfer enabled only - Fail expected as bob is not whitelisted - function testTransferStateWhitelistEnabledFail() public { - vm.prank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - //Whitelist transfer enabled only - Whitelist bob and transfer to non whitelisted. Fail expected - function testTransferStateWhitelistEnabledFail2() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - vm.stopPrank(); - vm.startPrank(bob); - vm.expectRevert(); - UStbContract.transfer(greg, _transferAmount); - } - - function testTransferStateWhitelistEnabledFail3() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.startPrank(bob); - UStbContract.approve(greg, _transferAmount); - vm.stopPrank(); - vm.startPrank(greg); - vm.expectRevert(); - UStbContract.transferFrom(bob, greg, _transferAmount); - } - - //Whitelist transfer enabled only - Whitelist bob and greg. transfer from bob to greg - function testTransferStateWhitelistEnabledPass() public { - vm.startPrank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.grantRole(WHITELISTED_ROLE, greg); - vm.stopPrank(); - vm.prank(bob); - UStbContract.transfer(greg, _transferAmount); - assertEq(_amount + _transferAmount, UStbContract.balanceOf(greg)); - } - - function testTransferStateFullyEnabledBlacklistedFromExpectRevert() public { - vm.prank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - vm.prank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function testTransferStateFullyEnabledBlacklistedToExpectRevert() public { - vm.prank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.FULLY_DISABLED); - vm.prank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, greg); - vm.startPrank(bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.transfer(greg, _transferAmount); - vm.stopPrank(); - } - - function testRedistributeLockedAmountPass() public { - uint256 aliceBalance = UStbContract.balanceOf(alice); - uint256 bobBalance = UStbContract.balanceOf(bob); - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.redistributeLockedAmount(alice, bob); - vm.stopPrank(); - uint256 newBobBalance = UStbContract.balanceOf(bob); - assertEq(aliceBalance + bobBalance, newBobBalance); - } - - function testRedistributeLockedAmountWhitelistEnabledPass() public { - vm.prank(newOwner); - UStbContract.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - uint256 aliceBalance = UStbContract.balanceOf(alice); - uint256 bobBalance = UStbContract.balanceOf(bob); - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - UStbContract.grantRole(WHITELISTED_ROLE, bob); - UStbContract.redistributeLockedAmount(alice, bob); - vm.stopPrank(); - uint256 newBobBalance = UStbContract.balanceOf(bob); - assertEq(aliceBalance + bobBalance, newBobBalance); - } - - function testRedistributeLockedAmountNotBlacklistedFromFails() public { - vm.startPrank(newOwner); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.redistributeLockedAmount(alice, bob); - vm.stopPrank(); - } - - function testRedistributeLockedAmountBlacklistedToFails() public { - vm.startPrank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, bob); - vm.expectRevert(IUStbDefinitions.OperationNotAllowed.selector); - UStbContract.redistributeLockedAmount(alice, bob); - vm.stopPrank(); - } - - function testRedistributeLockedAmountNonAdmin() public { - vm.prank(newOwner); - UStbContract.grantRole(BLACKLISTED_ROLE, alice); - vm.startPrank(bob); - vm.expectRevert(); - UStbContract.redistributeLockedAmount(alice, bob); - vm.stopPrank(); - } - - function testRescueTokenAdmin() public { - vm.prank(alice); - UStbContract.transfer(address(UStbContract), _transferAmount); - assertEq(_amount - _transferAmount, UStbContract.balanceOf(alice)); - vm.prank(newOwner); - UStbContract.rescueTokens(address(UStbContract), _transferAmount, greg); - assertEq(_amount + _transferAmount, UStbContract.balanceOf(greg)); - } - - function testRescueTokenNonAdmin() public { - vm.prank(alice); - UStbContract.transfer(address(UStbContract), _transferAmount); - assertEq(_amount - _transferAmount, UStbContract.balanceOf(alice)); - vm.startPrank(bob); - vm.expectRevert(); - UStbContract.rescueTokens(address(UStbContract), _transferAmount, greg); - } -} diff --git a/test/foundry/UStbMinting.utils.sol b/test/foundry/UStbMinting.utils.sol deleted file mode 100644 index 9c7260f..0000000 --- a/test/foundry/UStbMinting.utils.sol +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* solhint-disable func-name-mixedcase */ - -import "forge-std/console.sol"; -import "./UStbMintingBaseSetup.sol"; - -// These functions are reused across multiple files -contract UStbMintingUtils is UStbMintingBaseSetup { - function maxMint_perBlock_exceeded_revert(uint128 excessiveMintAmount) public { - // This amount is always greater than the allowed max mint per block - (,, uint128 maxMintPerBlock,) = UStbMintingContract.tokenConfig(address(stETHToken)); - - vm.assume(excessiveMintAmount > (maxMintPerBlock)); - (IUStbMinting.Order memory order, IUStbMinting.Signature memory takerSignature, IUStbMinting.Route memory route) = - mint_setup(excessiveMintAmount, _stETHToDeposit, stETHToken, 1, false); - - vm.prank(minter); - vm.expectRevert(MaxMintPerBlockExceeded); - UStbMintingContract.mint(order, route, takerSignature); - - assertEq(ustbToken.balanceOf(beneficiary), 0, "The beneficiary balance should be 0"); - assertEq(stETHToken.balanceOf(address(UStbMintingContract)), 0, "The ustb minting stETH balance should be 0"); - assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit, "Mismatch in stETH balance"); - } - - function maxRedeem_perBlock_exceeded_revert(uint128 excessiveRedeemAmount) public { - // Set the max mint per block to the same value as the max redeem in order to get to the redeem - vm.prank(owner); - UStbMintingContract.setMaxMintPerBlock(excessiveRedeemAmount, address(stETHToken)); - - (IUStbMinting.Order memory redeemOrder, IUStbMinting.Signature memory takerSignature2) = - redeem_setup(excessiveRedeemAmount, _stETHToDeposit, stETHToken, 1, false); - - vm.startPrank(redeemer); - vm.expectRevert(MaxRedeemPerBlockExceeded); - UStbMintingContract.redeem(redeemOrder, takerSignature2); - - assertEq(stETHToken.balanceOf(address(UStbMintingContract)), _stETHToDeposit, "Mismatch in stETH balance"); - assertEq(stETHToken.balanceOf(beneficiary), 0, "Mismatch in stETH balance"); - assertEq(ustbToken.balanceOf(beneficiary), excessiveRedeemAmount, "Mismatch in UStb balance"); - - vm.stopPrank(); - } - - function executeMint(IERC20 collateralAsset) public { - (IUStbMinting.Order memory order, IUStbMinting.Signature memory takerSignature, IUStbMinting.Route memory route) = - mint_setup(_ustbToMint, _stETHToDeposit, collateralAsset, 1, false); - - vm.prank(minter); - UStbMintingContract.mint(order, route, takerSignature); - } - - function executeRedeem(IERC20 collateralAsset) public { - (IUStbMinting.Order memory redeemOrder, IUStbMinting.Signature memory takerSignature2) = - redeem_setup(_ustbToMint, _stETHToDeposit, collateralAsset, 1, false); - vm.prank(redeemer); - UStbMintingContract.redeem(redeemOrder, takerSignature2); - } -} diff --git a/test/foundry/test/UStbMinting.ACL.t.sol b/test/foundry/test/USDtbMinting.ACL.t.sol similarity index 55% rename from test/foundry/test/UStbMinting.ACL.t.sol rename to test/foundry/test/USDtbMinting.ACL.t.sol index ab07a77..0b1d75b 100644 --- a/test/foundry/test/UStbMinting.ACL.t.sol +++ b/test/foundry/test/USDtbMinting.ACL.t.sol @@ -3,20 +3,20 @@ pragma solidity ^0.8.20; /* solhint-disable func-name-mixedcase */ -import "../UStbMinting.utils.sol"; -import "../../../contracts/ustb/IUStbMinting.sol"; +import "../USDtbMinting.utils.sol"; +import "../../../contracts/usdtb/IUSDtbMinting.sol"; import "../../../contracts/interfaces/ISingleAdminAccessControl.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; -import "../../../contracts/ustb/IUStbMinting.sol"; +import "../../../contracts/usdtb/IUSDtbMinting.sol"; -contract UStbMintingACLTest is UStbMintingUtils { +contract USDtbMintingACLTest is USDtbMintingUtils { function setUp() public override { super.setUp(); } function test_redeem_notRedeemer_revert() public { - (IUStbMinting.Order memory redeemOrder, IUStbMinting.Signature memory takerSignature2) = - redeem_setup(_ustbToMint, _stETHToDeposit, stETHToken, 1, false); + (IUSDtbMinting.Order memory redeemOrder, IUSDtbMinting.Signature memory takerSignature2) = + redeem_setup(_usdtbToMint, _stETHToDeposit, stETHToken, 1, false); vm.startPrank(minter); vm.expectRevert( @@ -26,12 +26,12 @@ contract UStbMintingACLTest is UStbMintingUtils { ) ) ); - UStbMintingContract.redeem(redeemOrder, takerSignature2); + USDtbMintingContract.redeem(redeemOrder, takerSignature2); } function test_fuzz_notMinter_cannot_mint(address nonMinter) public { - (IUStbMinting.Order memory mintOrder, IUStbMinting.Signature memory takerSignature, IUStbMinting.Route memory route) - = mint_setup(_ustbToMint, _stETHToDeposit, stETHToken, 1, false); + (IUSDtbMinting.Order memory mintOrder, IUSDtbMinting.Signature memory takerSignature, IUSDtbMinting.Route memory route) + = mint_setup(_usdtbToMint, _stETHToDeposit, stETHToken, 1, false); vm.assume(nonMinter != minter); vm.startPrank(nonMinter); @@ -42,10 +42,10 @@ contract UStbMintingACLTest is UStbMintingUtils { ) ) ); - UStbMintingContract.mint(mintOrder, route, takerSignature); + USDtbMintingContract.mint(mintOrder, route, takerSignature); assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit); - assertEq(ustbToken.balanceOf(beneficiary), 0); + assertEq(usdtbToken.balanceOf(beneficiary), 0); } function test_fuzz_nonOwner_cannot_add_supportedAsset_revert(address nonOwner) public { @@ -53,11 +53,11 @@ contract UStbMintingACLTest is UStbMintingUtils { address asset = address(20); vm.expectRevert(); vm.prank(nonOwner); - IUStbMinting.TokenConfig memory tokenConfig = IUStbMinting.TokenConfig( - IUStbMinting.TokenType.ASSET, true, MAX_USDE_MINT_AND_REDEEM_PER_BLOCK, MAX_USDE_MINT_AND_REDEEM_PER_BLOCK + IUSDtbMinting.TokenConfig memory tokenConfig = IUSDtbMinting.TokenConfig( + IUSDtbMinting.TokenType.ASSET, true, MAX_USDE_MINT_AND_REDEEM_PER_BLOCK, MAX_USDE_MINT_AND_REDEEM_PER_BLOCK ); - UStbMintingContract.addSupportedAsset(asset, tokenConfig); - assertFalse(UStbMintingContract.isSupportedAsset(asset)); + USDtbMintingContract.addSupportedAsset(asset, tokenConfig); + assertFalse(USDtbMintingContract.isSupportedAsset(asset)); } function test_fuzz_nonOwner_cannot_remove_supportedAsset_revert(address nonOwner) public { @@ -66,62 +66,62 @@ contract UStbMintingACLTest is UStbMintingUtils { vm.prank(owner); vm.expectEmit(true, false, false, false); emit AssetAdded(asset); - IUStbMinting.TokenConfig memory tokenConfig = IUStbMinting.TokenConfig( - IUStbMinting.TokenType.ASSET, true, MAX_USDE_MINT_AND_REDEEM_PER_BLOCK, MAX_USDE_MINT_AND_REDEEM_PER_BLOCK + IUSDtbMinting.TokenConfig memory tokenConfig = IUSDtbMinting.TokenConfig( + IUSDtbMinting.TokenType.ASSET, true, MAX_USDE_MINT_AND_REDEEM_PER_BLOCK, MAX_USDE_MINT_AND_REDEEM_PER_BLOCK ); - UStbMintingContract.addSupportedAsset(asset, tokenConfig); - assertTrue(UStbMintingContract.isSupportedAsset(asset)); + USDtbMintingContract.addSupportedAsset(asset, tokenConfig); + assertTrue(USDtbMintingContract.isSupportedAsset(asset)); vm.expectRevert(); vm.prank(nonOwner); - UStbMintingContract.removeSupportedAsset(asset); - assertTrue(UStbMintingContract.isSupportedAsset(asset)); + USDtbMintingContract.removeSupportedAsset(asset); + assertTrue(USDtbMintingContract.isSupportedAsset(asset)); } function test_collateralManager_canTransfer_custody() public { vm.startPrank(owner); - stETHToken.mint(1000, address(UStbMintingContract)); - UStbMintingContract.addCustodianAddress(beneficiary); - UStbMintingContract.grantRole(collateralManagerRole, minter); + stETHToken.mint(1000, address(USDtbMintingContract)); + USDtbMintingContract.addCustodianAddress(beneficiary); + USDtbMintingContract.grantRole(collateralManagerRole, minter); vm.stopPrank(); vm.prank(minter); vm.expectEmit(true, true, true, true); emit CustodyTransfer(beneficiary, address(stETHToken), 1000); - UStbMintingContract.transferToCustody(beneficiary, address(stETHToken), 1000); + USDtbMintingContract.transferToCustody(beneficiary, address(stETHToken), 1000); assertEq(stETHToken.balanceOf(beneficiary), 1000); - assertEq(stETHToken.balanceOf(address(UStbMintingContract)), 0); + assertEq(stETHToken.balanceOf(address(USDtbMintingContract)), 0); } function test_collateralManager_canTransferNative_custody() public { vm.startPrank(owner); - vm.deal(address(UStbMintingContract), 1000); - UStbMintingContract.addCustodianAddress(beneficiary); - UStbMintingContract.grantRole(collateralManagerRole, minter); + vm.deal(address(USDtbMintingContract), 1000); + USDtbMintingContract.addCustodianAddress(beneficiary); + USDtbMintingContract.grantRole(collateralManagerRole, minter); vm.stopPrank(); vm.prank(minter); vm.expectEmit(true, true, true, true); emit CustodyTransfer(beneficiary, address(NATIVE_TOKEN), 1000); - UStbMintingContract.transferToCustody(beneficiary, address(NATIVE_TOKEN), 1000); + USDtbMintingContract.transferToCustody(beneficiary, address(NATIVE_TOKEN), 1000); assertEq(beneficiary.balance, 1000); - assertEq(address(UStbMintingContract).balance, 0); + assertEq(address(USDtbMintingContract).balance, 0); } function test_collateralManager_cannotTransfer_zeroAddress() public { vm.startPrank(owner); - stETHToken.mint(1000, address(UStbMintingContract)); - UStbMintingContract.addCustodianAddress(beneficiary); - UStbMintingContract.grantRole(collateralManagerRole, minter); + stETHToken.mint(1000, address(USDtbMintingContract)); + USDtbMintingContract.addCustodianAddress(beneficiary); + USDtbMintingContract.grantRole(collateralManagerRole, minter); vm.stopPrank(); vm.prank(minter); - vm.expectRevert(IUStbMinting.InvalidAddress.selector); - UStbMintingContract.transferToCustody(address(0), address(stETHToken), 1000); + vm.expectRevert(IUSDtbMinting.InvalidAddress.selector); + USDtbMintingContract.transferToCustody(address(0), address(stETHToken), 1000); } function test_fuzz_nonCollateralManager_cannot_transferCustody_revert(address nonCollateralManager) public { vm.assume( nonCollateralManager != collateralManager && nonCollateralManager != owner && nonCollateralManager != address(0) ); - stETHToken.mint(1000, address(UStbMintingContract)); + stETHToken.mint(1000, address(USDtbMintingContract)); vm.expectRevert( bytes( @@ -134,7 +134,7 @@ contract UStbMintingACLTest is UStbMintingUtils { ) ); vm.prank(nonCollateralManager); - UStbMintingContract.transferToCustody(beneficiary, address(stETHToken), 1000); + USDtbMintingContract.transferToCustody(beneficiary, address(stETHToken), 1000); } /** @@ -143,22 +143,22 @@ contract UStbMintingACLTest is UStbMintingUtils { function test_gatekeeper_can_remove_minter() public { vm.prank(gatekeeper); - UStbMintingContract.removeMinterRole(minter); - assertFalse(UStbMintingContract.hasRole(minterRole, minter)); + USDtbMintingContract.removeMinterRole(minter); + assertFalse(USDtbMintingContract.hasRole(minterRole, minter)); } function test_gatekeeper_can_remove_redeemer() public { vm.prank(gatekeeper); - UStbMintingContract.removeRedeemerRole(redeemer); - assertFalse(UStbMintingContract.hasRole(redeemerRole, redeemer)); + USDtbMintingContract.removeRedeemerRole(redeemer); + assertFalse(USDtbMintingContract.hasRole(redeemerRole, redeemer)); } function test_gatekeeper_can_remove_collateral_manager() public { vm.prank(gatekeeper); - UStbMintingContract.removeCollateralManagerRole(collateralManager); - assertFalse(UStbMintingContract.hasRole(collateralManagerRole, collateralManager)); + USDtbMintingContract.removeCollateralManagerRole(collateralManager); + assertFalse(USDtbMintingContract.hasRole(collateralManagerRole, collateralManager)); } function test_fuzz_not_gatekeeper_cannot_remove_minter_revert(address notGatekeeper) public { @@ -174,8 +174,8 @@ contract UStbMintingACLTest is UStbMintingUtils { ) ) ); - UStbMintingContract.removeMinterRole(minter); - assertTrue(UStbMintingContract.hasRole(minterRole, minter)); + USDtbMintingContract.removeMinterRole(minter); + assertTrue(USDtbMintingContract.hasRole(minterRole, minter)); } function test_fuzz_not_gatekeeper_cannot_remove_redeemer_revert(address notGatekeeper) public { @@ -191,8 +191,8 @@ contract UStbMintingACLTest is UStbMintingUtils { ) ) ); - UStbMintingContract.removeRedeemerRole(redeemer); - assertTrue(UStbMintingContract.hasRole(redeemerRole, redeemer)); + USDtbMintingContract.removeRedeemerRole(redeemer); + assertTrue(USDtbMintingContract.hasRole(redeemerRole, redeemer)); } function test_fuzz_not_gatekeeper_cannot_remove_collateral_manager_revert(address notGatekeeper) public { @@ -208,8 +208,8 @@ contract UStbMintingACLTest is UStbMintingUtils { ) ) ); - UStbMintingContract.removeCollateralManagerRole(collateralManager); - assertTrue(UStbMintingContract.hasRole(collateralManagerRole, collateralManager)); + USDtbMintingContract.removeCollateralManagerRole(collateralManager); + assertTrue(USDtbMintingContract.hasRole(collateralManagerRole, collateralManager)); } function test_gatekeeper_cannot_add_minters_revert() public { @@ -221,8 +221,8 @@ contract UStbMintingACLTest is UStbMintingUtils { ) ) ); - UStbMintingContract.grantRole(minterRole, bob); - assertFalse(UStbMintingContract.hasRole(minterRole, bob), "Bob should lack the minter role"); + USDtbMintingContract.grantRole(minterRole, bob); + assertFalse(USDtbMintingContract.hasRole(minterRole, bob), "Bob should lack the minter role"); } function test_gatekeeper_cannot_add_collateral_managers_revert() public { @@ -234,26 +234,26 @@ contract UStbMintingACLTest is UStbMintingUtils { ) ) ); - UStbMintingContract.grantRole(collateralManagerRole, bob); - assertFalse(UStbMintingContract.hasRole(collateralManagerRole, bob), "Bob should lack the collateralManager role"); + USDtbMintingContract.grantRole(collateralManagerRole, bob); + assertFalse(USDtbMintingContract.hasRole(collateralManagerRole, bob), "Bob should lack the collateralManager role"); } function test_gatekeeper_can_disable_mintRedeem() public { vm.startPrank(gatekeeper); - UStbMintingContract.disableMintRedeem(); + USDtbMintingContract.disableMintRedeem(); - (IUStbMinting.Order memory order, IUStbMinting.Signature memory takerSignature, IUStbMinting.Route memory route) = - mint_setup(_ustbToMint, _stETHToDeposit, stETHToken, 1, false); + (IUSDtbMinting.Order memory order, IUSDtbMinting.Signature memory takerSignature, IUSDtbMinting.Route memory route) = + mint_setup(_usdtbToMint, _stETHToDeposit, stETHToken, 1, false); vm.prank(minter); vm.expectRevert(GlobalMaxMintPerBlockExceeded); - UStbMintingContract.mint(order, route, takerSignature); + USDtbMintingContract.mint(order, route, takerSignature); vm.prank(redeemer); vm.expectRevert(GlobalMaxRedeemPerBlockExceeded); - UStbMintingContract.redeem(order, takerSignature); + USDtbMintingContract.redeem(order, takerSignature); - (uint128 globalMaxMintPerBlock, uint128 globalMaxRedeemPerBlock) = UStbMintingContract.globalConfig(); + (uint128 globalMaxMintPerBlock, uint128 globalMaxRedeemPerBlock) = USDtbMintingContract.globalConfig(); assertEq(globalMaxMintPerBlock, 0, "Minting should be disabled"); assertEq(globalMaxRedeemPerBlock, 0, "Redeeming should be disabled"); @@ -282,7 +282,7 @@ contract UStbMintingACLTest is UStbMintingUtils { ) ) ); - UStbMintingContract.disableMintRedeem(); + USDtbMintingContract.disableMintRedeem(); assertTrue(tokenConfig[0].maxMintPerBlock > 0); assertTrue(tokenConfig[0].maxRedeemPerBlock > 0); @@ -293,42 +293,42 @@ contract UStbMintingACLTest is UStbMintingUtils { */ function test_admin_can_disable_mint(bool performCheckMint) public { vm.prank(owner); - UStbMintingContract.setMaxMintPerBlock(0, address(stETHToken)); + USDtbMintingContract.setMaxMintPerBlock(0, address(stETHToken)); if (performCheckMint) maxMint_perBlock_exceeded_revert(1e18); - (,, uint128 maxMintPerBlock,) = UStbMintingContract.tokenConfig(address(stETHToken)); + (,, uint128 maxMintPerBlock,) = USDtbMintingContract.tokenConfig(address(stETHToken)); assertEq(maxMintPerBlock, 0, "The minting should be disabled"); } function test_admin_can_disable_redeem(bool performCheckRedeem) public { vm.prank(owner); - UStbMintingContract.setMaxRedeemPerBlock(0, address(stETHToken)); + USDtbMintingContract.setMaxRedeemPerBlock(0, address(stETHToken)); if (performCheckRedeem) maxRedeem_perBlock_exceeded_revert(1e18); - (,,, uint128 maxRedeemPerBlock) = UStbMintingContract.tokenConfig(address(stETHToken)); + (,,, uint128 maxRedeemPerBlock) = USDtbMintingContract.tokenConfig(address(stETHToken)); assertEq(maxRedeemPerBlock, 0, "The redeem should be disabled"); } function test_admin_can_enable_mint() public { vm.startPrank(owner); - UStbMintingContract.setMaxMintPerBlock(0, address(stETHToken)); + USDtbMintingContract.setMaxMintPerBlock(0, address(stETHToken)); - (,, uint128 maxMintPerBlock1,) = UStbMintingContract.tokenConfig(address(stETHToken)); + (,, uint128 maxMintPerBlock1,) = USDtbMintingContract.tokenConfig(address(stETHToken)); assertEq(maxMintPerBlock1, 0, "The minting should be disabled"); // Re-enable the minting - UStbMintingContract.setMaxMintPerBlock(_maxMintPerBlock, address(stETHToken)); + USDtbMintingContract.setMaxMintPerBlock(_maxMintPerBlock, address(stETHToken)); vm.stopPrank(); executeMint(stETHToken); - (,, uint128 maxMintPerBlock2,) = UStbMintingContract.tokenConfig(address(stETHToken)); + (,, uint128 maxMintPerBlock2,) = USDtbMintingContract.tokenConfig(address(stETHToken)); assertTrue(maxMintPerBlock2 > 0, "The minting should be enabled"); } @@ -346,11 +346,11 @@ contract UStbMintingACLTest is UStbMintingUtils { ) ) ); - UStbMintingContract.setMaxMintPerBlock(_maxMintPerBlock, address(stETHToken)); + USDtbMintingContract.setMaxMintPerBlock(_maxMintPerBlock, address(stETHToken)); maxMint_perBlock_exceeded_revert(1e18); - (,, uint128 maxMintPerBlock,) = UStbMintingContract.tokenConfig(address(stETHToken)); + (,, uint128 maxMintPerBlock,) = USDtbMintingContract.tokenConfig(address(stETHToken)); assertEq(maxMintPerBlock, 0, "The minting should remain disabled"); } @@ -368,40 +368,40 @@ contract UStbMintingACLTest is UStbMintingUtils { ) ) ); - UStbMintingContract.setMaxRedeemPerBlock(_maxRedeemPerBlock, address(stETHToken)); + USDtbMintingContract.setMaxRedeemPerBlock(_maxRedeemPerBlock, address(stETHToken)); maxRedeem_perBlock_exceeded_revert(1e18); - (,,, uint128 maxRedeemPerBlock) = UStbMintingContract.tokenConfig(address(stETHToken)); + (,,, uint128 maxRedeemPerBlock) = USDtbMintingContract.tokenConfig(address(stETHToken)); assertEq(maxRedeemPerBlock, 0, "The redeeming should remain disabled"); } function test_admin_can_enable_redeem() public { vm.startPrank(owner); - UStbMintingContract.setMaxRedeemPerBlock(0, address(stETHToken)); + USDtbMintingContract.setMaxRedeemPerBlock(0, address(stETHToken)); - (,,, uint128 maxRedeemPerBlock1) = UStbMintingContract.tokenConfig(address(stETHToken)); + (,,, uint128 maxRedeemPerBlock1) = USDtbMintingContract.tokenConfig(address(stETHToken)); assertEq(maxRedeemPerBlock1, 0, "The redeem should be disabled"); // Re-enable the redeeming - UStbMintingContract.setMaxRedeemPerBlock(_maxRedeemPerBlock, address(stETHToken)); + USDtbMintingContract.setMaxRedeemPerBlock(_maxRedeemPerBlock, address(stETHToken)); vm.stopPrank(); executeRedeem(stETHToken); - (,,, uint128 maxRedeemPerBlock2) = UStbMintingContract.tokenConfig(address(stETHToken)); + (,,, uint128 maxRedeemPerBlock2) = USDtbMintingContract.tokenConfig(address(stETHToken)); assertTrue(maxRedeemPerBlock2 > 0, "The redeeming should be enabled"); } function test_admin_can_add_minter() public { vm.startPrank(owner); - UStbMintingContract.grantRole(minterRole, bob); + USDtbMintingContract.grantRole(minterRole, bob); - assertTrue(UStbMintingContract.hasRole(minterRole, bob), "Bob should have the minter role"); + assertTrue(USDtbMintingContract.hasRole(minterRole, bob), "Bob should have the minter role"); vm.stopPrank(); } @@ -409,18 +409,18 @@ contract UStbMintingACLTest is UStbMintingUtils { test_admin_can_add_minter(); vm.startPrank(owner); - UStbMintingContract.revokeRole(minterRole, bob); + USDtbMintingContract.revokeRole(minterRole, bob); - assertFalse(UStbMintingContract.hasRole(minterRole, bob), "Bob should no longer have the minter role"); + assertFalse(USDtbMintingContract.hasRole(minterRole, bob), "Bob should no longer have the minter role"); vm.stopPrank(); } function test_admin_can_add_gatekeeper() public { vm.startPrank(owner); - UStbMintingContract.grantRole(gatekeeperRole, bob); + USDtbMintingContract.grantRole(gatekeeperRole, bob); - assertTrue(UStbMintingContract.hasRole(gatekeeperRole, bob), "Bob should have the gatekeeper role"); + assertTrue(USDtbMintingContract.hasRole(gatekeeperRole, bob), "Bob should have the gatekeeper role"); vm.stopPrank(); } @@ -428,9 +428,9 @@ contract UStbMintingACLTest is UStbMintingUtils { test_admin_can_add_gatekeeper(); vm.startPrank(owner); - UStbMintingContract.revokeRole(gatekeeperRole, bob); + USDtbMintingContract.revokeRole(gatekeeperRole, bob); - assertFalse(UStbMintingContract.hasRole(gatekeeperRole, bob), "Bob should no longer have the gatekeeper role"); + assertFalse(USDtbMintingContract.hasRole(gatekeeperRole, bob), "Bob should no longer have the gatekeeper role"); vm.stopPrank(); } @@ -447,9 +447,9 @@ contract UStbMintingACLTest is UStbMintingUtils { ) ) ); - UStbMintingContract.revokeRole(minterRole, bob); + USDtbMintingContract.revokeRole(minterRole, bob); - assertTrue(UStbMintingContract.hasRole(minterRole, bob), "Bob should maintain the minter role"); + assertTrue(USDtbMintingContract.hasRole(minterRole, bob), "Bob should maintain the minter role"); vm.stopPrank(); } @@ -465,9 +465,9 @@ contract UStbMintingACLTest is UStbMintingUtils { ) ) ); - UStbMintingContract.revokeRole(gatekeeperRole, bob); + USDtbMintingContract.revokeRole(gatekeeperRole, bob); - assertTrue(UStbMintingContract.hasRole(gatekeeperRole, bob), "Bob should maintain the gatekeeper role"); + assertTrue(USDtbMintingContract.hasRole(gatekeeperRole, bob), "Bob should maintain the gatekeeper role"); vm.stopPrank(); } @@ -482,9 +482,9 @@ contract UStbMintingACLTest is UStbMintingUtils { ) ) ); - UStbMintingContract.grantRole(minterRole, bob); + USDtbMintingContract.grantRole(minterRole, bob); - assertFalse(UStbMintingContract.hasRole(minterRole, bob), "Bob should lack the minter role"); + assertFalse(USDtbMintingContract.hasRole(minterRole, bob), "Bob should lack the minter role"); vm.stopPrank(); } @@ -498,29 +498,29 @@ contract UStbMintingACLTest is UStbMintingUtils { ) ) ); - UStbMintingContract.grantRole(gatekeeperRole, bob); + USDtbMintingContract.grantRole(gatekeeperRole, bob); - assertFalse(UStbMintingContract.hasRole(gatekeeperRole, bob), "Bob should lack the gatekeeper role"); + assertFalse(USDtbMintingContract.hasRole(gatekeeperRole, bob), "Bob should lack the gatekeeper role"); vm.stopPrank(); } function test_base_transferAdmin() public { vm.prank(owner); - UStbMintingContract.transferAdmin(newOwner); - assertTrue(UStbMintingContract.hasRole(adminRole, owner)); - assertFalse(UStbMintingContract.hasRole(adminRole, newOwner)); + USDtbMintingContract.transferAdmin(newOwner); + assertTrue(USDtbMintingContract.hasRole(adminRole, owner)); + assertFalse(USDtbMintingContract.hasRole(adminRole, newOwner)); vm.prank(newOwner); - UStbMintingContract.acceptAdmin(); - assertFalse(UStbMintingContract.hasRole(adminRole, owner)); - assertTrue(UStbMintingContract.hasRole(adminRole, newOwner)); + USDtbMintingContract.acceptAdmin(); + assertFalse(USDtbMintingContract.hasRole(adminRole, owner)); + assertTrue(USDtbMintingContract.hasRole(adminRole, newOwner)); } function test_transferAdmin_notAdmin() public { vm.startPrank(randomer); vm.expectRevert(); - UStbMintingContract.transferAdmin(randomer); + USDtbMintingContract.transferAdmin(randomer); } function test_grantRole_AdminRoleExternally() public { @@ -528,7 +528,7 @@ contract UStbMintingACLTest is UStbMintingUtils { vm.expectRevert( "AccessControl: account 0xc91041eae7bf78e1040f4abd7b29908651f45546 is missing role 0x0000000000000000000000000000000000000000000000000000000000000000" ); - UStbMintingContract.grantRole(adminRole, randomer); + USDtbMintingContract.grantRole(adminRole, randomer); vm.stopPrank(); } @@ -537,209 +537,209 @@ contract UStbMintingACLTest is UStbMintingUtils { vm.expectRevert( "AccessControl: account 0xc91041eae7bf78e1040f4abd7b29908651f45546 is missing role 0x0000000000000000000000000000000000000000000000000000000000000000" ); - UStbMintingContract.revokeRole(adminRole, owner); + USDtbMintingContract.revokeRole(adminRole, owner); } function test_revokeRole_AdminRole() public { vm.startPrank(owner); vm.expectRevert(); - UStbMintingContract.revokeRole(adminRole, owner); + USDtbMintingContract.revokeRole(adminRole, owner); } function test_renounceRole_notAdmin() public { vm.startPrank(randomer); vm.expectRevert(InvalidAdminChange); - UStbMintingContract.renounceRole(adminRole, owner); + USDtbMintingContract.renounceRole(adminRole, owner); } function test_renounceRole_AdminRole() public { vm.prank(owner); vm.expectRevert(InvalidAdminChange); - UStbMintingContract.renounceRole(adminRole, owner); + USDtbMintingContract.renounceRole(adminRole, owner); } function test_revoke_AdminRole() public { vm.prank(owner); vm.expectRevert(InvalidAdminChange); - UStbMintingContract.revokeRole(adminRole, owner); + USDtbMintingContract.revokeRole(adminRole, owner); } function test_grantRole_nonAdminRole() public { vm.prank(owner); - UStbMintingContract.grantRole(minterRole, randomer); - assertTrue(UStbMintingContract.hasRole(minterRole, randomer)); + USDtbMintingContract.grantRole(minterRole, randomer); + assertTrue(USDtbMintingContract.hasRole(minterRole, randomer)); } function test_revokeRole_nonAdminRole() public { vm.startPrank(owner); - UStbMintingContract.grantRole(minterRole, randomer); - UStbMintingContract.revokeRole(minterRole, randomer); + USDtbMintingContract.grantRole(minterRole, randomer); + USDtbMintingContract.revokeRole(minterRole, randomer); vm.stopPrank(); - assertFalse(UStbMintingContract.hasRole(minterRole, randomer)); + assertFalse(USDtbMintingContract.hasRole(minterRole, randomer)); } function test_renounceRole_nonAdminRole() public { vm.prank(owner); - UStbMintingContract.grantRole(minterRole, randomer); + USDtbMintingContract.grantRole(minterRole, randomer); vm.prank(randomer); - UStbMintingContract.renounceRole(minterRole, randomer); - assertFalse(UStbMintingContract.hasRole(minterRole, randomer)); + USDtbMintingContract.renounceRole(minterRole, randomer); + assertFalse(USDtbMintingContract.hasRole(minterRole, randomer)); } function testCanRepeatedlyTransferAdmin() public { vm.startPrank(owner); - UStbMintingContract.transferAdmin(newOwner); - UStbMintingContract.transferAdmin(randomer); + USDtbMintingContract.transferAdmin(newOwner); + USDtbMintingContract.transferAdmin(randomer); vm.stopPrank(); } function test_renounceRole_forDifferentAccount() public { vm.prank(randomer); vm.expectRevert("AccessControl: can only renounce roles for self"); - UStbMintingContract.renounceRole(minterRole, owner); + USDtbMintingContract.renounceRole(minterRole, owner); } function testCancelTransferAdmin() public { vm.startPrank(owner); - UStbMintingContract.transferAdmin(newOwner); - UStbMintingContract.transferAdmin(address(0)); + USDtbMintingContract.transferAdmin(newOwner); + USDtbMintingContract.transferAdmin(address(0)); vm.stopPrank(); - assertTrue(UStbMintingContract.hasRole(adminRole, owner)); - assertFalse(UStbMintingContract.hasRole(adminRole, address(0))); - assertFalse(UStbMintingContract.hasRole(adminRole, newOwner)); + assertTrue(USDtbMintingContract.hasRole(adminRole, owner)); + assertFalse(USDtbMintingContract.hasRole(adminRole, address(0))); + assertFalse(USDtbMintingContract.hasRole(adminRole, newOwner)); } function test_admin_cannot_transfer_self() public { vm.startPrank(owner); vm.expectRevert(InvalidAdminChange); - UStbMintingContract.transferAdmin(owner); + USDtbMintingContract.transferAdmin(owner); vm.stopPrank(); - assertTrue(UStbMintingContract.hasRole(adminRole, owner)); + assertTrue(USDtbMintingContract.hasRole(adminRole, owner)); } function testAdminCanCancelTransfer() public { vm.startPrank(owner); - UStbMintingContract.transferAdmin(newOwner); - UStbMintingContract.transferAdmin(address(0)); + USDtbMintingContract.transferAdmin(newOwner); + USDtbMintingContract.transferAdmin(address(0)); vm.stopPrank(); vm.prank(newOwner); vm.expectRevert(ISingleAdminAccessControl.NotPendingAdmin.selector); - UStbMintingContract.acceptAdmin(); + USDtbMintingContract.acceptAdmin(); - assertTrue(UStbMintingContract.hasRole(adminRole, owner)); - assertFalse(UStbMintingContract.hasRole(adminRole, address(0))); - assertFalse(UStbMintingContract.hasRole(adminRole, newOwner)); + assertTrue(USDtbMintingContract.hasRole(adminRole, owner)); + assertFalse(USDtbMintingContract.hasRole(adminRole, address(0))); + assertFalse(USDtbMintingContract.hasRole(adminRole, newOwner)); } function testOwnershipCannotBeRenounced() public { vm.startPrank(owner); vm.expectRevert(ISingleAdminAccessControl.InvalidAdminChange.selector); - UStbMintingContract.renounceRole(adminRole, owner); + USDtbMintingContract.renounceRole(adminRole, owner); vm.expectRevert(ISingleAdminAccessControl.InvalidAdminChange.selector); - UStbMintingContract.revokeRole(adminRole, owner); + USDtbMintingContract.revokeRole(adminRole, owner); vm.stopPrank(); - assertEq(UStbMintingContract.owner(), owner); - assertTrue(UStbMintingContract.hasRole(adminRole, owner)); + assertEq(USDtbMintingContract.owner(), owner); + assertTrue(USDtbMintingContract.hasRole(adminRole, owner)); } function testOwnershipTransferRequiresTwoSteps() public { vm.prank(owner); - UStbMintingContract.transferAdmin(newOwner); - assertEq(UStbMintingContract.owner(), owner); - assertTrue(UStbMintingContract.hasRole(adminRole, owner)); - assertNotEq(UStbMintingContract.owner(), newOwner); - assertFalse(UStbMintingContract.hasRole(adminRole, newOwner)); + USDtbMintingContract.transferAdmin(newOwner); + assertEq(USDtbMintingContract.owner(), owner); + assertTrue(USDtbMintingContract.hasRole(adminRole, owner)); + assertNotEq(USDtbMintingContract.owner(), newOwner); + assertFalse(USDtbMintingContract.hasRole(adminRole, newOwner)); } function testCanTransferOwnership() public { vm.prank(owner); - UStbMintingContract.transferAdmin(newOwner); + USDtbMintingContract.transferAdmin(newOwner); vm.prank(newOwner); - UStbMintingContract.acceptAdmin(); - assertTrue(UStbMintingContract.hasRole(adminRole, newOwner)); - assertFalse(UStbMintingContract.hasRole(adminRole, owner)); + USDtbMintingContract.acceptAdmin(); + assertTrue(USDtbMintingContract.hasRole(adminRole, newOwner)); + assertFalse(USDtbMintingContract.hasRole(adminRole, owner)); } function testNewOwnerCanPerformOwnerActions() public { vm.prank(owner); - UStbMintingContract.transferAdmin(newOwner); + USDtbMintingContract.transferAdmin(newOwner); vm.startPrank(newOwner); - UStbMintingContract.acceptAdmin(); - UStbMintingContract.grantRole(gatekeeperRole, bob); + USDtbMintingContract.acceptAdmin(); + USDtbMintingContract.grantRole(gatekeeperRole, bob); vm.stopPrank(); - assertTrue(UStbMintingContract.hasRole(adminRole, newOwner)); - assertTrue(UStbMintingContract.hasRole(gatekeeperRole, bob)); + assertTrue(USDtbMintingContract.hasRole(adminRole, newOwner)); + assertTrue(USDtbMintingContract.hasRole(gatekeeperRole, bob)); } function testOldOwnerCantPerformOwnerActions() public { vm.prank(owner); - UStbMintingContract.transferAdmin(newOwner); + USDtbMintingContract.transferAdmin(newOwner); vm.prank(newOwner); - UStbMintingContract.acceptAdmin(); - assertTrue(UStbMintingContract.hasRole(adminRole, newOwner)); - assertFalse(UStbMintingContract.hasRole(adminRole, owner)); + USDtbMintingContract.acceptAdmin(); + assertTrue(USDtbMintingContract.hasRole(adminRole, newOwner)); + assertFalse(USDtbMintingContract.hasRole(adminRole, owner)); vm.prank(owner); vm.expectRevert( "AccessControl: account 0xe05fcc23807536bee418f142d19fa0d21bb0cff7 is missing role 0x0000000000000000000000000000000000000000000000000000000000000000" ); - UStbMintingContract.grantRole(gatekeeperRole, bob); - assertFalse(UStbMintingContract.hasRole(gatekeeperRole, bob)); + USDtbMintingContract.grantRole(gatekeeperRole, bob); + assertFalse(USDtbMintingContract.hasRole(gatekeeperRole, bob)); } function testOldOwnerCantTransferOwnership() public { vm.prank(owner); - UStbMintingContract.transferAdmin(newOwner); + USDtbMintingContract.transferAdmin(newOwner); vm.prank(newOwner); - UStbMintingContract.acceptAdmin(); - assertTrue(UStbMintingContract.hasRole(adminRole, newOwner)); - assertFalse(UStbMintingContract.hasRole(adminRole, owner)); + USDtbMintingContract.acceptAdmin(); + assertTrue(USDtbMintingContract.hasRole(adminRole, newOwner)); + assertFalse(USDtbMintingContract.hasRole(adminRole, owner)); vm.prank(owner); vm.expectRevert( "AccessControl: account 0xe05fcc23807536bee418f142d19fa0d21bb0cff7 is missing role 0x0000000000000000000000000000000000000000000000000000000000000000" ); - UStbMintingContract.transferAdmin(bob); - assertFalse(UStbMintingContract.hasRole(adminRole, bob)); + USDtbMintingContract.transferAdmin(bob); + assertFalse(USDtbMintingContract.hasRole(adminRole, bob)); } function testNonAdminCanRenounceRoles() public { vm.prank(owner); - UStbMintingContract.grantRole(gatekeeperRole, bob); - assertTrue(UStbMintingContract.hasRole(gatekeeperRole, bob)); + USDtbMintingContract.grantRole(gatekeeperRole, bob); + assertTrue(USDtbMintingContract.hasRole(gatekeeperRole, bob)); vm.prank(bob); - UStbMintingContract.renounceRole(gatekeeperRole, bob); - assertFalse(UStbMintingContract.hasRole(gatekeeperRole, bob)); + USDtbMintingContract.renounceRole(gatekeeperRole, bob); + assertFalse(USDtbMintingContract.hasRole(gatekeeperRole, bob)); } function testCorrectInitConfig() public { - UStbMinting ustbMinting2 = new UStbMinting(assets, tokenConfig, globalConfig, custodians, randomer); + USDtbMinting usdtbMinting2 = new USDtbMinting(assets, tokenConfig, globalConfig, custodians, randomer); - assertFalse(ustbMinting2.hasRole(adminRole, owner)); - assertNotEq(ustbMinting2.owner(), owner); - assertTrue(ustbMinting2.hasRole(adminRole, randomer)); - assertEq(ustbMinting2.owner(), randomer); + assertFalse(usdtbMinting2.hasRole(adminRole, owner)); + assertNotEq(usdtbMinting2.owner(), owner); + assertTrue(usdtbMinting2.hasRole(adminRole, randomer)); + assertEq(usdtbMinting2.owner(), randomer); } function testInitConfigBlockLimitMismatch() public { // define zero token tokenConfig - IUStbMinting.TokenConfig[] memory zeroTokenConfig = new IUStbMinting.TokenConfig[](6); + IUSDtbMinting.TokenConfig[] memory zeroTokenConfig = new IUSDtbMinting.TokenConfig[](6); // 6 zero configs for (uint256 i = 0; i < 6; i++) { - zeroTokenConfig[i] = IUStbMinting.TokenConfig(IUStbMinting.TokenType.ASSET, true, 0, 0); + zeroTokenConfig[i] = IUSDtbMinting.TokenConfig(IUSDtbMinting.TokenType.ASSET, true, 0, 0); } vm.expectRevert(InvalidAmount); - new UStbMinting(assets, zeroTokenConfig, globalConfig, custodians, randomer); + new USDtbMinting(assets, zeroTokenConfig, globalConfig, custodians, randomer); // mismatched redeem configuration versus assets - IUStbMinting.TokenConfig[] memory invalidRedeemTokenConfig = new IUStbMinting.TokenConfig[](1); - invalidRedeemTokenConfig[0] = IUStbMinting.TokenConfig(IUStbMinting.TokenType.ASSET, true, 1, 1); + IUSDtbMinting.TokenConfig[] memory invalidRedeemTokenConfig = new IUSDtbMinting.TokenConfig[](1); + invalidRedeemTokenConfig[0] = IUSDtbMinting.TokenConfig(IUSDtbMinting.TokenType.ASSET, true, 1, 1); vm.expectRevert(InvalidAssetAddress); - new UStbMinting(assets, invalidRedeemTokenConfig, globalConfig, custodians, randomer); + new USDtbMinting(assets, invalidRedeemTokenConfig, globalConfig, custodians, randomer); // correct config - new UStbMinting(assets, tokenConfig, globalConfig, custodians, randomer); + new USDtbMinting(assets, tokenConfig, globalConfig, custodians, randomer); } } diff --git a/test/foundry/test/USDtbMinting.Delegate.t.sol b/test/foundry/test/USDtbMinting.Delegate.t.sol new file mode 100644 index 0000000..6d5c084 --- /dev/null +++ b/test/foundry/test/USDtbMinting.Delegate.t.sol @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "../USDtbMinting.utils.sol"; + +contract USDtbMintingDelegateTest is USDtbMintingUtils { + function setUp() public override { + super.setUp(); + } + + function testDelegateSuccessfulMint() public { + (IUSDtbMinting.Order memory order,, IUSDtbMinting.Route memory route) = + mint_setup(_usdtbToMint, _stETHToDeposit, stETHToken, 1, false); + + // request delegation + vm.prank(benefactor); + vm.expectEmit(); + emit DelegatedSignerInitiated(trader2, benefactor); + USDtbMintingContract.setDelegatedSigner(trader2); + + assertEq( + uint256(USDtbMintingContract.delegatedSigner(trader2, benefactor)), + uint256(IUSDtbMinting.DelegatedSignerStatus.PENDING), + "The delegation status should be pending" + ); + + bytes32 digest1 = USDtbMintingContract.hashOrder(order); + + // accept delegation + vm.prank(trader2); + vm.expectEmit(); + emit DelegatedSignerAdded(trader2, benefactor); + USDtbMintingContract.confirmDelegatedSigner(benefactor); + + assertEq( + uint256(USDtbMintingContract.delegatedSigner(trader2, benefactor)), + uint256(IUSDtbMinting.DelegatedSignerStatus.ACCEPTED), + "The delegation status should be accepted" + ); + + IUSDtbMinting.Signature memory trader2Sig = signOrder(trader2PrivateKey, digest1, IUSDtbMinting.SignatureType.EIP712); + + assertEq( + stETHToken.balanceOf(address(USDtbMintingContract)), 0, "Mismatch in Minting contract stETH balance before mint" + ); + assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit, "Mismatch in benefactor stETH balance before mint"); + assertEq(usdtbToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary USDtb balance before mint"); + + vm.prank(minter); + USDtbMintingContract.mint(order, route, trader2Sig); + + assertEq( + stETHToken.balanceOf(address(USDtbMintingContract)), + _stETHToDeposit, + "Mismatch in Minting contract stETH balance after mint" + ); + assertEq(stETHToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary stETH balance after mint"); + assertEq(usdtbToken.balanceOf(beneficiary), _usdtbToMint, "Mismatch in beneficiary USDtb balance after mint"); + } + + function testDelegateFailureMint() public { + (IUSDtbMinting.Order memory order,, IUSDtbMinting.Route memory route) = + mint_setup(_usdtbToMint, _stETHToDeposit, stETHToken, 1, false); + + bytes32 digest1 = USDtbMintingContract.hashOrder(order); + + // accept delegation + vm.prank(trader2); + vm.expectRevert(IUSDtbMinting.DelegationNotInitiated.selector); + USDtbMintingContract.confirmDelegatedSigner(benefactor); + + vm.prank(trader2); + IUSDtbMinting.Signature memory trader2Sig = signOrder(trader2PrivateKey, digest1, IUSDtbMinting.SignatureType.EIP712); + + assertEq( + stETHToken.balanceOf(address(USDtbMintingContract)), 0, "Mismatch in Minting contract stETH balance before mint" + ); + assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit, "Mismatch in benefactor stETH balance before mint"); + assertEq(usdtbToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary USDtb balance before mint"); + + // assert that the delegation is rejected + assertEq( + uint256(USDtbMintingContract.delegatedSigner(minter, trader2)), + uint256(IUSDtbMinting.DelegatedSignerStatus.REJECTED), + "The delegation status should be rejected" + ); + + vm.prank(minter); + vm.expectRevert(InvalidEIP712Signature); + USDtbMintingContract.mint(order, route, trader2Sig); + + assertEq( + stETHToken.balanceOf(address(USDtbMintingContract)), 0, "Mismatch in Minting contract stETH balance after mint" + ); + assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit, "Mismatch in beneficiary stETH balance after mint"); + assertEq(usdtbToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary USDtb balance after mint"); + } + + function testDelegateSuccessfulRedeem() public { + (IUSDtbMinting.Order memory order,) = redeem_setup(_usdtbToMint, _stETHToDeposit, stETHToken, 1, false); + + // request delegation + vm.prank(beneficiary); + vm.expectEmit(); + emit DelegatedSignerInitiated(trader2, beneficiary); + USDtbMintingContract.setDelegatedSigner(trader2); + + assertEq( + uint256(USDtbMintingContract.delegatedSigner(trader2, beneficiary)), + uint256(IUSDtbMinting.DelegatedSignerStatus.PENDING), + "The delegation status should be pending" + ); + + bytes32 digest1 = USDtbMintingContract.hashOrder(order); + + // accept delegation + vm.prank(trader2); + vm.expectEmit(); + emit DelegatedSignerAdded(trader2, beneficiary); + USDtbMintingContract.confirmDelegatedSigner(beneficiary); + + assertEq( + uint256(USDtbMintingContract.delegatedSigner(trader2, beneficiary)), + uint256(IUSDtbMinting.DelegatedSignerStatus.ACCEPTED), + "The delegation status should be accepted" + ); + + IUSDtbMinting.Signature memory trader2Sig = signOrder(trader2PrivateKey, digest1, IUSDtbMinting.SignatureType.EIP712); + + assertEq( + stETHToken.balanceOf(address(USDtbMintingContract)), + _stETHToDeposit, + "Mismatch in Minting contract stETH balance before mint" + ); + assertEq(stETHToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary stETH balance before mint"); + assertEq(usdtbToken.balanceOf(beneficiary), _usdtbToMint, "Mismatch in beneficiary USDtb balance before mint"); + + vm.prank(redeemer); + USDtbMintingContract.redeem(order, trader2Sig); + + assertEq( + stETHToken.balanceOf(address(USDtbMintingContract)), 0, "Mismatch in Minting contract stETH balance after mint" + ); + assertEq(stETHToken.balanceOf(beneficiary), _stETHToDeposit, "Mismatch in beneficiary stETH balance after mint"); + assertEq(usdtbToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary USDtb balance after mint"); + } + + function testDelegateFailureRedeem() public { + (IUSDtbMinting.Order memory order,) = redeem_setup(_usdtbToMint, _stETHToDeposit, stETHToken, 1, false); + + bytes32 digest1 = USDtbMintingContract.hashOrder(order); + vm.prank(trader2); + IUSDtbMinting.Signature memory trader2Sig = signOrder(trader2PrivateKey, digest1, IUSDtbMinting.SignatureType.EIP712); + + assertEq( + stETHToken.balanceOf(address(USDtbMintingContract)), + _stETHToDeposit, + "Mismatch in Minting contract stETH balance before mint" + ); + assertEq(stETHToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary stETH balance before mint"); + assertEq(usdtbToken.balanceOf(beneficiary), _usdtbToMint, "Mismatch in beneficiary USDtb balance before mint"); + + // assert that the delegation is rejected + assertEq( + uint256(USDtbMintingContract.delegatedSigner(redeemer, trader2)), + uint256(IUSDtbMinting.DelegatedSignerStatus.REJECTED), + "The delegation status should be rejected" + ); + + vm.prank(redeemer); + vm.expectRevert(InvalidEIP712Signature); + USDtbMintingContract.redeem(order, trader2Sig); + + assertEq( + stETHToken.balanceOf(address(USDtbMintingContract)), + _stETHToDeposit, + "Mismatch in Minting contract stETH balance after mint" + ); + assertEq(stETHToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary stETH balance after mint"); + assertEq(usdtbToken.balanceOf(beneficiary), _usdtbToMint, "Mismatch in beneficiary USDtb balance after mint"); + } + + function testCanUndelegate() public { + (IUSDtbMinting.Order memory order,, IUSDtbMinting.Route memory route) = + mint_setup(_usdtbToMint, _stETHToDeposit, stETHToken, 1, false); + + // delegate request + vm.prank(benefactor); + vm.expectEmit(); + emit DelegatedSignerInitiated(trader2, benefactor); + USDtbMintingContract.setDelegatedSigner(trader2); + + assertEq( + uint256(USDtbMintingContract.delegatedSigner(trader2, benefactor)), + uint256(IUSDtbMinting.DelegatedSignerStatus.PENDING), + "The delegation status should be pending" + ); + + // accept the delegation + vm.prank(trader2); + vm.expectEmit(); + emit DelegatedSignerAdded(trader2, benefactor); + USDtbMintingContract.confirmDelegatedSigner(benefactor); + + assertEq( + uint256(USDtbMintingContract.delegatedSigner(trader2, benefactor)), + uint256(IUSDtbMinting.DelegatedSignerStatus.ACCEPTED), + "The delegation status should be accepted" + ); + + // remove the delegation + vm.prank(benefactor); + vm.expectEmit(); + emit DelegatedSignerRemoved(trader2, benefactor); + USDtbMintingContract.removeDelegatedSigner(trader2); + + assertEq( + uint256(USDtbMintingContract.delegatedSigner(trader2, benefactor)), + uint256(IUSDtbMinting.DelegatedSignerStatus.REJECTED), + "The delegation status should be accepted" + ); + + bytes32 digest1 = USDtbMintingContract.hashOrder(order); + vm.prank(trader2); + IUSDtbMinting.Signature memory trader2Sig = signOrder(trader2PrivateKey, digest1, IUSDtbMinting.SignatureType.EIP712); + + assertEq( + stETHToken.balanceOf(address(USDtbMintingContract)), 0, "Mismatch in Minting contract stETH balance before mint" + ); + assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit, "Mismatch in benefactor stETH balance before mint"); + assertEq(usdtbToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary USDtb balance before mint"); + + vm.prank(minter); + vm.expectRevert(InvalidEIP712Signature); + USDtbMintingContract.mint(order, route, trader2Sig); + + assertEq( + stETHToken.balanceOf(address(USDtbMintingContract)), 0, "Mismatch in Minting contract stETH balance after mint" + ); + assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit, "Mismatch in beneficiary stETH balance after mint"); + assertEq(usdtbToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary USDtb balance after mint"); + } +} diff --git a/test/foundry/test/UStbMinting.SmartContractSigning.t.sol b/test/foundry/test/USDtbMinting.SmartContractSigning.t.sol similarity index 58% rename from test/foundry/test/UStbMinting.SmartContractSigning.t.sol rename to test/foundry/test/USDtbMinting.SmartContractSigning.t.sol index b73f2b4..909c861 100644 --- a/test/foundry/test/UStbMinting.SmartContractSigning.t.sol +++ b/test/foundry/test/USDtbMinting.SmartContractSigning.t.sol @@ -3,17 +3,17 @@ pragma solidity ^0.8.20; /* solhint-disable func-name-mixedcase */ -import "../UStbMinting.utils.sol"; +import "../USDtbMinting.utils.sol"; -contract UStbMintingContractSigningTest is UStbMintingUtils { +contract USDtbMintingContractSigningTest is USDtbMintingUtils { function setUp() public override { super.setUp(); } function test_multi_sig_eip_1271_mint() public { - IUStbMinting.Order memory order = createOrder(); - IUStbMinting.Route memory route = createRoute(); - bytes32 digest1 = UStbMintingContract.hashOrder(order); + IUSDtbMinting.Order memory order = createOrder(); + IUSDtbMinting.Route memory route = createRoute(); + bytes32 digest1 = USDtbMintingContract.hashOrder(order); approveERC20(owner); @@ -21,70 +21,70 @@ contract UStbMintingContractSigningTest is UStbMintingUtils { vm.prank(minter); vm.expectRevert(InvalidEIP1271Signature); - UStbMintingContract.mint( - order, route, signOrder(smartContractSigner1PrivateKey, digest1, IUStbMinting.SignatureType.EIP1271) + USDtbMintingContract.mint( + order, route, signOrder(smartContractSigner1PrivateKey, digest1, IUSDtbMinting.SignatureType.EIP1271) ); submitSecondSignature(digest1); vm.prank(minter); - UStbMintingContract.mint( - order, route, signOrder(smartContractSigner2PrivateKey, digest1, IUStbMinting.SignatureType.EIP1271) + USDtbMintingContract.mint( + order, route, signOrder(smartContractSigner2PrivateKey, digest1, IUSDtbMinting.SignatureType.EIP1271) ); assertEq(stETHToken.balanceOf(address(MultiSigWalletBenefactor)), 0); - assertEq(stETHToken.balanceOf(address(UStbMintingContract)), _stETHToDeposit); - assertEq(ustbToken.balanceOf(address(MultiSigWalletBenefactor)), _ustbToMint); + assertEq(stETHToken.balanceOf(address(USDtbMintingContract)), _stETHToDeposit); + assertEq(usdtbToken.balanceOf(address(MultiSigWalletBenefactor)), _usdtbToMint); } - function createOrder() internal view returns (IUStbMinting.Order memory) { - return IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.MINT, + function createOrder() internal view returns (IUSDtbMinting.Order memory) { + return IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.MINT, order_id: generateRandomOrderId(), expiry: uint120(block.timestamp + 10 minutes), nonce: 1, benefactor: mockMultiSigWallet, beneficiary: mockMultiSigWallet, collateral_asset: address(stETHToken), - ustb_amount: _ustbToMint, + usdtb_amount: _usdtbToMint, collateral_amount: _stETHToDeposit }); } - function createRoute() internal view returns (IUStbMinting.Route memory) { + function createRoute() internal view returns (IUSDtbMinting.Route memory) { address[] memory targets = new address[](1); - targets[0] = address(UStbMintingContract); + targets[0] = address(USDtbMintingContract); uint128[] memory ratios = new uint128[](1); ratios[0] = 10_000; - return IUStbMinting.Route({addresses: targets, ratios: ratios}); + return IUSDtbMinting.Route({addresses: targets, ratios: ratios}); } function signMessage(uint256 privateKey) internal view returns (bytes memory) { bytes32 messageHash = - keccak256(abi.encodePacked(address(stETHToken), address(UStbMintingContract), _stETHToDeposit)); + keccak256(abi.encodePacked(address(stETHToken), address(USDtbMintingContract), _stETHToDeposit)); (uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, messageHash); return _packRsv(r, s, v); } function approveERC20(address approver) internal { vm.prank(approver); - MultiSigWalletBenefactor.approveERC20(address(stETHToken), address(UStbMintingContract), _stETHToDeposit); + MultiSigWalletBenefactor.approveERC20(address(stETHToken), address(USDtbMintingContract), _stETHToDeposit); } function submitFirstSignature(bytes32 digest) internal { vm.startPrank(smartContractSigner1); - IUStbMinting.Signature memory signature = - signOrder(smartContractSigner1PrivateKey, digest, IUStbMinting.SignatureType.EIP1271); + IUSDtbMinting.Signature memory signature = + signOrder(smartContractSigner1PrivateKey, digest, IUSDtbMinting.SignatureType.EIP1271); MultiSigWalletBenefactor.submitSignature(digest, signature.signature_bytes); vm.stopPrank(); } function submitSecondSignature(bytes32 digest) internal { vm.startPrank(smartContractSigner2); - IUStbMinting.Signature memory signature = - signOrder(smartContractSigner2PrivateKey, digest, IUStbMinting.SignatureType.EIP1271); + IUSDtbMinting.Signature memory signature = + signOrder(smartContractSigner2PrivateKey, digest, IUSDtbMinting.SignatureType.EIP1271); MultiSigWalletBenefactor.submitSignature(digest, signature.signature_bytes); vm.stopPrank(); } diff --git a/test/foundry/test/USDtbMinting.StableRatios.t.sol b/test/foundry/test/USDtbMinting.StableRatios.t.sol new file mode 100644 index 0000000..2baceaa --- /dev/null +++ b/test/foundry/test/USDtbMinting.StableRatios.t.sol @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +/* solhint-disable func-name-mixedcase */ + +import "../USDtbMinting.utils.sol"; + +contract USDtbMintingStableRatiosTest is USDtbMintingUtils { + function setUp() public override { + super.setUp(); + } + + function test_stable_ratios_setup() public { + uint128 stablesDeltaLimitZero = 0; // zero bps allowed (identical USDT and USDtb amounts) + uint128 stablesDeltaLimitPositive = 577; // positive bps allowed + + vm.prank(owner); + USDtbMintingContract.setStablesDeltaLimit(stablesDeltaLimitZero); + + vm.prank(owner); + USDtbMintingContract.setStablesDeltaLimit(stablesDeltaLimitPositive); + } + + function test_verify_stables_limit() external { + vm.prank(benefactor); + USDTToken.mint(25000 * 10 ** 6); + + uint128 stablesDeltaLimit = 100; // 100 bps + + vm.prank(owner); + USDtbMintingContract.setStablesDeltaLimit(stablesDeltaLimit); + + uint128 usdtbAmount = 1000 * 10 ** 18; // 1,000 USDtb + + uint128 usdtAmountAtUpperLimit = 1010 * 10 ** 6; // 100 bps above the USDT amount that should be at the upper bps limit + uint128 usdtAmountAtLowerLimit = 990 * 10 ** 6; // 100 bps below the USDT amount that should be at the lower bps limit + + address usdtAddress = address(USDTToken); + + assertEq( + USDtbMintingContract.verifyStablesLimit( + usdtAmountAtUpperLimit, usdtbAmount, usdtAddress, IUSDtbMinting.OrderType.MINT + ), + true + ); + assertEq( + USDtbMintingContract.verifyStablesLimit( + usdtAmountAtLowerLimit, usdtbAmount, usdtAddress, IUSDtbMinting.OrderType.REDEEM + ), + true + ); + } + + function test_stables_limit_minting_valid() public { + vm.prank(benefactor); + USDTToken.mint(2500 * 10 ** 6); // Ensuring there is enough USDT for testing + + uint128 stablesDeltaLimit = 100; // 100 bps + + vm.prank(owner); + USDtbMintingContract.setStablesDeltaLimit(stablesDeltaLimit); + + uint128 usdtbAmount = 1000 * 10 ** 18; // 1,000 USDtb + + uint128 usdtAmountAtUpperLimit = 1010 * 10 ** 6; // 100 bps above the USDT amount that should be at the upper bps limit + uint128 usdtAmountAtLowerLimit = 990 * 10 ** 6; // 100 bps below the USDT amount that should be at the lower bps limit + + (IUSDtbMinting.Order memory orderLow, IUSDtbMinting.Signature memory signatureLow, IUSDtbMinting.Route memory routeLow) + = mint_setup(usdtbAmount, usdtAmountAtLowerLimit, USDTToken, 1, true); + vm.prank(minter); + USDtbMintingContract.mint(orderLow, routeLow, signatureLow); + + ( + IUSDtbMinting.Order memory orderHigh, + IUSDtbMinting.Signature memory signatureHigh, + IUSDtbMinting.Route memory routeHigh + ) = mint_setup(usdtbAmount, usdtAmountAtUpperLimit, USDTToken, 2, true); + vm.prank(minter); + USDtbMintingContract.mint(orderHigh, routeHigh, signatureHigh); + + assertEq(USDTToken.balanceOf(benefactor), 2500 * 10 ** 6 - usdtAmountAtLowerLimit - usdtAmountAtUpperLimit); + assertEq(USDTToken.balanceOf(address(USDtbMintingContract)), usdtAmountAtLowerLimit + usdtAmountAtUpperLimit); + } + + function test_stable_ratios_minting_invalid() public { + vm.prank(benefactor); + USDTToken.mint(2500 * 10 ** 18); + + uint128 stablesDeltaLimit = 100; // 100 bps + vm.prank(owner); + USDtbMintingContract.setStablesDeltaLimit(stablesDeltaLimit); + + uint128 usdtbAmount = 1000 * 10 ** 18; // 1,000 USDtb + uint128 collateralGreaterBreachStableLimit = 1011 * 10 ** 6; + (IUSDtbMinting.Order memory aOrder, IUSDtbMinting.Signature memory aTakerSignature, IUSDtbMinting.Route memory aRoute) + = mint_setup(usdtbAmount, collateralGreaterBreachStableLimit, USDTToken, 1, true); + + vm.prank(minter); + USDtbMintingContract.mint(aOrder, aRoute, aTakerSignature); + + uint128 collateralLessThanBreachesStableLimit = 989 * 10 ** 6; + (IUSDtbMinting.Order memory bOrder, IUSDtbMinting.Signature memory bTakerSignature, IUSDtbMinting.Route memory bRoute) + = mint_setup(usdtbAmount, collateralLessThanBreachesStableLimit, USDTToken, 2, true); + + vm.expectRevert(InvalidStablePrice); + vm.prank(minter); + USDtbMintingContract.mint(bOrder, bRoute, bTakerSignature); + } + + function test_stables_limit_redeem_valid() public { + vm.prank(address(USDtbMintingContract)); + usdtbToken.mint(beneficiary, 2500 * 10 ** 18); + + USDTToken.mint(2500 * 10 ** 6, benefactor); // initial mint + + uint128 stablesDeltaLimit = 100; // 100 bps + + vm.prank(owner); + USDtbMintingContract.setStablesDeltaLimit(stablesDeltaLimit); + + uint128 usdtbAmount = 1000 * 10 ** 18; // 1,000 USDtb + + uint128 usdtAmountAtUpperLimit = 1010 * 10 ** 6; // 100 bps above the USDT amount that should be at the upper bps limit + uint128 usdtAmountAtLowerLimit = 990 * 10 ** 6; // 100 bps below the USDT amount that should be at the lower bps limit + + (IUSDtbMinting.Order memory orderLow, IUSDtbMinting.Signature memory signatureLow) = + redeem_setup(usdtbAmount, usdtAmountAtLowerLimit, USDTToken, 1, true); + vm.prank(redeemer); + USDtbMintingContract.redeem(orderLow, signatureLow); + + (IUSDtbMinting.Order memory orderHigh, IUSDtbMinting.Signature memory signatureHigh) = + redeem_setup(usdtbAmount, usdtAmountAtUpperLimit, USDTToken, 2, true); + vm.prank(redeemer); + USDtbMintingContract.redeem(orderHigh, signatureHigh); + + assertEq(USDTToken.balanceOf(beneficiary), usdtAmountAtLowerLimit + usdtAmountAtUpperLimit); + assertEq(USDTToken.balanceOf(address(USDtbMintingContract)), 0); + } + + function test_stable_ratios_redeem_invalid() public { + vm.prank(address(USDtbMintingContract)); + usdtbToken.mint(beneficiary, 2500 * 10 ** 18); + + USDTToken.mint(2500 * 10 ** 6, address(USDtbMintingContract)); + + uint128 stablesDeltaLimit = 100; // 100 bps + vm.prank(owner); + USDtbMintingContract.setStablesDeltaLimit(stablesDeltaLimit); + + uint128 usdtbAmount = 1000 * 10 ** 18; // 1,000 USDtb + + address collateralAsset = address(USDTToken); + + // case 1 + uint128 collateralGreaterThanUSDtbAmount = 1011 * 10 ** 6; // 1011 USDT redeemed (greater than USDtb) + IUSDtbMinting.Order memory redeemOrder2 = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.REDEEM, + order_id: generateRandomOrderId(), + expiry: uint120(block.timestamp + 10 minutes), + nonce: 2, + benefactor: beneficiary, + beneficiary: beneficiary, + collateral_asset: collateralAsset, + usdtb_amount: usdtbAmount, + collateral_amount: collateralGreaterThanUSDtbAmount + }); + + vm.startPrank(beneficiary); + usdtbToken.approve(address(USDtbMintingContract), usdtbAmount); + + bytes32 digest2 = USDtbMintingContract.hashOrder(redeemOrder2); + IUSDtbMinting.Signature memory takerSignature2 = + signOrder(beneficiaryPrivateKey, digest2, IUSDtbMinting.SignatureType.EIP712); + vm.stopPrank(); + + vm.expectRevert(InvalidStablePrice); + vm.prank(redeemer); + USDtbMintingContract.redeem(redeemOrder2, takerSignature2); + + // case 2 + uint128 collateralLessThanUSDtbAmount = 989 * 10 ** 6; // 989 USDT redeemed (less than USDtb) + IUSDtbMinting.Order memory redeemOrder1 = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.REDEEM, + order_id: generateRandomOrderId(), + expiry: uint120(block.timestamp + 10 minutes), + nonce: 1, + benefactor: beneficiary, + beneficiary: beneficiary, + collateral_asset: collateralAsset, + usdtb_amount: usdtbAmount, + collateral_amount: collateralLessThanUSDtbAmount + }); + + vm.startPrank(beneficiary); + usdtbToken.approve(address(USDtbMintingContract), usdtbAmount); + + bytes32 digest1 = USDtbMintingContract.hashOrder(redeemOrder1); + IUSDtbMinting.Signature memory takerSignature1 = + signOrder(beneficiaryPrivateKey, digest1, IUSDtbMinting.SignatureType.EIP712); + vm.stopPrank(); + + vm.startPrank(owner); + USDtbMintingContract.grantRole(redeemerRole, redeemer); + vm.stopPrank(); + + vm.prank(redeemer); + USDtbMintingContract.redeem(redeemOrder1, takerSignature1); + } +} diff --git a/test/foundry/test/USDtbMinting.Whitelist.t.sol b/test/foundry/test/USDtbMinting.Whitelist.t.sol new file mode 100644 index 0000000..0592edb --- /dev/null +++ b/test/foundry/test/USDtbMinting.Whitelist.t.sol @@ -0,0 +1,317 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +/* solhint-disable func-name-mixedcase */ + +import "../USDtbMinting.utils.sol"; + +contract USDtbMintingWhitelistTest is USDtbMintingUtils { + function setUp() public override { + super.setUp(); + vm.deal(benefactor, _stETHToDeposit); + } + + function generate_nonce() public view returns (uint128) { + return uint128(uint256(keccak256(abi.encodePacked(block.timestamp, block.prevrandao, msg.sender)))); + } + + function test_whitelist_mint() public { + IUSDtbMinting.Order memory order = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.MINT, + order_id: generateRandomOrderId(), + expiry: uint120(block.timestamp + 10 minutes), + nonce: generate_nonce(), + benefactor: benefactor, + beneficiary: beneficiary, + collateral_asset: address(stETHToken), + collateral_amount: _stETHToDeposit, + usdtb_amount: _usdtbToMint / 2 + }); + + address[] memory targets = new address[](1); + targets[0] = address(USDtbMintingContract); + + uint128[] memory ratios = new uint128[](1); + ratios[0] = 10_000; + + IUSDtbMinting.Route memory route = IUSDtbMinting.Route({addresses: targets, ratios: ratios}); + + // taker + vm.startPrank(benefactor); + stETHToken.approve(address(USDtbMintingContract), _stETHToDeposit); + + bytes32 digest1 = USDtbMintingContract.hashOrder(order); + IUSDtbMinting.Signature memory takerSignature = + signOrder(benefactorPrivateKey, digest1, IUSDtbMinting.SignatureType.EIP712); + vm.stopPrank(); + + vm.prank(owner); + USDtbMintingContract.removeWhitelistedBenefactor(benefactor); + + vm.expectRevert(BenefactorNotWhitelisted); + vm.prank(minter); + USDtbMintingContract.mint(order, route, takerSignature); + + vm.prank(owner); + USDtbMintingContract.addWhitelistedBenefactor(benefactor); + vm.prank(minter); + USDtbMintingContract.mint(order, route, takerSignature); + + // assert balances + assertEq(stETHToken.balanceOf(address(benefactor)), 0); + assertEq(stETHToken.balanceOf(address(USDtbMintingContract)), _stETHToDeposit); + assertEq(usdtbToken.balanceOf(address(beneficiary)), _usdtbToMint / 2); + } + + function test_whitelist_redeem() public { + (IUSDtbMinting.Order memory mintOrder, IUSDtbMinting.Signature memory sig, IUSDtbMinting.Route memory route) = + mint_setup(_usdtbToMint, _stETHToDeposit, stETHToken, 1, false); + + vm.prank(minter); + USDtbMintingContract.mint(mintOrder, route, sig); + + IUSDtbMinting.Order memory redeemOrder = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.REDEEM, + order_id: generateRandomOrderId(), + expiry: uint120(block.timestamp + 10 minutes), + nonce: 47, + benefactor: beneficiary, + beneficiary: benefactor, // switched + collateral_asset: address(stETHToken), + collateral_amount: _stETHToDeposit, + usdtb_amount: _usdtbToMint + }); + + // taker + vm.startPrank(beneficiary); + usdtbToken.approve(address(USDtbMintingContract), _usdtbToMint); + + bytes32 redeemDigest = USDtbMintingContract.hashOrder(redeemOrder); + IUSDtbMinting.Signature memory takerSignature = + signOrder(beneficiaryPrivateKey, redeemDigest, IUSDtbMinting.SignatureType.EIP712); + vm.stopPrank(); + + vm.startPrank(owner); + vm.expectRevert(InvalidAddress); + USDtbMintingContract.removeWhitelistedBenefactor(owner); + + USDtbMintingContract.removeWhitelistedBenefactor(beneficiary); + vm.stopPrank(); + + vm.expectRevert(BenefactorNotWhitelisted); + vm.prank(redeemer); + USDtbMintingContract.redeem(redeemOrder, takerSignature); + + vm.prank(owner); + USDtbMintingContract.addWhitelistedBenefactor(beneficiary); + vm.prank(redeemer); + USDtbMintingContract.redeem(redeemOrder, takerSignature); + + assertEq(stETHToken.balanceOf(address(benefactor)), _stETHToDeposit); + assertEq(stETHToken.balanceOf(address(USDtbMintingContract)), 0); + assertEq(usdtbToken.balanceOf(address(beneficiary)), 0); + } + + function test_non_whitelisted_beneficiary_mint() public { + IUSDtbMinting.Order memory order = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.MINT, + order_id: generateRandomOrderId(), + expiry: uint120(block.timestamp + 10 minutes), + nonce: generate_nonce(), + benefactor: benefactor, + beneficiary: owner, + collateral_asset: address(stETHToken), + collateral_amount: _stETHToDeposit, + usdtb_amount: _usdtbToMint / 2 + }); + + address[] memory targets = new address[](1); + targets[0] = address(USDtbMintingContract); + + uint128[] memory ratios = new uint128[](1); + ratios[0] = 10_000; + + IUSDtbMinting.Route memory route = IUSDtbMinting.Route({addresses: targets, ratios: ratios}); + + // taker + vm.startPrank(benefactor); + stETHToken.approve(address(USDtbMintingContract), _stETHToDeposit); + + bytes32 digest1 = USDtbMintingContract.hashOrder(order); + IUSDtbMinting.Signature memory takerSignature = + signOrder(benefactorPrivateKey, digest1, IUSDtbMinting.SignatureType.EIP712); + vm.stopPrank(); + + vm.expectRevert(BeneficiaryNotApproved); + vm.prank(minter); + USDtbMintingContract.mint(order, route, takerSignature); + + vm.prank(benefactor); + USDtbMintingContract.setApprovedBeneficiary(owner, true); + vm.prank(minter); + USDtbMintingContract.mint(order, route, takerSignature); + + // assert balances + assertEq(stETHToken.balanceOf(address(benefactor)), 0); + assertEq(stETHToken.balanceOf(address(USDtbMintingContract)), _stETHToDeposit); + assertEq(usdtbToken.balanceOf(address(owner)), _usdtbToMint / 2); + } + + function test_non_whitelisted_beneficiary_redeem() public { + vm.prank(benefactor); + USDtbMintingContract.setApprovedBeneficiary(owner, true); + IUSDtbMinting.Order memory order = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.MINT, + order_id: generateRandomOrderId(), + expiry: uint120(block.timestamp + 10 minutes), + nonce: 3423423, + benefactor: benefactor, + beneficiary: owner, + collateral_asset: address(stETHToken), + usdtb_amount: _usdtbToMint, + collateral_amount: _stETHToDeposit + }); + + address[] memory targets = new address[](1); + targets[0] = address(USDtbMintingContract); + + uint128[] memory ratios = new uint128[](1); + ratios[0] = 10_000; + + IUSDtbMinting.Route memory route = IUSDtbMinting.Route({addresses: targets, ratios: ratios}); + + vm.startPrank(benefactor); + bytes32 digest1 = USDtbMintingContract.hashOrder(order); + IUSDtbMinting.Signature memory takerSignature = + signOrder(benefactorPrivateKey, digest1, IUSDtbMinting.SignatureType.EIP712); + IERC20(address(stETHToken)).approve(address(USDtbMintingContract), _stETHToDeposit); + vm.stopPrank(); + + vm.prank(minter); + USDtbMintingContract.mint(order, route, takerSignature); + + IUSDtbMinting.Order memory redeemOrder = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.REDEEM, + order_id: generateRandomOrderId(), + expiry: uint120(block.timestamp + 10 minutes), + nonce: 44524527, + benefactor: owner, + beneficiary: beneficiary, + collateral_asset: address(stETHToken), + collateral_amount: _stETHToDeposit, + usdtb_amount: _usdtbToMint + }); + + // taker + vm.startPrank(owner); + usdtbToken.approve(address(USDtbMintingContract), _usdtbToMint); + + bytes32 redeemDigest = USDtbMintingContract.hashOrder(redeemOrder); + IUSDtbMinting.Signature memory redeemTakerSignature = + signOrder(ownerPrivateKey, redeemDigest, IUSDtbMinting.SignatureType.EIP712); + vm.stopPrank(); + + vm.startPrank(redeemer); + vm.expectRevert(BenefactorNotWhitelisted); + USDtbMintingContract.redeem(redeemOrder, redeemTakerSignature); + vm.stopPrank(); + + vm.startPrank(owner); + USDtbMintingContract.addWhitelistedBenefactor(owner); + vm.stopPrank(); + + vm.startPrank(redeemer); + vm.expectRevert(BeneficiaryNotApproved); + USDtbMintingContract.redeem(redeemOrder, redeemTakerSignature); + vm.stopPrank(); + + vm.startPrank(owner); + USDtbMintingContract.setApprovedBeneficiary(beneficiary, true); + vm.stopPrank(); + + vm.prank(redeemer); + USDtbMintingContract.redeem(redeemOrder, redeemTakerSignature); + } + + function test_whitelisted_beneficiary_whitelist_enabled_transfer_redeem() public { + vm.prank(benefactor); + USDtbMintingContract.setApprovedBeneficiary(owner, true); + IUSDtbMinting.Order memory order = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.MINT, + order_id: generateRandomOrderId(), + expiry: uint120(block.timestamp + 10 minutes), + nonce: 3423423, + benefactor: benefactor, + beneficiary: owner, + collateral_asset: address(stETHToken), + usdtb_amount: _usdtbToMint, + collateral_amount: _stETHToDeposit + }); + + address[] memory targets = new address[](1); + targets[0] = address(USDtbMintingContract); + + uint128[] memory ratios = new uint128[](1); + ratios[0] = 10_000; + + IUSDtbMinting.Route memory route = IUSDtbMinting.Route({addresses: targets, ratios: ratios}); + + vm.startPrank(benefactor); + bytes32 digest1 = USDtbMintingContract.hashOrder(order); + IUSDtbMinting.Signature memory takerSignature = + signOrder(benefactorPrivateKey, digest1, IUSDtbMinting.SignatureType.EIP712); + IERC20(address(stETHToken)).approve(address(USDtbMintingContract), _stETHToDeposit); + vm.stopPrank(); + + vm.prank(minter); + USDtbMintingContract.mint(order, route, takerSignature); + + // set the transfer state to WHITELIST_ENABLED + vm.startPrank(newOwner); + usdtbToken.updateTransferState(IUSDtbDefinitions.TransferState.WHITELIST_ENABLED); + usdtbToken.grantRole(keccak256("WHITELISTED_ROLE"), owner); + vm.stopPrank(); + + IUSDtbMinting.Order memory redeemOrder = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.REDEEM, + order_id: generateRandomOrderId(), + expiry: uint120(block.timestamp + 10 minutes), + nonce: 44524527, + benefactor: owner, + beneficiary: beneficiary, + collateral_asset: address(stETHToken), + collateral_amount: _stETHToDeposit, + usdtb_amount: _usdtbToMint + }); + + // taker + vm.startPrank(owner); + usdtbToken.approve(address(USDtbMintingContract), _usdtbToMint); + + bytes32 redeemDigest = USDtbMintingContract.hashOrder(redeemOrder); + IUSDtbMinting.Signature memory redeemTakerSignature = + signOrder(ownerPrivateKey, redeemDigest, IUSDtbMinting.SignatureType.EIP712); + vm.stopPrank(); + + vm.startPrank(redeemer); + vm.expectRevert(BenefactorNotWhitelisted); + USDtbMintingContract.redeem(redeemOrder, redeemTakerSignature); + vm.stopPrank(); + + vm.startPrank(owner); + USDtbMintingContract.addWhitelistedBenefactor(owner); + vm.stopPrank(); + + vm.startPrank(redeemer); + vm.expectRevert(BeneficiaryNotApproved); + USDtbMintingContract.redeem(redeemOrder, redeemTakerSignature); + vm.stopPrank(); + + vm.startPrank(owner); + USDtbMintingContract.setApprovedBeneficiary(beneficiary, true); + vm.stopPrank(); + + vm.prank(redeemer); + USDtbMintingContract.redeem(redeemOrder, redeemTakerSignature); + } +} diff --git a/test/foundry/test/UStbMinting.blockLimits.t.sol b/test/foundry/test/USDtbMinting.blockLimits.t.sol similarity index 61% rename from test/foundry/test/UStbMinting.blockLimits.t.sol rename to test/foundry/test/USDtbMinting.blockLimits.t.sol index 5e34774..f1ca90e 100644 --- a/test/foundry/test/UStbMinting.blockLimits.t.sol +++ b/test/foundry/test/USDtbMinting.blockLimits.t.sol @@ -3,9 +3,9 @@ pragma solidity ^0.8.20; /* solhint-disable func-name-mixedcase */ -import "../UStbMinting.utils.sol"; +import "../USDtbMinting.utils.sol"; -contract UStbMintingBlockLimitsTest is UStbMintingUtils { +contract USDtbMintingBlockLimitsTest is USDtbMintingUtils { /** * Max mint per block tests */ @@ -16,22 +16,22 @@ contract UStbMintingBlockLimitsTest is UStbMintingUtils { uint128 maxMintAmount = tokenConfig[0].maxMintPerBlock; uint128 firstMintAmount = maxMintAmount / 4; uint128 secondMintAmount = maxMintAmount / 2; - (IUStbMinting.Order memory aOrder, IUStbMinting.Signature memory aTakerSignature, IUStbMinting.Route memory aRoute) + (IUSDtbMinting.Order memory aOrder, IUSDtbMinting.Signature memory aTakerSignature, IUSDtbMinting.Route memory aRoute) = mint_setup(firstMintAmount, _stETHToDeposit, stETHToken, 1, false); vm.prank(minter); - UStbMintingContract.mint(aOrder, aRoute, aTakerSignature); + USDtbMintingContract.mint(aOrder, aRoute, aTakerSignature); vm.prank(owner); stETHToken.mint(_stETHToDeposit, benefactor); - (IUStbMinting.Order memory bOrder, IUStbMinting.Signature memory bTakerSignature, IUStbMinting.Route memory bRoute) + (IUSDtbMinting.Order memory bOrder, IUSDtbMinting.Signature memory bTakerSignature, IUSDtbMinting.Route memory bRoute) = mint_setup(secondMintAmount, _stETHToDeposit, stETHToken, 2, true); vm.prank(minter); - UStbMintingContract.mint(bOrder, bRoute, bTakerSignature); + USDtbMintingContract.mint(bOrder, bRoute, bTakerSignature); - (uint128 mintedPerBlock,) = UStbMintingContract.totalPerBlockPerAsset(block.number, address(stETHToken)); + (uint128 mintedPerBlock,) = USDtbMintingContract.totalPerBlockPerAsset(block.number, address(stETHToken)); assertEq(mintedPerBlock, firstMintAmount + secondMintAmount, "Incorrect minted amount"); assertTrue(mintedPerBlock < maxMintAmount, "Mint amount exceeded without revert"); @@ -46,37 +46,37 @@ contract UStbMintingBlockLimitsTest is UStbMintingUtils { function test_fuzz_mint_maxMint_perBlock_exceeded_revert(uint128 excessiveMintAmount) public { vm.assume(excessiveMintAmount > tokenConfig[0].maxMintPerBlock); - (IUStbMinting.Order memory mintOrder, IUStbMinting.Signature memory takerSignature, IUStbMinting.Route memory route) + (IUSDtbMinting.Order memory mintOrder, IUSDtbMinting.Signature memory takerSignature, IUSDtbMinting.Route memory route) = mint_setup(excessiveMintAmount, _stETHToDeposit, stETHToken, 1, false); // maker vm.startPrank(minter); assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit); - assertEq(ustbToken.balanceOf(beneficiary), 0); + assertEq(usdtbToken.balanceOf(beneficiary), 0); vm.expectRevert(MaxMintPerBlockExceeded); // minter passes in permit signature data - UStbMintingContract.mint(mintOrder, route, takerSignature); + USDtbMintingContract.mint(mintOrder, route, takerSignature); assertEq( stETHToken.balanceOf(benefactor), _stETHToDeposit, "The benefactor stEth balance should be the same as the minted stEth" ); - assertEq(ustbToken.balanceOf(beneficiary), 0, "The beneficiary UStb balance should be 0"); + assertEq(usdtbToken.balanceOf(beneficiary), 0, "The beneficiary USDtb balance should be 0"); } function test_fuzz_nextBlock_mint_is_zero(uint128 mintAmount) public { vm.assume(mintAmount < tokenConfig[0].maxMintPerBlock && mintAmount > 0); - (IUStbMinting.Order memory order, IUStbMinting.Signature memory takerSignature, IUStbMinting.Route memory route) = - mint_setup(_ustbToMint, _stETHToDeposit, stETHToken, 1, false); + (IUSDtbMinting.Order memory order, IUSDtbMinting.Signature memory takerSignature, IUSDtbMinting.Route memory route) = + mint_setup(_usdtbToMint, _stETHToDeposit, stETHToken, 1, false); vm.prank(minter); - UStbMintingContract.mint(order, route, takerSignature); + USDtbMintingContract.mint(order, route, takerSignature); vm.roll(block.number + 1); - (uint128 mintedPerBlock,) = UStbMintingContract.totalPerBlockPerAsset(block.number, address(stETHToken)); + (uint128 mintedPerBlock,) = USDtbMintingContract.totalPerBlockPerAsset(block.number, address(stETHToken)); assertEq(mintedPerBlock, 0, "The minted amount should reset to 0 in the next block"); } @@ -90,9 +90,9 @@ contract UStbMintingBlockLimitsTest is UStbMintingUtils { vm.expectEmit(); emit MaxMintPerBlockChanged(oldMaxMintPerBlock, newMaxMintPerBlock, address(stETHToken)); - UStbMintingContract.setMaxMintPerBlock(newMaxMintPerBlock, address(stETHToken)); + USDtbMintingContract.setMaxMintPerBlock(newMaxMintPerBlock, address(stETHToken)); - (,, uint128 maxMintPerBlock,) = UStbMintingContract.tokenConfig(address(stETHToken)); + (,, uint128 maxMintPerBlock,) = USDtbMintingContract.tokenConfig(address(stETHToken)); assertEq(maxMintPerBlock, newMaxMintPerBlock, "The max mint per block setter failed"); } @@ -100,7 +100,7 @@ contract UStbMintingBlockLimitsTest is UStbMintingUtils { function test_global_mint_limit_versus_local_perBlock() public { uint128 maxMintAmount = tokenConfig[0].maxMintPerBlock; uint128 firstMintAmount = maxMintAmount / 4; - (IUStbMinting.Order memory aOrder, IUStbMinting.Signature memory aTakerSignature, IUStbMinting.Route memory aRoute) + (IUSDtbMinting.Order memory aOrder, IUSDtbMinting.Signature memory aTakerSignature, IUSDtbMinting.Route memory aRoute) = mint_setup(firstMintAmount, _stETHToDeposit, stETHToken, 1, false); vm.startPrank(owner); @@ -108,34 +108,34 @@ contract UStbMintingBlockLimitsTest is UStbMintingUtils { // within per asset but NOT global limit vm.startPrank(owner); - UStbMintingContract.setMaxMintPerBlock(maxMintAmount, address(stETHToken)); - UStbMintingContract.setGlobalMaxMintPerBlock(maxMintAmount / 5); + USDtbMintingContract.setMaxMintPerBlock(maxMintAmount, address(stETHToken)); + USDtbMintingContract.setGlobalMaxMintPerBlock(maxMintAmount / 5); vm.stopPrank(); vm.startPrank(minter); vm.expectRevert(GlobalMaxMintPerBlockExceeded); - UStbMintingContract.mint(aOrder, aRoute, aTakerSignature); + USDtbMintingContract.mint(aOrder, aRoute, aTakerSignature); vm.stopPrank(); // within global but NOT per asset limit vm.startPrank(owner); - UStbMintingContract.setGlobalMaxMintPerBlock(maxMintAmount); - UStbMintingContract.setMaxMintPerBlock(firstMintAmount / 2, address(stETHToken)); + USDtbMintingContract.setGlobalMaxMintPerBlock(maxMintAmount); + USDtbMintingContract.setMaxMintPerBlock(firstMintAmount / 2, address(stETHToken)); vm.stopPrank(); vm.startPrank(minter); vm.expectRevert(MaxMintPerBlockExceeded); - UStbMintingContract.mint(aOrder, aRoute, aTakerSignature); + USDtbMintingContract.mint(aOrder, aRoute, aTakerSignature); vm.stopPrank(); // within global and per asset limit vm.startPrank(owner); - UStbMintingContract.setMaxMintPerBlock(firstMintAmount, address(stETHToken)); - UStbMintingContract.setGlobalMaxMintPerBlock(firstMintAmount); + USDtbMintingContract.setMaxMintPerBlock(firstMintAmount, address(stETHToken)); + USDtbMintingContract.setGlobalMaxMintPerBlock(firstMintAmount); vm.stopPrank(); vm.prank(minter); - UStbMintingContract.mint(aOrder, aRoute, aTakerSignature); + USDtbMintingContract.mint(aOrder, aRoute, aTakerSignature); } /** @@ -149,26 +149,26 @@ contract UStbMintingBlockLimitsTest is UStbMintingUtils { uint128 firstRedeemAmount = maxRedeemAmount / 4; uint128 secondRedeemAmount = maxRedeemAmount / 2; - (IUStbMinting.Order memory redeemOrder, IUStbMinting.Signature memory takerSignature2) = + (IUSDtbMinting.Order memory redeemOrder, IUSDtbMinting.Signature memory takerSignature2) = redeem_setup(firstRedeemAmount, _stETHToDeposit, stETHToken, 1, false); vm.prank(redeemer); - UStbMintingContract.redeem(redeemOrder, takerSignature2); + USDtbMintingContract.redeem(redeemOrder, takerSignature2); vm.prank(owner); stETHToken.mint(_stETHToDeposit, benefactor); - (IUStbMinting.Order memory bRedeemOrder, IUStbMinting.Signature memory bTakerSignature2) = + (IUSDtbMinting.Order memory bRedeemOrder, IUSDtbMinting.Signature memory bTakerSignature2) = redeem_setup(secondRedeemAmount, _stETHToDeposit, stETHToken, 2, true); vm.prank(redeemer); - UStbMintingContract.redeem(bRedeemOrder, bTakerSignature2); + USDtbMintingContract.redeem(bRedeemOrder, bTakerSignature2); - (uint128 mintedPerBlock,) = UStbMintingContract.totalPerBlockPerAsset(block.number, address(stETHToken)); + (uint128 mintedPerBlock,) = USDtbMintingContract.totalPerBlockPerAsset(block.number, address(stETHToken)); assertEq(mintedPerBlock, firstRedeemAmount + secondRedeemAmount, "Incorrect minted amount"); - (, uint128 redeemedPerBlock2) = UStbMintingContract.totalPerBlockPerAsset(block.number, address(stETHToken)); + (, uint128 redeemedPerBlock2) = USDtbMintingContract.totalPerBlockPerAsset(block.number, address(stETHToken)); assertTrue(redeemedPerBlock2 < maxRedeemAmount, "Redeem amount exceeded without revert"); } @@ -178,39 +178,39 @@ contract UStbMintingBlockLimitsTest is UStbMintingUtils { // excessive redeem amount greater than max mint/redeem per block for stETH but within global limit vm.startPrank(owner); - UStbMintingContract.setGlobalMaxMintPerBlock(excessiveRedeemAmount); - UStbMintingContract.setGlobalMaxRedeemPerBlock(excessiveRedeemAmount); + USDtbMintingContract.setGlobalMaxMintPerBlock(excessiveRedeemAmount); + USDtbMintingContract.setGlobalMaxRedeemPerBlock(excessiveRedeemAmount); vm.stopPrank(); // Set the max mint per block to the same value as the max redeem in order to get to the redeem vm.prank(owner); - UStbMintingContract.setMaxMintPerBlock(excessiveRedeemAmount, address(stETHToken)); + USDtbMintingContract.setMaxMintPerBlock(excessiveRedeemAmount, address(stETHToken)); - (IUStbMinting.Order memory redeemOrder, IUStbMinting.Signature memory takerSignature2) = + (IUSDtbMinting.Order memory redeemOrder, IUSDtbMinting.Signature memory takerSignature2) = redeem_setup(excessiveRedeemAmount, _stETHToDeposit, stETHToken, 1, false); vm.startPrank(redeemer); vm.expectRevert(MaxRedeemPerBlockExceeded); - UStbMintingContract.redeem(redeemOrder, takerSignature2); + USDtbMintingContract.redeem(redeemOrder, takerSignature2); - assertEq(stETHToken.balanceOf(address(UStbMintingContract)), _stETHToDeposit, "Mismatch in stETH balance"); + assertEq(stETHToken.balanceOf(address(USDtbMintingContract)), _stETHToDeposit, "Mismatch in stETH balance"); assertEq(stETHToken.balanceOf(beneficiary), 0, "Mismatch in stETH balance"); - assertEq(ustbToken.balanceOf(beneficiary), excessiveRedeemAmount, "Mismatch in UStb balance"); + assertEq(usdtbToken.balanceOf(beneficiary), excessiveRedeemAmount, "Mismatch in USDtb balance"); vm.stopPrank(); } function test_fuzz_nextBlock_redeem_is_zero(uint128 redeemAmount) public { vm.assume(redeemAmount < tokenConfig[0].maxRedeemPerBlock && redeemAmount > 0); - (IUStbMinting.Order memory redeemOrder, IUStbMinting.Signature memory takerSignature2) = + (IUSDtbMinting.Order memory redeemOrder, IUSDtbMinting.Signature memory takerSignature2) = redeem_setup(redeemAmount, _stETHToDeposit, stETHToken, 1, false); vm.startPrank(redeemer); - UStbMintingContract.redeem(redeemOrder, takerSignature2); + USDtbMintingContract.redeem(redeemOrder, takerSignature2); vm.roll(block.number + 1); - (, uint128 redeemedPerBlock) = UStbMintingContract.totalPerBlockPerAsset(block.number, address(stETHToken)); + (, uint128 redeemedPerBlock) = USDtbMintingContract.totalPerBlockPerAsset(block.number, address(stETHToken)); assertEq(redeemedPerBlock, 0, "The redeemed amount should reset to 0 in the next block"); vm.stopPrank(); @@ -224,9 +224,9 @@ contract UStbMintingBlockLimitsTest is UStbMintingUtils { vm.prank(owner); vm.expectEmit(); emit MaxRedeemPerBlockChanged(oldMaxRedeemPerBlock, newMaxRedeemPerBlock, address(stETHToken)); - UStbMintingContract.setMaxRedeemPerBlock(newMaxRedeemPerBlock, address(stETHToken)); + USDtbMintingContract.setMaxRedeemPerBlock(newMaxRedeemPerBlock, address(stETHToken)); - (,,, uint128 maxRedeemPerBlock) = UStbMintingContract.tokenConfig(address(stETHToken)); + (,,, uint128 maxRedeemPerBlock) = USDtbMintingContract.tokenConfig(address(stETHToken)); assertEq(maxRedeemPerBlock, newMaxRedeemPerBlock, "The max redeem per block setter failed"); } diff --git a/test/foundry/test/UStbMinting.core.t.sol b/test/foundry/test/USDtbMinting.core.t.sol similarity index 50% rename from test/foundry/test/UStbMinting.core.t.sol rename to test/foundry/test/USDtbMinting.core.t.sol index 23c765e..ff1d773 100644 --- a/test/foundry/test/UStbMinting.core.t.sol +++ b/test/foundry/test/USDtbMinting.core.t.sol @@ -3,9 +3,9 @@ pragma solidity ^0.8.20; /* solhint-disable func-name-mixedcase */ -import "../UStbMinting.utils.sol"; +import "../USDtbMinting.utils.sol"; -contract UStbMintingCoreTest is UStbMintingUtils { +contract USDtbMintingCoreTest is USDtbMintingUtils { function setUp() public override { super.setUp(); } @@ -16,33 +16,33 @@ contract UStbMintingCoreTest is UStbMintingUtils { function test_redeem() public { executeRedeem(stETHToken); - assertEq(stETHToken.balanceOf(address(UStbMintingContract)), 0, "Mismatch in stETH balance"); + assertEq(stETHToken.balanceOf(address(USDtbMintingContract)), 0, "Mismatch in stETH balance"); assertEq(stETHToken.balanceOf(beneficiary), _stETHToDeposit, "Mismatch in stETH balance"); - assertEq(ustbToken.balanceOf(beneficiary), 0, "Mismatch in UStb balance"); + assertEq(usdtbToken.balanceOf(beneficiary), 0, "Mismatch in USDtb balance"); } function test_redeem_invalidNonce_revert() public { // Unset the max redeem per block limit vm.startPrank(owner); - UStbMintingContract.setMaxRedeemPerBlock(MAX_USDE_MINT_AND_REDEEM_PER_BLOCK * 10, address(stETHToken)); - UStbMintingContract.setGlobalMaxRedeemPerBlock(type(uint128).max); + USDtbMintingContract.setMaxRedeemPerBlock(MAX_USDE_MINT_AND_REDEEM_PER_BLOCK * 10, address(stETHToken)); + USDtbMintingContract.setGlobalMaxRedeemPerBlock(type(uint128).max); vm.stopPrank(); - (IUStbMinting.Order memory redeemOrder, IUStbMinting.Signature memory takerSignature2) = - redeem_setup(_ustbToMint, _stETHToDeposit, stETHToken, 1, false); + (IUSDtbMinting.Order memory redeemOrder, IUSDtbMinting.Signature memory takerSignature2) = + redeem_setup(_usdtbToMint, _stETHToDeposit, stETHToken, 1, false); vm.startPrank(redeemer); - UStbMintingContract.redeem(redeemOrder, takerSignature2); + USDtbMintingContract.redeem(redeemOrder, takerSignature2); vm.expectRevert(InvalidNonce); - UStbMintingContract.redeem(redeemOrder, takerSignature2); + USDtbMintingContract.redeem(redeemOrder, takerSignature2); } function test_nativeEth_withdraw() public { - vm.deal(address(UStbMintingContract), _stETHToDeposit); + vm.deal(address(USDtbMintingContract), _stETHToDeposit); - IUStbMinting.Order memory order = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.MINT, + IUSDtbMinting.Order memory order = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.MINT, order_id: generateRandomOrderId(), expiry: uint120(block.timestamp + 10 minutes), nonce: 8, @@ -50,62 +50,62 @@ contract UStbMintingCoreTest is UStbMintingUtils { beneficiary: benefactor, collateral_asset: address(stETHToken), collateral_amount: _stETHToDeposit, - ustb_amount: _ustbToMint + usdtb_amount: _usdtbToMint }); address[] memory targets = new address[](1); - targets[0] = address(UStbMintingContract); + targets[0] = address(USDtbMintingContract); uint128[] memory ratios = new uint128[](1); ratios[0] = 10_000; - IUStbMinting.Route memory route = IUStbMinting.Route({addresses: targets, ratios: ratios}); + IUSDtbMinting.Route memory route = IUSDtbMinting.Route({addresses: targets, ratios: ratios}); // taker vm.startPrank(benefactor); - stETHToken.approve(address(UStbMintingContract), _stETHToDeposit); + stETHToken.approve(address(USDtbMintingContract), _stETHToDeposit); - bytes32 digest1 = UStbMintingContract.hashOrder(order); - IUStbMinting.Signature memory takerSignature = - signOrder(benefactorPrivateKey, digest1, IUStbMinting.SignatureType.EIP712); + bytes32 digest1 = USDtbMintingContract.hashOrder(order); + IUSDtbMinting.Signature memory takerSignature = + signOrder(benefactorPrivateKey, digest1, IUSDtbMinting.SignatureType.EIP712); vm.stopPrank(); - assertEq(ustbToken.balanceOf(benefactor), 0); + assertEq(usdtbToken.balanceOf(benefactor), 0); vm.recordLogs(); vm.prank(minter); - UStbMintingContract.mint(order, route, takerSignature); + USDtbMintingContract.mint(order, route, takerSignature); vm.getRecordedLogs(); - assertEq(ustbToken.balanceOf(benefactor), _ustbToMint); + assertEq(usdtbToken.balanceOf(benefactor), _usdtbToMint); //redeem - IUStbMinting.Order memory redeemOrder = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.REDEEM, + IUSDtbMinting.Order memory redeemOrder = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.REDEEM, order_id: generateRandomOrderId(), expiry: uint120(block.timestamp + 10 minutes), nonce: 800, benefactor: benefactor, beneficiary: benefactor, collateral_asset: NATIVE_TOKEN, - ustb_amount: _ustbToMint, + usdtb_amount: _usdtbToMint, collateral_amount: _stETHToDeposit }); // taker vm.startPrank(benefactor); - ustbToken.approve(address(UStbMintingContract), _ustbToMint); + usdtbToken.approve(address(USDtbMintingContract), _usdtbToMint); - bytes32 digest3 = UStbMintingContract.hashOrder(redeemOrder); - IUStbMinting.Signature memory takerSignature2 = - signOrder(benefactorPrivateKey, digest3, IUStbMinting.SignatureType.EIP712); + bytes32 digest3 = USDtbMintingContract.hashOrder(redeemOrder); + IUSDtbMinting.Signature memory takerSignature2 = + signOrder(benefactorPrivateKey, digest3, IUSDtbMinting.SignatureType.EIP712); vm.stopPrank(); vm.startPrank(redeemer); - UStbMintingContract.redeem(redeemOrder, takerSignature2); + USDtbMintingContract.redeem(redeemOrder, takerSignature2); assertEq(stETHToken.balanceOf(benefactor), 0); - assertEq(ustbToken.balanceOf(benefactor), 0); + assertEq(usdtbToken.balanceOf(benefactor), 0); assertEq(benefactor.balance, _stETHToDeposit); vm.stopPrank(); @@ -114,22 +114,22 @@ contract UStbMintingCoreTest is UStbMintingUtils { function test_fuzz_mint_noSlippage(uint128 expectedAmount) public { vm.assume(expectedAmount > 0 && expectedAmount < _maxMintPerBlock); - (IUStbMinting.Order memory order, IUStbMinting.Signature memory takerSignature, IUStbMinting.Route memory route) = + (IUSDtbMinting.Order memory order, IUSDtbMinting.Signature memory takerSignature, IUSDtbMinting.Route memory route) = mint_setup(expectedAmount, _stETHToDeposit, stETHToken, 1, false); vm.recordLogs(); vm.prank(minter); - UStbMintingContract.mint(order, route, takerSignature); + USDtbMintingContract.mint(order, route, takerSignature); vm.getRecordedLogs(); assertEq(stETHToken.balanceOf(benefactor), 0); - assertEq(stETHToken.balanceOf(address(UStbMintingContract)), _stETHToDeposit); - assertEq(ustbToken.balanceOf(beneficiary), expectedAmount); + assertEq(stETHToken.balanceOf(address(USDtbMintingContract)), _stETHToDeposit); + assertEq(usdtbToken.balanceOf(beneficiary), expectedAmount); } function test_multipleValid_custodyRatios_addresses() public { uint128 _smallUsdeToMint = 1.75 * 10 ** 23; - IUStbMinting.Order memory order = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.MINT, + IUSDtbMinting.Order memory order = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.MINT, order_id: generateRandomOrderId(), expiry: uint120(block.timestamp + 10 minutes), nonce: 14, @@ -137,11 +137,11 @@ contract UStbMintingCoreTest is UStbMintingUtils { beneficiary: beneficiary, collateral_asset: address(stETHToken), collateral_amount: _stETHToDeposit, - ustb_amount: _smallUsdeToMint + usdtb_amount: _smallUsdeToMint }); address[] memory targets = new address[](3); - targets[0] = address(UStbMintingContract); + targets[0] = address(USDtbMintingContract); targets[1] = custodian1; targets[2] = custodian2; @@ -150,51 +150,51 @@ contract UStbMintingCoreTest is UStbMintingUtils { ratios[1] = 4_000; ratios[2] = 3_000; - IUStbMinting.Route memory route = IUStbMinting.Route({addresses: targets, ratios: ratios}); + IUSDtbMinting.Route memory route = IUSDtbMinting.Route({addresses: targets, ratios: ratios}); // taker vm.startPrank(benefactor); - stETHToken.approve(address(UStbMintingContract), _stETHToDeposit); + stETHToken.approve(address(USDtbMintingContract), _stETHToDeposit); - bytes32 digest1 = UStbMintingContract.hashOrder(order); - IUStbMinting.Signature memory takerSignature = - signOrder(benefactorPrivateKey, digest1, IUStbMinting.SignatureType.EIP712); + bytes32 digest1 = USDtbMintingContract.hashOrder(order); + IUSDtbMinting.Signature memory takerSignature = + signOrder(benefactorPrivateKey, digest1, IUSDtbMinting.SignatureType.EIP712); vm.stopPrank(); assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit); vm.prank(minter); vm.expectRevert(InvalidRoute); - UStbMintingContract.mint(order, route, takerSignature); + USDtbMintingContract.mint(order, route, takerSignature); vm.prank(owner); - UStbMintingContract.addCustodianAddress(custodian2); + USDtbMintingContract.addCustodianAddress(custodian2); vm.prank(minter); - UStbMintingContract.mint(order, route, takerSignature); + USDtbMintingContract.mint(order, route, takerSignature); assertEq(stETHToken.balanceOf(benefactor), 0); - assertEq(ustbToken.balanceOf(beneficiary), _smallUsdeToMint); + assertEq(usdtbToken.balanceOf(beneficiary), _smallUsdeToMint); assertEq(stETHToken.balanceOf(address(custodian1)), (_stETHToDeposit * 4) / 10); assertEq(stETHToken.balanceOf(address(custodian2)), (_stETHToDeposit * 3) / 10); - assertEq(stETHToken.balanceOf(address(UStbMintingContract)), (_stETHToDeposit * 3) / 10); + assertEq(stETHToken.balanceOf(address(USDtbMintingContract)), (_stETHToDeposit * 3) / 10); // remove custodian and expect reversion vm.prank(owner); - UStbMintingContract.removeCustodianAddress(custodian2); + USDtbMintingContract.removeCustodianAddress(custodian2); vm.prank(minter); vm.expectRevert(InvalidRoute); - UStbMintingContract.mint(order, route, takerSignature); + USDtbMintingContract.mint(order, route, takerSignature); } function test_fuzz_multipleInvalid_custodyRatios_revert(uint128 ratio1) public { ratio1 = uint128(bound(ratio1, 0, type(uint128).max - 7_000)); vm.assume(ratio1 != 3_000); - IUStbMinting.Order memory mintOrder = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.MINT, + IUSDtbMinting.Order memory mintOrder = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.MINT, order_id: generateRandomOrderId(), expiry: uint120(block.timestamp + 10 minutes), nonce: 15, @@ -202,45 +202,45 @@ contract UStbMintingCoreTest is UStbMintingUtils { beneficiary: beneficiary, collateral_asset: address(stETHToken), collateral_amount: _stETHToDeposit, - ustb_amount: _ustbToMint + usdtb_amount: _usdtbToMint }); address[] memory targets = new address[](2); - targets[0] = address(UStbMintingContract); + targets[0] = address(USDtbMintingContract); targets[1] = owner; uint128[] memory ratios = new uint128[](2); ratios[0] = ratio1; ratios[1] = 7_000; - IUStbMinting.Route memory route = IUStbMinting.Route({addresses: targets, ratios: ratios}); + IUSDtbMinting.Route memory route = IUSDtbMinting.Route({addresses: targets, ratios: ratios}); vm.startPrank(benefactor); - stETHToken.approve(address(UStbMintingContract), _stETHToDeposit); + stETHToken.approve(address(USDtbMintingContract), _stETHToDeposit); - bytes32 digest1 = UStbMintingContract.hashOrder(mintOrder); - IUStbMinting.Signature memory takerSignature = - signOrder(benefactorPrivateKey, digest1, IUStbMinting.SignatureType.EIP712); + bytes32 digest1 = USDtbMintingContract.hashOrder(mintOrder); + IUSDtbMinting.Signature memory takerSignature = + signOrder(benefactorPrivateKey, digest1, IUSDtbMinting.SignatureType.EIP712); vm.stopPrank(); assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit); vm.expectRevert(InvalidRoute); vm.prank(minter); - UStbMintingContract.mint(mintOrder, route, takerSignature); + USDtbMintingContract.mint(mintOrder, route, takerSignature); assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit); - assertEq(ustbToken.balanceOf(beneficiary), 0); + assertEq(usdtbToken.balanceOf(beneficiary), 0); - assertEq(stETHToken.balanceOf(address(UStbMintingContract)), 0); + assertEq(stETHToken.balanceOf(address(USDtbMintingContract)), 0); assertEq(stETHToken.balanceOf(owner), 0); } function test_fuzz_singleInvalid_custodyRatio_revert(uint128 ratio1) public { vm.assume(ratio1 != 10_000); - IUStbMinting.Order memory order = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.MINT, + IUSDtbMinting.Order memory order = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.MINT, order_id: generateRandomOrderId(), expiry: uint120(block.timestamp + 10 minutes), nonce: 16, @@ -248,46 +248,46 @@ contract UStbMintingCoreTest is UStbMintingUtils { beneficiary: beneficiary, collateral_asset: address(stETHToken), collateral_amount: _stETHToDeposit, - ustb_amount: _ustbToMint + usdtb_amount: _usdtbToMint }); address[] memory targets = new address[](1); - targets[0] = address(UStbMintingContract); + targets[0] = address(USDtbMintingContract); uint128[] memory ratios = new uint128[](1); ratios[0] = ratio1; - IUStbMinting.Route memory route = IUStbMinting.Route({addresses: targets, ratios: ratios}); + IUSDtbMinting.Route memory route = IUSDtbMinting.Route({addresses: targets, ratios: ratios}); // taker vm.startPrank(benefactor); - stETHToken.approve(address(UStbMintingContract), _stETHToDeposit); + stETHToken.approve(address(USDtbMintingContract), _stETHToDeposit); - bytes32 digest1 = UStbMintingContract.hashOrder(order); - IUStbMinting.Signature memory takerSignature = - signOrder(benefactorPrivateKey, digest1, IUStbMinting.SignatureType.EIP712); + bytes32 digest1 = USDtbMintingContract.hashOrder(order); + IUSDtbMinting.Signature memory takerSignature = + signOrder(benefactorPrivateKey, digest1, IUSDtbMinting.SignatureType.EIP712); vm.stopPrank(); assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit); vm.expectRevert(InvalidRoute); vm.prank(minter); - UStbMintingContract.mint(order, route, takerSignature); + USDtbMintingContract.mint(order, route, takerSignature); assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit); - assertEq(ustbToken.balanceOf(beneficiary), 0); + assertEq(usdtbToken.balanceOf(beneficiary), 0); - assertEq(stETHToken.balanceOf(address(UStbMintingContract)), 0); + assertEq(stETHToken.balanceOf(address(USDtbMintingContract)), 0); } function test_unsupported_assets_ERC20_revert() public { vm.startPrank(owner); - UStbMintingContract.removeSupportedAsset(address(stETHToken)); + USDtbMintingContract.removeSupportedAsset(address(stETHToken)); stETHToken.mint(_stETHToDeposit, benefactor); vm.stopPrank(); - IUStbMinting.Order memory order = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.MINT, + IUSDtbMinting.Order memory order = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.MINT, order_id: generateRandomOrderId(), expiry: uint120(block.timestamp + 10 minutes), nonce: 18, @@ -295,30 +295,30 @@ contract UStbMintingCoreTest is UStbMintingUtils { beneficiary: beneficiary, collateral_asset: address(stETHToken), collateral_amount: _stETHToDeposit, - ustb_amount: _ustbToMint + usdtb_amount: _usdtbToMint }); address[] memory targets = new address[](1); - targets[0] = address(UStbMintingContract); + targets[0] = address(USDtbMintingContract); uint128[] memory ratios = new uint128[](1); ratios[0] = 10_000; - IUStbMinting.Route memory route = IUStbMinting.Route({addresses: targets, ratios: ratios}); + IUSDtbMinting.Route memory route = IUSDtbMinting.Route({addresses: targets, ratios: ratios}); // taker vm.startPrank(benefactor); - stETHToken.approve(address(UStbMintingContract), _stETHToDeposit); + stETHToken.approve(address(USDtbMintingContract), _stETHToDeposit); - bytes32 digest1 = UStbMintingContract.hashOrder(order); - IUStbMinting.Signature memory takerSignature = - signOrder(benefactorPrivateKey, digest1, IUStbMinting.SignatureType.EIP712); + bytes32 digest1 = USDtbMintingContract.hashOrder(order); + IUSDtbMinting.Signature memory takerSignature = + signOrder(benefactorPrivateKey, digest1, IUSDtbMinting.SignatureType.EIP712); vm.stopPrank(); vm.recordLogs(); vm.expectRevert(UnsupportedAsset); vm.prank(minter); - UStbMintingContract.mint(order, route, takerSignature); + USDtbMintingContract.mint(order, route, takerSignature); vm.getRecordedLogs(); } @@ -327,8 +327,8 @@ contract UStbMintingCoreTest is UStbMintingUtils { vm.deal(benefactor, _stETHToDeposit); vm.stopPrank(); - IUStbMinting.Order memory order = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.MINT, + IUSDtbMinting.Order memory order = IUSDtbMinting.Order({ + order_type: IUSDtbMinting.OrderType.MINT, order_id: generateRandomOrderId(), expiry: uint120(block.timestamp + 10 minutes), nonce: 19, @@ -336,43 +336,43 @@ contract UStbMintingCoreTest is UStbMintingUtils { beneficiary: beneficiary, collateral_asset: NATIVE_TOKEN, collateral_amount: _stETHToDeposit, - ustb_amount: _ustbToMint + usdtb_amount: _usdtbToMint }); address[] memory targets = new address[](1); - targets[0] = address(UStbMintingContract); + targets[0] = address(USDtbMintingContract); uint128[] memory ratios = new uint128[](1); ratios[0] = 10_000; - IUStbMinting.Route memory route = IUStbMinting.Route({addresses: targets, ratios: ratios}); + IUSDtbMinting.Route memory route = IUSDtbMinting.Route({addresses: targets, ratios: ratios}); // taker vm.startPrank(benefactor); - stETHToken.approve(address(UStbMintingContract), _stETHToDeposit); + stETHToken.approve(address(USDtbMintingContract), _stETHToDeposit); - bytes32 digest1 = UStbMintingContract.hashOrder(order); - IUStbMinting.Signature memory takerSignature = - signOrder(benefactorPrivateKey, digest1, IUStbMinting.SignatureType.EIP712); + bytes32 digest1 = USDtbMintingContract.hashOrder(order); + IUSDtbMinting.Signature memory takerSignature = + signOrder(benefactorPrivateKey, digest1, IUSDtbMinting.SignatureType.EIP712); vm.stopPrank(); vm.recordLogs(); vm.expectRevert(UnsupportedAsset); vm.prank(minter); - UStbMintingContract.mint(order, route, takerSignature); + USDtbMintingContract.mint(order, route, takerSignature); vm.getRecordedLogs(); } function test_expired_orders_revert() public { - (IUStbMinting.Order memory order, IUStbMinting.Signature memory takerSignature, IUStbMinting.Route memory route) = - mint_setup(_ustbToMint, _stETHToDeposit, stETHToken, 1, false); + (IUSDtbMinting.Order memory order, IUSDtbMinting.Signature memory takerSignature, IUSDtbMinting.Route memory route) = + mint_setup(_usdtbToMint, _stETHToDeposit, stETHToken, 1, false); vm.warp(block.timestamp + 11 minutes); vm.recordLogs(); vm.expectRevert(SignatureExpired); vm.prank(minter); - UStbMintingContract.mint(order, route, takerSignature); + USDtbMintingContract.mint(order, route, takerSignature); vm.getRecordedLogs(); } @@ -381,13 +381,13 @@ contract UStbMintingCoreTest is UStbMintingUtils { vm.expectEmit(true, false, false, false); emit AssetAdded(asset); vm.startPrank(owner); - UStbMintingContract.addSupportedAsset(asset, assetConfig); - assertTrue(UStbMintingContract.isSupportedAsset(asset)); + USDtbMintingContract.addSupportedAsset(asset, assetConfig); + assertTrue(USDtbMintingContract.isSupportedAsset(asset)); vm.expectEmit(true, false, false, false); emit AssetRemoved(asset); - UStbMintingContract.removeSupportedAsset(asset); - assertFalse(UStbMintingContract.isSupportedAsset(asset)); + USDtbMintingContract.removeSupportedAsset(asset); + assertFalse(USDtbMintingContract.isSupportedAsset(asset)); } function test_cannot_add_asset_already_supported_revert() public { @@ -395,66 +395,66 @@ contract UStbMintingCoreTest is UStbMintingUtils { vm.expectEmit(true, false, false, false); emit AssetAdded(asset); vm.startPrank(owner); - UStbMintingContract.addSupportedAsset(asset, assetConfig); - assertTrue(UStbMintingContract.isSupportedAsset(asset)); + USDtbMintingContract.addSupportedAsset(asset, assetConfig); + assertTrue(USDtbMintingContract.isSupportedAsset(asset)); vm.expectRevert(InvalidAssetAddress); - UStbMintingContract.addSupportedAsset(asset, assetConfig); + USDtbMintingContract.addSupportedAsset(asset, assetConfig); } function test_cannot_removeAsset_not_supported_revert() public { address asset = address(20); - assertFalse(UStbMintingContract.isSupportedAsset(asset)); + assertFalse(USDtbMintingContract.isSupportedAsset(asset)); vm.prank(owner); vm.expectRevert(InvalidAssetAddress); - UStbMintingContract.removeSupportedAsset(asset); + USDtbMintingContract.removeSupportedAsset(asset); } function test_cannotAdd_addressZero_revert() public { vm.prank(owner); vm.expectRevert(InvalidAssetAddress); - UStbMintingContract.addSupportedAsset(address(0), assetConfig); + USDtbMintingContract.addSupportedAsset(address(0), assetConfig); } - function test_cannotAdd_UStb_revert() public { + function test_cannotAdd_USDtb_revert() public { vm.prank(owner); vm.expectRevert(InvalidAssetAddress); - UStbMintingContract.addSupportedAsset(address(ustbToken), stableConfig); + USDtbMintingContract.addSupportedAsset(address(usdtbToken), stableConfig); } function test_sending_redeem_order_to_mint_revert() public { - (IUStbMinting.Order memory order, IUStbMinting.Signature memory takerSignature) = + (IUSDtbMinting.Order memory order, IUSDtbMinting.Signature memory takerSignature) = redeem_setup(1 ether, 50 ether, stETHToken, 20, false); address[] memory targets = new address[](1); - targets[0] = address(UStbMintingContract); + targets[0] = address(USDtbMintingContract); uint128[] memory ratios = new uint128[](1); ratios[0] = 10_000; - IUStbMinting.Route memory route = IUStbMinting.Route({addresses: targets, ratios: ratios}); + IUSDtbMinting.Route memory route = IUSDtbMinting.Route({addresses: targets, ratios: ratios}); vm.expectRevert(InvalidOrder); vm.prank(minter); - UStbMintingContract.mint(order, route, takerSignature); + USDtbMintingContract.mint(order, route, takerSignature); } function test_sending_mint_order_to_redeem_revert() public { - (IUStbMinting.Order memory order, IUStbMinting.Signature memory takerSignature,) = + (IUSDtbMinting.Order memory order, IUSDtbMinting.Signature memory takerSignature,) = mint_setup(1 ether, 50 ether, stETHToken, 20, false); vm.expectRevert(InvalidOrder); vm.prank(redeemer); - UStbMintingContract.redeem(order, takerSignature); + USDtbMintingContract.redeem(order, takerSignature); } function test_receive_eth() public { - assertEq(address(UStbMintingContract).balance, 0); + assertEq(address(USDtbMintingContract).balance, 0); vm.deal(owner, 10_000 ether); vm.prank(owner); - (bool success,) = address(UStbMintingContract).call{value: 10_000 ether}(""); + (bool success,) = address(USDtbMintingContract).call{value: 10_000 ether}(""); assertTrue(success); - assertEq(address(UStbMintingContract).balance, 10_000 ether); + assertEq(address(USDtbMintingContract).balance, 10_000 ether); } } diff --git a/test/foundry/test/UStbMinting.Delegate.t.sol b/test/foundry/test/UStbMinting.Delegate.t.sol deleted file mode 100644 index 1bc3bfa..0000000 --- a/test/foundry/test/UStbMinting.Delegate.t.sol +++ /dev/null @@ -1,243 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "../UStbMinting.utils.sol"; - -contract UStbMintingDelegateTest is UStbMintingUtils { - function setUp() public override { - super.setUp(); - } - - function testDelegateSuccessfulMint() public { - (IUStbMinting.Order memory order,, IUStbMinting.Route memory route) = - mint_setup(_ustbToMint, _stETHToDeposit, stETHToken, 1, false); - - // request delegation - vm.prank(benefactor); - vm.expectEmit(); - emit DelegatedSignerInitiated(trader2, benefactor); - UStbMintingContract.setDelegatedSigner(trader2); - - assertEq( - uint256(UStbMintingContract.delegatedSigner(trader2, benefactor)), - uint256(IUStbMinting.DelegatedSignerStatus.PENDING), - "The delegation status should be pending" - ); - - bytes32 digest1 = UStbMintingContract.hashOrder(order); - - // accept delegation - vm.prank(trader2); - vm.expectEmit(); - emit DelegatedSignerAdded(trader2, benefactor); - UStbMintingContract.confirmDelegatedSigner(benefactor); - - assertEq( - uint256(UStbMintingContract.delegatedSigner(trader2, benefactor)), - uint256(IUStbMinting.DelegatedSignerStatus.ACCEPTED), - "The delegation status should be accepted" - ); - - IUStbMinting.Signature memory trader2Sig = signOrder(trader2PrivateKey, digest1, IUStbMinting.SignatureType.EIP712); - - assertEq( - stETHToken.balanceOf(address(UStbMintingContract)), 0, "Mismatch in Minting contract stETH balance before mint" - ); - assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit, "Mismatch in benefactor stETH balance before mint"); - assertEq(ustbToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary UStb balance before mint"); - - vm.prank(minter); - UStbMintingContract.mint(order, route, trader2Sig); - - assertEq( - stETHToken.balanceOf(address(UStbMintingContract)), - _stETHToDeposit, - "Mismatch in Minting contract stETH balance after mint" - ); - assertEq(stETHToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary stETH balance after mint"); - assertEq(ustbToken.balanceOf(beneficiary), _ustbToMint, "Mismatch in beneficiary UStb balance after mint"); - } - - function testDelegateFailureMint() public { - (IUStbMinting.Order memory order,, IUStbMinting.Route memory route) = - mint_setup(_ustbToMint, _stETHToDeposit, stETHToken, 1, false); - - bytes32 digest1 = UStbMintingContract.hashOrder(order); - - // accept delegation - vm.prank(trader2); - vm.expectRevert(IUStbMinting.DelegationNotInitiated.selector); - UStbMintingContract.confirmDelegatedSigner(benefactor); - - vm.prank(trader2); - IUStbMinting.Signature memory trader2Sig = signOrder(trader2PrivateKey, digest1, IUStbMinting.SignatureType.EIP712); - - assertEq( - stETHToken.balanceOf(address(UStbMintingContract)), 0, "Mismatch in Minting contract stETH balance before mint" - ); - assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit, "Mismatch in benefactor stETH balance before mint"); - assertEq(ustbToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary UStb balance before mint"); - - // assert that the delegation is rejected - assertEq( - uint256(UStbMintingContract.delegatedSigner(minter, trader2)), - uint256(IUStbMinting.DelegatedSignerStatus.REJECTED), - "The delegation status should be rejected" - ); - - vm.prank(minter); - vm.expectRevert(InvalidEIP712Signature); - UStbMintingContract.mint(order, route, trader2Sig); - - assertEq( - stETHToken.balanceOf(address(UStbMintingContract)), 0, "Mismatch in Minting contract stETH balance after mint" - ); - assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit, "Mismatch in beneficiary stETH balance after mint"); - assertEq(ustbToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary UStb balance after mint"); - } - - function testDelegateSuccessfulRedeem() public { - (IUStbMinting.Order memory order,) = redeem_setup(_ustbToMint, _stETHToDeposit, stETHToken, 1, false); - - // request delegation - vm.prank(beneficiary); - vm.expectEmit(); - emit DelegatedSignerInitiated(trader2, beneficiary); - UStbMintingContract.setDelegatedSigner(trader2); - - assertEq( - uint256(UStbMintingContract.delegatedSigner(trader2, beneficiary)), - uint256(IUStbMinting.DelegatedSignerStatus.PENDING), - "The delegation status should be pending" - ); - - bytes32 digest1 = UStbMintingContract.hashOrder(order); - - // accept delegation - vm.prank(trader2); - vm.expectEmit(); - emit DelegatedSignerAdded(trader2, beneficiary); - UStbMintingContract.confirmDelegatedSigner(beneficiary); - - assertEq( - uint256(UStbMintingContract.delegatedSigner(trader2, beneficiary)), - uint256(IUStbMinting.DelegatedSignerStatus.ACCEPTED), - "The delegation status should be accepted" - ); - - IUStbMinting.Signature memory trader2Sig = signOrder(trader2PrivateKey, digest1, IUStbMinting.SignatureType.EIP712); - - assertEq( - stETHToken.balanceOf(address(UStbMintingContract)), - _stETHToDeposit, - "Mismatch in Minting contract stETH balance before mint" - ); - assertEq(stETHToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary stETH balance before mint"); - assertEq(ustbToken.balanceOf(beneficiary), _ustbToMint, "Mismatch in beneficiary UStb balance before mint"); - - vm.prank(redeemer); - UStbMintingContract.redeem(order, trader2Sig); - - assertEq( - stETHToken.balanceOf(address(UStbMintingContract)), 0, "Mismatch in Minting contract stETH balance after mint" - ); - assertEq(stETHToken.balanceOf(beneficiary), _stETHToDeposit, "Mismatch in beneficiary stETH balance after mint"); - assertEq(ustbToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary UStb balance after mint"); - } - - function testDelegateFailureRedeem() public { - (IUStbMinting.Order memory order,) = redeem_setup(_ustbToMint, _stETHToDeposit, stETHToken, 1, false); - - bytes32 digest1 = UStbMintingContract.hashOrder(order); - vm.prank(trader2); - IUStbMinting.Signature memory trader2Sig = signOrder(trader2PrivateKey, digest1, IUStbMinting.SignatureType.EIP712); - - assertEq( - stETHToken.balanceOf(address(UStbMintingContract)), - _stETHToDeposit, - "Mismatch in Minting contract stETH balance before mint" - ); - assertEq(stETHToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary stETH balance before mint"); - assertEq(ustbToken.balanceOf(beneficiary), _ustbToMint, "Mismatch in beneficiary UStb balance before mint"); - - // assert that the delegation is rejected - assertEq( - uint256(UStbMintingContract.delegatedSigner(redeemer, trader2)), - uint256(IUStbMinting.DelegatedSignerStatus.REJECTED), - "The delegation status should be rejected" - ); - - vm.prank(redeemer); - vm.expectRevert(InvalidEIP712Signature); - UStbMintingContract.redeem(order, trader2Sig); - - assertEq( - stETHToken.balanceOf(address(UStbMintingContract)), - _stETHToDeposit, - "Mismatch in Minting contract stETH balance after mint" - ); - assertEq(stETHToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary stETH balance after mint"); - assertEq(ustbToken.balanceOf(beneficiary), _ustbToMint, "Mismatch in beneficiary UStb balance after mint"); - } - - function testCanUndelegate() public { - (IUStbMinting.Order memory order,, IUStbMinting.Route memory route) = - mint_setup(_ustbToMint, _stETHToDeposit, stETHToken, 1, false); - - // delegate request - vm.prank(benefactor); - vm.expectEmit(); - emit DelegatedSignerInitiated(trader2, benefactor); - UStbMintingContract.setDelegatedSigner(trader2); - - assertEq( - uint256(UStbMintingContract.delegatedSigner(trader2, benefactor)), - uint256(IUStbMinting.DelegatedSignerStatus.PENDING), - "The delegation status should be pending" - ); - - // accept the delegation - vm.prank(trader2); - vm.expectEmit(); - emit DelegatedSignerAdded(trader2, benefactor); - UStbMintingContract.confirmDelegatedSigner(benefactor); - - assertEq( - uint256(UStbMintingContract.delegatedSigner(trader2, benefactor)), - uint256(IUStbMinting.DelegatedSignerStatus.ACCEPTED), - "The delegation status should be accepted" - ); - - // remove the delegation - vm.prank(benefactor); - vm.expectEmit(); - emit DelegatedSignerRemoved(trader2, benefactor); - UStbMintingContract.removeDelegatedSigner(trader2); - - assertEq( - uint256(UStbMintingContract.delegatedSigner(trader2, benefactor)), - uint256(IUStbMinting.DelegatedSignerStatus.REJECTED), - "The delegation status should be accepted" - ); - - bytes32 digest1 = UStbMintingContract.hashOrder(order); - vm.prank(trader2); - IUStbMinting.Signature memory trader2Sig = signOrder(trader2PrivateKey, digest1, IUStbMinting.SignatureType.EIP712); - - assertEq( - stETHToken.balanceOf(address(UStbMintingContract)), 0, "Mismatch in Minting contract stETH balance before mint" - ); - assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit, "Mismatch in benefactor stETH balance before mint"); - assertEq(ustbToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary UStb balance before mint"); - - vm.prank(minter); - vm.expectRevert(InvalidEIP712Signature); - UStbMintingContract.mint(order, route, trader2Sig); - - assertEq( - stETHToken.balanceOf(address(UStbMintingContract)), 0, "Mismatch in Minting contract stETH balance after mint" - ); - assertEq(stETHToken.balanceOf(benefactor), _stETHToDeposit, "Mismatch in beneficiary stETH balance after mint"); - assertEq(ustbToken.balanceOf(beneficiary), 0, "Mismatch in beneficiary UStb balance after mint"); - } -} diff --git a/test/foundry/test/UStbMinting.StableRatios.t.sol b/test/foundry/test/UStbMinting.StableRatios.t.sol deleted file mode 100644 index 3e86e51..0000000 --- a/test/foundry/test/UStbMinting.StableRatios.t.sol +++ /dev/null @@ -1,209 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* solhint-disable func-name-mixedcase */ - -import "../UStbMinting.utils.sol"; - -contract UStbMintingStableRatiosTest is UStbMintingUtils { - function setUp() public override { - super.setUp(); - } - - function test_stable_ratios_setup() public { - uint128 stablesDeltaLimitZero = 0; // zero bps allowed (identical USDT and UStb amounts) - uint128 stablesDeltaLimitPositive = 577; // positive bps allowed - - vm.prank(owner); - UStbMintingContract.setStablesDeltaLimit(stablesDeltaLimitZero); - - vm.prank(owner); - UStbMintingContract.setStablesDeltaLimit(stablesDeltaLimitPositive); - } - - function test_verify_stables_limit() external { - vm.prank(benefactor); - USDTToken.mint(25000 * 10 ** 6); - - uint128 stablesDeltaLimit = 100; // 100 bps - - vm.prank(owner); - UStbMintingContract.setStablesDeltaLimit(stablesDeltaLimit); - - uint128 ustbAmount = 1000 * 10 ** 18; // 1,000 UStb - - uint128 usdtAmountAtUpperLimit = 1010 * 10 ** 6; // 100 bps above the USDT amount that should be at the upper bps limit - uint128 usdtAmountAtLowerLimit = 990 * 10 ** 6; // 100 bps below the USDT amount that should be at the lower bps limit - - address usdtAddress = address(USDTToken); - - assertEq( - UStbMintingContract.verifyStablesLimit( - usdtAmountAtUpperLimit, ustbAmount, usdtAddress, IUStbMinting.OrderType.MINT - ), - true - ); - assertEq( - UStbMintingContract.verifyStablesLimit( - usdtAmountAtLowerLimit, ustbAmount, usdtAddress, IUStbMinting.OrderType.REDEEM - ), - true - ); - } - - function test_stables_limit_minting_valid() public { - vm.prank(benefactor); - USDTToken.mint(2500 * 10 ** 6); // Ensuring there is enough USDT for testing - - uint128 stablesDeltaLimit = 100; // 100 bps - - vm.prank(owner); - UStbMintingContract.setStablesDeltaLimit(stablesDeltaLimit); - - uint128 ustbAmount = 1000 * 10 ** 18; // 1,000 UStb - - uint128 usdtAmountAtUpperLimit = 1010 * 10 ** 6; // 100 bps above the USDT amount that should be at the upper bps limit - uint128 usdtAmountAtLowerLimit = 990 * 10 ** 6; // 100 bps below the USDT amount that should be at the lower bps limit - - (IUStbMinting.Order memory orderLow, IUStbMinting.Signature memory signatureLow, IUStbMinting.Route memory routeLow) - = mint_setup(ustbAmount, usdtAmountAtLowerLimit, USDTToken, 1, true); - vm.prank(minter); - UStbMintingContract.mint(orderLow, routeLow, signatureLow); - - ( - IUStbMinting.Order memory orderHigh, - IUStbMinting.Signature memory signatureHigh, - IUStbMinting.Route memory routeHigh - ) = mint_setup(ustbAmount, usdtAmountAtUpperLimit, USDTToken, 2, true); - vm.prank(minter); - UStbMintingContract.mint(orderHigh, routeHigh, signatureHigh); - - assertEq(USDTToken.balanceOf(benefactor), 2500 * 10 ** 6 - usdtAmountAtLowerLimit - usdtAmountAtUpperLimit); - assertEq(USDTToken.balanceOf(address(UStbMintingContract)), usdtAmountAtLowerLimit + usdtAmountAtUpperLimit); - } - - function test_stable_ratios_minting_invalid() public { - vm.prank(benefactor); - USDTToken.mint(2500 * 10 ** 18); - - uint128 stablesDeltaLimit = 100; // 100 bps - vm.prank(owner); - UStbMintingContract.setStablesDeltaLimit(stablesDeltaLimit); - - uint128 ustbAmount = 1000 * 10 ** 18; // 1,000 UStb - uint128 collateralGreaterBreachStableLimit = 1011 * 10 ** 6; - (IUStbMinting.Order memory aOrder, IUStbMinting.Signature memory aTakerSignature, IUStbMinting.Route memory aRoute) - = mint_setup(ustbAmount, collateralGreaterBreachStableLimit, USDTToken, 1, true); - - vm.prank(minter); - UStbMintingContract.mint(aOrder, aRoute, aTakerSignature); - - uint128 collateralLessThanBreachesStableLimit = 989 * 10 ** 6; - (IUStbMinting.Order memory bOrder, IUStbMinting.Signature memory bTakerSignature, IUStbMinting.Route memory bRoute) - = mint_setup(ustbAmount, collateralLessThanBreachesStableLimit, USDTToken, 2, true); - - vm.expectRevert(InvalidStablePrice); - vm.prank(minter); - UStbMintingContract.mint(bOrder, bRoute, bTakerSignature); - } - - function test_stables_limit_redeem_valid() public { - vm.prank(address(UStbMintingContract)); - ustbToken.mint(beneficiary, 2500 * 10 ** 18); - - USDTToken.mint(2500 * 10 ** 6, benefactor); // initial mint - - uint128 stablesDeltaLimit = 100; // 100 bps - - vm.prank(owner); - UStbMintingContract.setStablesDeltaLimit(stablesDeltaLimit); - - uint128 ustbAmount = 1000 * 10 ** 18; // 1,000 UStb - - uint128 usdtAmountAtUpperLimit = 1010 * 10 ** 6; // 100 bps above the USDT amount that should be at the upper bps limit - uint128 usdtAmountAtLowerLimit = 990 * 10 ** 6; // 100 bps below the USDT amount that should be at the lower bps limit - - (IUStbMinting.Order memory orderLow, IUStbMinting.Signature memory signatureLow) = - redeem_setup(ustbAmount, usdtAmountAtLowerLimit, USDTToken, 1, true); - vm.prank(redeemer); - UStbMintingContract.redeem(orderLow, signatureLow); - - (IUStbMinting.Order memory orderHigh, IUStbMinting.Signature memory signatureHigh) = - redeem_setup(ustbAmount, usdtAmountAtUpperLimit, USDTToken, 2, true); - vm.prank(redeemer); - UStbMintingContract.redeem(orderHigh, signatureHigh); - - assertEq(USDTToken.balanceOf(beneficiary), usdtAmountAtLowerLimit + usdtAmountAtUpperLimit); - assertEq(USDTToken.balanceOf(address(UStbMintingContract)), 0); - } - - function test_stable_ratios_redeem_invalid() public { - vm.prank(address(UStbMintingContract)); - ustbToken.mint(beneficiary, 2500 * 10 ** 18); - - USDTToken.mint(2500 * 10 ** 6, address(UStbMintingContract)); - - uint128 stablesDeltaLimit = 100; // 100 bps - vm.prank(owner); - UStbMintingContract.setStablesDeltaLimit(stablesDeltaLimit); - - uint128 ustbAmount = 1000 * 10 ** 18; // 1,000 UStb - - address collateralAsset = address(USDTToken); - - // case 1 - uint128 collateralGreaterThanUStbAmount = 1011 * 10 ** 6; // 1011 USDT redeemed (greater than UStb) - IUStbMinting.Order memory redeemOrder2 = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.REDEEM, - order_id: generateRandomOrderId(), - expiry: uint120(block.timestamp + 10 minutes), - nonce: 2, - benefactor: beneficiary, - beneficiary: beneficiary, - collateral_asset: collateralAsset, - ustb_amount: ustbAmount, - collateral_amount: collateralGreaterThanUStbAmount - }); - - vm.startPrank(beneficiary); - ustbToken.approve(address(UStbMintingContract), ustbAmount); - - bytes32 digest2 = UStbMintingContract.hashOrder(redeemOrder2); - IUStbMinting.Signature memory takerSignature2 = - signOrder(beneficiaryPrivateKey, digest2, IUStbMinting.SignatureType.EIP712); - vm.stopPrank(); - - vm.expectRevert(InvalidStablePrice); - vm.prank(redeemer); - UStbMintingContract.redeem(redeemOrder2, takerSignature2); - - // case 2 - uint128 collateralLessThanUStbAmount = 989 * 10 ** 6; // 989 USDT redeemed (less than UStb) - IUStbMinting.Order memory redeemOrder1 = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.REDEEM, - order_id: generateRandomOrderId(), - expiry: uint120(block.timestamp + 10 minutes), - nonce: 1, - benefactor: beneficiary, - beneficiary: beneficiary, - collateral_asset: collateralAsset, - ustb_amount: ustbAmount, - collateral_amount: collateralLessThanUStbAmount - }); - - vm.startPrank(beneficiary); - ustbToken.approve(address(UStbMintingContract), ustbAmount); - - bytes32 digest1 = UStbMintingContract.hashOrder(redeemOrder1); - IUStbMinting.Signature memory takerSignature1 = - signOrder(beneficiaryPrivateKey, digest1, IUStbMinting.SignatureType.EIP712); - vm.stopPrank(); - - vm.startPrank(owner); - UStbMintingContract.grantRole(redeemerRole, redeemer); - vm.stopPrank(); - - vm.prank(redeemer); - UStbMintingContract.redeem(redeemOrder1, takerSignature1); - } -} diff --git a/test/foundry/test/UStbMinting.Whitelist.t.sol b/test/foundry/test/UStbMinting.Whitelist.t.sol deleted file mode 100644 index c86a696..0000000 --- a/test/foundry/test/UStbMinting.Whitelist.t.sol +++ /dev/null @@ -1,317 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* solhint-disable func-name-mixedcase */ - -import "../UStbMinting.utils.sol"; - -contract UStbMintingWhitelistTest is UStbMintingUtils { - function setUp() public override { - super.setUp(); - vm.deal(benefactor, _stETHToDeposit); - } - - function generate_nonce() public view returns (uint128) { - return uint128(uint256(keccak256(abi.encodePacked(block.timestamp, block.prevrandao, msg.sender)))); - } - - function test_whitelist_mint() public { - IUStbMinting.Order memory order = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.MINT, - order_id: generateRandomOrderId(), - expiry: uint120(block.timestamp + 10 minutes), - nonce: generate_nonce(), - benefactor: benefactor, - beneficiary: beneficiary, - collateral_asset: address(stETHToken), - collateral_amount: _stETHToDeposit, - ustb_amount: _ustbToMint / 2 - }); - - address[] memory targets = new address[](1); - targets[0] = address(UStbMintingContract); - - uint128[] memory ratios = new uint128[](1); - ratios[0] = 10_000; - - IUStbMinting.Route memory route = IUStbMinting.Route({addresses: targets, ratios: ratios}); - - // taker - vm.startPrank(benefactor); - stETHToken.approve(address(UStbMintingContract), _stETHToDeposit); - - bytes32 digest1 = UStbMintingContract.hashOrder(order); - IUStbMinting.Signature memory takerSignature = - signOrder(benefactorPrivateKey, digest1, IUStbMinting.SignatureType.EIP712); - vm.stopPrank(); - - vm.prank(owner); - UStbMintingContract.removeWhitelistedBenefactor(benefactor); - - vm.expectRevert(BenefactorNotWhitelisted); - vm.prank(minter); - UStbMintingContract.mint(order, route, takerSignature); - - vm.prank(owner); - UStbMintingContract.addWhitelistedBenefactor(benefactor); - vm.prank(minter); - UStbMintingContract.mint(order, route, takerSignature); - - // assert balances - assertEq(stETHToken.balanceOf(address(benefactor)), 0); - assertEq(stETHToken.balanceOf(address(UStbMintingContract)), _stETHToDeposit); - assertEq(ustbToken.balanceOf(address(beneficiary)), _ustbToMint / 2); - } - - function test_whitelist_redeem() public { - (IUStbMinting.Order memory mintOrder, IUStbMinting.Signature memory sig, IUStbMinting.Route memory route) = - mint_setup(_ustbToMint, _stETHToDeposit, stETHToken, 1, false); - - vm.prank(minter); - UStbMintingContract.mint(mintOrder, route, sig); - - IUStbMinting.Order memory redeemOrder = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.REDEEM, - order_id: generateRandomOrderId(), - expiry: uint120(block.timestamp + 10 minutes), - nonce: 47, - benefactor: beneficiary, - beneficiary: benefactor, // switched - collateral_asset: address(stETHToken), - collateral_amount: _stETHToDeposit, - ustb_amount: _ustbToMint - }); - - // taker - vm.startPrank(beneficiary); - ustbToken.approve(address(UStbMintingContract), _ustbToMint); - - bytes32 redeemDigest = UStbMintingContract.hashOrder(redeemOrder); - IUStbMinting.Signature memory takerSignature = - signOrder(beneficiaryPrivateKey, redeemDigest, IUStbMinting.SignatureType.EIP712); - vm.stopPrank(); - - vm.startPrank(owner); - vm.expectRevert(InvalidAddress); - UStbMintingContract.removeWhitelistedBenefactor(owner); - - UStbMintingContract.removeWhitelistedBenefactor(beneficiary); - vm.stopPrank(); - - vm.expectRevert(BenefactorNotWhitelisted); - vm.prank(redeemer); - UStbMintingContract.redeem(redeemOrder, takerSignature); - - vm.prank(owner); - UStbMintingContract.addWhitelistedBenefactor(beneficiary); - vm.prank(redeemer); - UStbMintingContract.redeem(redeemOrder, takerSignature); - - assertEq(stETHToken.balanceOf(address(benefactor)), _stETHToDeposit); - assertEq(stETHToken.balanceOf(address(UStbMintingContract)), 0); - assertEq(ustbToken.balanceOf(address(beneficiary)), 0); - } - - function test_non_whitelisted_beneficiary_mint() public { - IUStbMinting.Order memory order = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.MINT, - order_id: generateRandomOrderId(), - expiry: uint120(block.timestamp + 10 minutes), - nonce: generate_nonce(), - benefactor: benefactor, - beneficiary: owner, - collateral_asset: address(stETHToken), - collateral_amount: _stETHToDeposit, - ustb_amount: _ustbToMint / 2 - }); - - address[] memory targets = new address[](1); - targets[0] = address(UStbMintingContract); - - uint128[] memory ratios = new uint128[](1); - ratios[0] = 10_000; - - IUStbMinting.Route memory route = IUStbMinting.Route({addresses: targets, ratios: ratios}); - - // taker - vm.startPrank(benefactor); - stETHToken.approve(address(UStbMintingContract), _stETHToDeposit); - - bytes32 digest1 = UStbMintingContract.hashOrder(order); - IUStbMinting.Signature memory takerSignature = - signOrder(benefactorPrivateKey, digest1, IUStbMinting.SignatureType.EIP712); - vm.stopPrank(); - - vm.expectRevert(BeneficiaryNotApproved); - vm.prank(minter); - UStbMintingContract.mint(order, route, takerSignature); - - vm.prank(benefactor); - UStbMintingContract.setApprovedBeneficiary(owner, true); - vm.prank(minter); - UStbMintingContract.mint(order, route, takerSignature); - - // assert balances - assertEq(stETHToken.balanceOf(address(benefactor)), 0); - assertEq(stETHToken.balanceOf(address(UStbMintingContract)), _stETHToDeposit); - assertEq(ustbToken.balanceOf(address(owner)), _ustbToMint / 2); - } - - function test_non_whitelisted_beneficiary_redeem() public { - vm.prank(benefactor); - UStbMintingContract.setApprovedBeneficiary(owner, true); - IUStbMinting.Order memory order = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.MINT, - order_id: generateRandomOrderId(), - expiry: uint120(block.timestamp + 10 minutes), - nonce: 3423423, - benefactor: benefactor, - beneficiary: owner, - collateral_asset: address(stETHToken), - ustb_amount: _ustbToMint, - collateral_amount: _stETHToDeposit - }); - - address[] memory targets = new address[](1); - targets[0] = address(UStbMintingContract); - - uint128[] memory ratios = new uint128[](1); - ratios[0] = 10_000; - - IUStbMinting.Route memory route = IUStbMinting.Route({addresses: targets, ratios: ratios}); - - vm.startPrank(benefactor); - bytes32 digest1 = UStbMintingContract.hashOrder(order); - IUStbMinting.Signature memory takerSignature = - signOrder(benefactorPrivateKey, digest1, IUStbMinting.SignatureType.EIP712); - IERC20(address(stETHToken)).approve(address(UStbMintingContract), _stETHToDeposit); - vm.stopPrank(); - - vm.prank(minter); - UStbMintingContract.mint(order, route, takerSignature); - - IUStbMinting.Order memory redeemOrder = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.REDEEM, - order_id: generateRandomOrderId(), - expiry: uint120(block.timestamp + 10 minutes), - nonce: 44524527, - benefactor: owner, - beneficiary: beneficiary, - collateral_asset: address(stETHToken), - collateral_amount: _stETHToDeposit, - ustb_amount: _ustbToMint - }); - - // taker - vm.startPrank(owner); - ustbToken.approve(address(UStbMintingContract), _ustbToMint); - - bytes32 redeemDigest = UStbMintingContract.hashOrder(redeemOrder); - IUStbMinting.Signature memory redeemTakerSignature = - signOrder(ownerPrivateKey, redeemDigest, IUStbMinting.SignatureType.EIP712); - vm.stopPrank(); - - vm.startPrank(redeemer); - vm.expectRevert(BenefactorNotWhitelisted); - UStbMintingContract.redeem(redeemOrder, redeemTakerSignature); - vm.stopPrank(); - - vm.startPrank(owner); - UStbMintingContract.addWhitelistedBenefactor(owner); - vm.stopPrank(); - - vm.startPrank(redeemer); - vm.expectRevert(BeneficiaryNotApproved); - UStbMintingContract.redeem(redeemOrder, redeemTakerSignature); - vm.stopPrank(); - - vm.startPrank(owner); - UStbMintingContract.setApprovedBeneficiary(beneficiary, true); - vm.stopPrank(); - - vm.prank(redeemer); - UStbMintingContract.redeem(redeemOrder, redeemTakerSignature); - } - - function test_whitelisted_beneficiary_whitelist_enabled_transfer_redeem() public { - vm.prank(benefactor); - UStbMintingContract.setApprovedBeneficiary(owner, true); - IUStbMinting.Order memory order = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.MINT, - order_id: generateRandomOrderId(), - expiry: uint120(block.timestamp + 10 minutes), - nonce: 3423423, - benefactor: benefactor, - beneficiary: owner, - collateral_asset: address(stETHToken), - ustb_amount: _ustbToMint, - collateral_amount: _stETHToDeposit - }); - - address[] memory targets = new address[](1); - targets[0] = address(UStbMintingContract); - - uint128[] memory ratios = new uint128[](1); - ratios[0] = 10_000; - - IUStbMinting.Route memory route = IUStbMinting.Route({addresses: targets, ratios: ratios}); - - vm.startPrank(benefactor); - bytes32 digest1 = UStbMintingContract.hashOrder(order); - IUStbMinting.Signature memory takerSignature = - signOrder(benefactorPrivateKey, digest1, IUStbMinting.SignatureType.EIP712); - IERC20(address(stETHToken)).approve(address(UStbMintingContract), _stETHToDeposit); - vm.stopPrank(); - - vm.prank(minter); - UStbMintingContract.mint(order, route, takerSignature); - - // set the transfer state to WHITELIST_ENABLED - vm.startPrank(newOwner); - ustbToken.updateTransferState(IUStbDefinitions.TransferState.WHITELIST_ENABLED); - ustbToken.grantRole(keccak256("WHITELISTED_ROLE"), owner); - vm.stopPrank(); - - IUStbMinting.Order memory redeemOrder = IUStbMinting.Order({ - order_type: IUStbMinting.OrderType.REDEEM, - order_id: generateRandomOrderId(), - expiry: uint120(block.timestamp + 10 minutes), - nonce: 44524527, - benefactor: owner, - beneficiary: beneficiary, - collateral_asset: address(stETHToken), - collateral_amount: _stETHToDeposit, - ustb_amount: _ustbToMint - }); - - // taker - vm.startPrank(owner); - ustbToken.approve(address(UStbMintingContract), _ustbToMint); - - bytes32 redeemDigest = UStbMintingContract.hashOrder(redeemOrder); - IUStbMinting.Signature memory redeemTakerSignature = - signOrder(ownerPrivateKey, redeemDigest, IUStbMinting.SignatureType.EIP712); - vm.stopPrank(); - - vm.startPrank(redeemer); - vm.expectRevert(BenefactorNotWhitelisted); - UStbMintingContract.redeem(redeemOrder, redeemTakerSignature); - vm.stopPrank(); - - vm.startPrank(owner); - UStbMintingContract.addWhitelistedBenefactor(owner); - vm.stopPrank(); - - vm.startPrank(redeemer); - vm.expectRevert(BeneficiaryNotApproved); - UStbMintingContract.redeem(redeemOrder, redeemTakerSignature); - vm.stopPrank(); - - vm.startPrank(owner); - UStbMintingContract.setApprovedBeneficiary(beneficiary, true); - vm.stopPrank(); - - vm.prank(redeemer); - UStbMintingContract.redeem(redeemOrder, redeemTakerSignature); - } -}