From bdc453a92acc2b399422b25510656fffe3723c5a Mon Sep 17 00:00:00 2001 From: aliarbak Date: Wed, 3 Jan 2024 12:14:25 +0300 Subject: [PATCH 01/55] Remove _compliance parameter from setSupplyLimit function of the SupplyLimitModule (#183) --- CHANGELOG.md | 4 ++++ .../modular/modules/SupplyLimitModule.sol | 6 ++--- package-lock.json | 4 ++-- package.json | 2 +- test/compliances/module-supply-limit.test.ts | 24 ++++--------------- 5 files changed, 15 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80a4dc38..9753537c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## [4.1.2] +- **Compliance Modules**: + - Removed `_compliance` parameter from `setSupplyLimit` function of the `SupplyLimitModule` + ## [4.1.1] No changes, republishing package. diff --git a/contracts/compliance/modular/modules/SupplyLimitModule.sol b/contracts/compliance/modular/modules/SupplyLimitModule.sol index 15c14ece..00bafc30 100644 --- a/contracts/compliance/modular/modules/SupplyLimitModule.sol +++ b/contracts/compliance/modular/modules/SupplyLimitModule.sol @@ -84,9 +84,9 @@ contract SupplyLimitModule is AbstractModule { * Only the owner of the Compliance smart contract can call this function * emits an `SupplyLimitSet` event */ - function setSupplyLimit(address _compliance, uint256 _limit) external onlyComplianceCall { - _supplyLimits[_compliance] = _limit; - emit SupplyLimitSet(_compliance, _limit); + function setSupplyLimit(uint256 _limit) external onlyComplianceCall { + _supplyLimits[msg.sender] = _limit; + emit SupplyLimitSet(msg.sender, _limit); } /** diff --git a/package-lock.json b/package-lock.json index ba8037dd..0fb59117 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@tokenysolutions/t-rex", - "version": "4.1.1", + "version": "4.1.2-beta1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@tokenysolutions/t-rex", - "version": "4.1.0-beta5", + "version": "4.1.2-beta1", "license": "SEE LICENSE IN LICENSE.md", "devDependencies": { "@commitlint/cli": "^17.6.1", diff --git a/package.json b/package.json index 55686019..d354820d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tokenysolutions/t-rex", - "version": "4.1.1", + "version": "4.1.2", "description": "A fully compliant environment for the issuance and use of tokenized securities.", "main": "index.js", "directories": { diff --git a/test/compliances/module-supply-limit.test.ts b/test/compliances/module-supply-limit.test.ts index d2530ce8..f1b8a7ff 100644 --- a/test/compliances/module-supply-limit.test.ts +++ b/test/compliances/module-supply-limit.test.ts @@ -69,9 +69,7 @@ describe('Compliance Module: SupplyLimit', () => { it('should revert', async () => { const context = await loadFixture(deploySupplyLimitFixture); - await expect(context.suite.complianceModule.setSupplyLimit(context.suite.compliance.address, 100)).to.revertedWith( - 'only bound compliance can call', - ); + await expect(context.suite.complianceModule.setSupplyLimit(100)).to.revertedWith('only bound compliance can call'); }); }); @@ -80,10 +78,7 @@ describe('Compliance Module: SupplyLimit', () => { const context = await loadFixture(deploySupplyLimitFixture); const tx = await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setSupplyLimit(address _compliance, uint256 _limit)']).encodeFunctionData('setSupplyLimit', [ - context.suite.compliance.address, - 100, - ]), + new ethers.utils.Interface(['function setSupplyLimit(uint256 _limit)']).encodeFunctionData('setSupplyLimit', [100]), context.suite.complianceModule.address, ); @@ -97,10 +92,7 @@ describe('Compliance Module: SupplyLimit', () => { it('should return', async () => { const context = await loadFixture(deploySupplyLimitFixture); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setSupplyLimit(address _compliance, uint256 _limit)']).encodeFunctionData('setSupplyLimit', [ - context.suite.compliance.address, - 1600, - ]), + new ethers.utils.Interface(['function setSupplyLimit(uint256 _limit)']).encodeFunctionData('setSupplyLimit', [1600]), context.suite.complianceModule.address, ); const supplyLimit = await context.suite.complianceModule.getSupplyLimit(context.suite.compliance.address); @@ -118,10 +110,7 @@ describe('Compliance Module: SupplyLimit', () => { const from = zeroAddress; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setSupplyLimit(address _compliance, uint256 _limit)']).encodeFunctionData('setSupplyLimit', [ - context.suite.compliance.address, - 1600, - ]), + new ethers.utils.Interface(['function setSupplyLimit(uint256 _limit)']).encodeFunctionData('setSupplyLimit', [1600]), context.suite.complianceModule.address, ); @@ -137,10 +126,7 @@ describe('Compliance Module: SupplyLimit', () => { const from = zeroAddress; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setSupplyLimit(address _compliance, uint256 _limit)']).encodeFunctionData('setSupplyLimit', [ - context.suite.compliance.address, - 1600, - ]), + new ethers.utils.Interface(['function setSupplyLimit(uint256 _limit)']).encodeFunctionData('setSupplyLimit', [1600]), context.suite.complianceModule.address, ); From fced25a44b1144d2ca7458e37337ceed46957700 Mon Sep 17 00:00:00 2001 From: joachimlebrun Date: Fri, 9 Feb 2024 17:28:32 +0100 Subject: [PATCH 02/55] :sparkles: () add permissioning --- contracts/token/IToken.sol | 117 ++++++++++++++++++++++++------- contracts/token/Token.sol | 57 +++++++++++++++ contracts/token/TokenStorage.sol | 5 +- contracts/token/TokenStructs.sol | 75 ++++++++++++++++++++ 4 files changed, 226 insertions(+), 28 deletions(-) create mode 100644 contracts/token/TokenStructs.sol diff --git a/contracts/token/IToken.sol b/contracts/token/IToken.sol index 9f123142..77e3db39 100644 --- a/contracts/token/IToken.sol +++ b/contracts/token/IToken.sol @@ -66,6 +66,7 @@ pragma solidity 0.8.17; import "../registry/interface/IIdentityRegistry.sol"; import "../compliance/modular/IModularCompliance.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "./TokenStructs.sol"; /// @dev interface interface IToken is IERC20 { @@ -148,6 +149,29 @@ interface IToken is IERC20 { */ event Unpaused(address _userAddress); + + /** + * This event is emitted when restrictions on an agent's roles are updated. + * The event is emitted by the `setAgentRestrictions` function. + * `agent` is the address of the agent whose roles are being restricted. + * `disableMint` indicates whether the agent is restricted from minting tokens. + * `disableBurn` indicates whether the agent is restricted from burning tokens. + * `disableAddressFreeze` indicates whether the agent is restricted from freezing addresses. + * `disableForceTransfer` indicates whether the agent is restricted from forcing transfers. + * `disablePartialFreeze` indicates whether the agent is restricted from partially freezing tokens. + * `disablePause` indicates whether the agent is restricted from pausing the token contract. + * `disableRecovery` indicates whether the agent is restricted from performing recovery operations. + */ + event AgentRestrictionsSet( + address indexed agent, + bool disableMint, + bool disableBurn, + bool disableAddressFreeze, + bool disableForceTransfer, + bool disablePartialFreeze, + bool disablePause, + bool disableRecovery ); + /// functions /** @@ -175,45 +199,67 @@ interface IToken is IERC20 { function setOnchainID(address _onchainID) external; /** - * @dev pauses the token contract, when contract is paused investors cannot transfer tokens anymore - * This function can only be called by a wallet set as agent of the token - * emits a `Paused` event - */ + * @dev Pauses the token contract. When the contract is paused, investors cannot transfer tokens anymore. + * This function can only be called by an agent of the token, provided the agent is not restricted from pausing the token. + * emits a `Paused` event upon successful execution. + * To pause token transfers, the calling agent must have pausing capabilities enabled. + * If the agent is disabled from pausing, the function call will fail. + * The function can be called only when the contract is not already paused. + * error AgentNotAuthorized - Thrown if the agent is disabled from pausing the token, + * indicating they do not have the necessary permissions to execute this function. + */ function pause() external; /** - * @dev unpauses the token contract, when contract is unpaused investors can transfer tokens - * if their wallet is not blocked & if the amount to transfer is <= to the amount of free tokens - * This function can only be called by a wallet set as agent of the token - * emits an `Unpaused` event - */ + * @dev Unpauses the token contract, allowing investors to resume token transfers under normal conditions + * This function can only be called by an agent of the token, provided the agent is not restricted from pausing the token. + * emits an `Unpaused` event upon successful execution. + * To unpause token transfers, the calling agent must have pausing capabilities enabled. + * If the agent is disabled from pausing, the function call will fail. + * The function can be called only when the contract is currently paused. + * error AgentNotAuthorized - Thrown if the agent is disabled from pausing the token, + * indicating they do not have the necessary permissions to execute this function. + */ function unpause() external; /** - * @dev sets an address frozen status for this token. - * @param _userAddress The address for which to update frozen status - * @param _freeze Frozen status of the address - * This function can only be called by a wallet set as agent of the token - * emits an `AddressFrozen` event - */ + * @dev Sets an address's frozen status for this token, + * either freezing or unfreezing the address based on the provided boolean value. + * This function can be called by an agent of the token, assuming the agent is not restricted from freezing addresses. + * emits an `AddressFrozen` event upon successful execution. + * @param _userAddress The address for which to update the frozen status. + * @param _freeze The frozen status to be applied: `true` to freeze, `false` to unfreeze. + * @notice To change an address's frozen status, the calling agent must have the capability to freeze addresses enabled. + * If the agent is disabled from freezing addresses, the function call will fail. + * error AgentNotAuthorized - Thrown if the agent is disabled from freezing addresses, + * indicating they do not have the necessary permissions to execute this function. + */ function setAddressFrozen(address _userAddress, bool _freeze) external; /** - * @dev freezes token amount specified for given address. - * @param _userAddress The address for which to update frozen tokens - * @param _amount Amount of Tokens to be frozen - * This function can only be called by a wallet set as agent of the token - * emits a `TokensFrozen` event - */ + * @dev Freezes a specified token amount for a given address, preventing those tokens from being transferred. + * This function can be called by an agent of the token, provided the agent is not restricted from freezing tokens. + * emits a `TokensFrozen` event upon successful execution. + * @param _userAddress The address for which to freeze tokens. + * @param _amount The amount of tokens to be frozen. + * @notice To freeze tokens for an address, the calling agent must have the capability to freeze tokens enabled. + * If the agent is disabled from freezing tokens, the function call will fail. + * error AgentNotAuthorized - Thrown if the agent is disabled from freezing tokens, + * indicating they do not have the necessary permissions to execute this function. + */ function freezePartialTokens(address _userAddress, uint256 _amount) external; /** - * @dev unfreezes token amount specified for given address - * @param _userAddress The address for which to update frozen tokens - * @param _amount Amount of Tokens to be unfrozen - * This function can only be called by a wallet set as agent of the token - * emits a `TokensUnfrozen` event - */ + * @dev Unfreezes a specified token amount for a given address, allowing those tokens to be transferred again. + * This function can be called by an agent of the token, assuming the agent is not restricted from unfreezing tokens. + * emits a `TokensUnfrozen` event upon successful execution. + * @param _userAddress The address for which to unfreeze tokens. + * @param _amount The amount of tokens to be unfrozen. + * @notice To unfreeze tokens for an address, the calling agent must have the capability to unfreeze tokens enabled. + * If the agent is disabled from unfreezing tokens, the function call will fail. + * error AgentNotAuthorized - Thrown if the agent is disabled from unfreezing tokens, + * indicating they do not have the necessary permissions to execute this function. + */ function unfreezePartialTokens(address _userAddress, uint256 _amount) external; /** @@ -388,6 +434,17 @@ interface IToken is IERC20 { */ function batchUnfreezePartialTokens(address[] calldata _userAddresses, uint256[] calldata _amounts) external; + /** + * @dev Set restrictions on agent's roles. + * This function can only be called by the contract owner, as enforced by the `onlyOwner` modifier. + * emits an `AgentRestrictionsSet` event upon successfully updating an agent's restrictions. + * @param agent The address of the agent whose permissions are being modified. + * @param restrictions A `TokenRoles` struct containing boolean flags for each role to be restricted. + * Each flag set to `true` disables the corresponding capability for the agent. + * throws AddressNotAgent error if the specified address is not an agent. + */ + function setAgentRestrictions(address agent, TokenRoles memory restrictions) external; + /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should @@ -457,4 +514,10 @@ interface IToken is IERC20 { * @param _userAddress the address of the wallet on which getFrozenTokens is called */ function getFrozenTokens(address _userAddress) external view returns (uint256); + + /** + * @dev Returns A `TokenRoles` struct containing boolean flags for each restricted role. + * Each flag set to `true` disables the corresponding capability for the agent. + */ + function getAgentRestrictions(address agent) external view returns (TokenRoles memory); } diff --git a/contracts/token/Token.sol b/contracts/token/Token.sol index 4ea30918..6b4b4ff2 100755 --- a/contracts/token/Token.sol +++ b/contracts/token/Token.sol @@ -70,6 +70,10 @@ import "../roles/AgentRoleUpgradeable.sol"; contract Token is IToken, AgentRoleUpgradeable, TokenStorage { + error AddressNotAgent(address agent); + + error AgentNotAuthorized(address agent, string reason); + /// modifiers /// @dev Modifier to make a function callable only when the contract is not paused. @@ -186,6 +190,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-pause}. */ function pause() external override onlyAgent whenNotPaused { + if(getAgentRestrictions(msg.sender).disablePause) { + revert AgentNotAuthorized(msg.sender, "pause disabled"); + } _tokenPaused = true; emit Paused(msg.sender); } @@ -194,6 +201,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-unpause}. */ function unpause() external override onlyAgent whenPaused { + if(getAgentRestrictions(msg.sender).disablePause) { + revert AgentNotAuthorized(msg.sender, "pause disabled"); + } _tokenPaused = false; emit Unpaused(msg.sender); } @@ -207,6 +217,25 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { } } + /** + * @dev See {IToken-setAgentRestrictions}. + */ + function setAgentRestrictions(address agent, TokenRoles memory restrictions) external override onlyOwner { + if(!isAgent(agent)) { + revert AddressNotAgent(agent); + } + _agentsRestrictions[agent] = restrictions; + emit AgentRestrictionsSet( + agent, + restrictions.disableMint, + restrictions.disableBurn, + restrictions.disableAddressFreeze, + restrictions.disableForceTransfer, + restrictions.disablePartialFreeze, + restrictions.disablePause, + restrictions.disableRecovery ); + } + /** * @notice ERC-20 overridden function that include logic to check for trade validity. * Require that the from and to addresses are not frozen. @@ -299,6 +328,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { address _newWallet, address _investorOnchainID ) external override onlyAgent returns (bool) { + if(getAgentRestrictions(msg.sender).disableRecovery) { + revert AgentNotAuthorized(msg.sender, "recovery disabled"); + } require(balanceOf(_lostWallet) != 0, "no tokens to recover"); IIdentity _onchainID = IIdentity(_investorOnchainID); bytes32 _key = keccak256(abi.encode(_newWallet)); @@ -433,6 +465,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { address _to, uint256 _amount ) public override onlyAgent returns (bool) { + if(getAgentRestrictions(msg.sender).disableForceTransfer) { + revert AgentNotAuthorized(msg.sender, "forceTransfer disabled"); + } require(balanceOf(_from) >= _amount, "sender balance too low"); uint256 freeBalance = balanceOf(_from) - (_frozenTokens[_from]); if (_amount > freeBalance) { @@ -452,6 +487,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-mint}. */ function mint(address _to, uint256 _amount) public override onlyAgent { + if(getAgentRestrictions(msg.sender).disableMint) { + revert AgentNotAuthorized(msg.sender, "mint disabled"); + } require(_tokenIdentityRegistry.isVerified(_to), "Identity is not verified."); require(_tokenCompliance.canTransfer(address(0), _to, _amount), "Compliance not followed"); _mint(_to, _amount); @@ -462,6 +500,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-burn}. */ function burn(address _userAddress, uint256 _amount) public override onlyAgent { + if(getAgentRestrictions(msg.sender).disableBurn) { + revert AgentNotAuthorized(msg.sender, "burn disabled"); + } require(balanceOf(_userAddress) >= _amount, "cannot burn more than balance"); uint256 freeBalance = balanceOf(_userAddress) - _frozenTokens[_userAddress]; if (_amount > freeBalance) { @@ -477,6 +518,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-setAddressFrozen}. */ function setAddressFrozen(address _userAddress, bool _freeze) public override onlyAgent { + if(getAgentRestrictions(msg.sender).disableAddressFreeze) { + revert AgentNotAuthorized(msg.sender, "address freeze disabled"); + } _frozen[_userAddress] = _freeze; emit AddressFrozen(_userAddress, _freeze, msg.sender); @@ -486,6 +530,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-freezePartialTokens}. */ function freezePartialTokens(address _userAddress, uint256 _amount) public override onlyAgent { + if(getAgentRestrictions(msg.sender).disablePartialFreeze) { + revert AgentNotAuthorized(msg.sender, "partial freeze disabled"); + } uint256 balance = balanceOf(_userAddress); require(balance >= _frozenTokens[_userAddress] + _amount, "Amount exceeds available balance"); _frozenTokens[_userAddress] = _frozenTokens[_userAddress] + (_amount); @@ -496,6 +543,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-unfreezePartialTokens}. */ function unfreezePartialTokens(address _userAddress, uint256 _amount) public override onlyAgent { + if(getAgentRestrictions(msg.sender).disablePartialFreeze) { + revert AgentNotAuthorized(msg.sender, "partial freeze disabled"); + } require(_frozenTokens[_userAddress] >= _amount, "Amount should be less than or equal to frozen tokens"); _frozenTokens[_userAddress] = _frozenTokens[_userAddress] - (_amount); emit TokensUnfrozen(_userAddress, _amount); @@ -528,6 +578,13 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { return _balances[_userAddress]; } + /** + * @dev See {IToken-getAgentRestrictions}. + */ + function getAgentRestrictions(address agent) public view override returns (TokenRoles memory) { + return _agentsRestrictions[agent]; + } + /** * @dev See {ERC20-_transfer}. */ diff --git a/contracts/token/TokenStorage.sol b/contracts/token/TokenStorage.sol index 046f44bc..b1c91d00 100644 --- a/contracts/token/TokenStorage.sol +++ b/contracts/token/TokenStorage.sol @@ -64,6 +64,7 @@ pragma solidity 0.8.17; import "../compliance/modular/IModularCompliance.sol"; import "../registry/interface/IIdentityRegistry.sol"; +import "./TokenStructs.sol"; contract TokenStorage { /// @dev ERC20 basic variables @@ -90,9 +91,11 @@ contract TokenStorage { /// @dev Compliance contract linked to the onchain validator system IModularCompliance internal _tokenCompliance; + mapping(address => TokenRoles) internal _agentsRestrictions; + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. */ - uint256[49] private __gap; + uint256[48] private __gap; } diff --git a/contracts/token/TokenStructs.sol b/contracts/token/TokenStructs.sol new file mode 100644 index 00000000..e8032f6e --- /dev/null +++ b/contracts/token/TokenStructs.sol @@ -0,0 +1,75 @@ + +// SPDX-License-Identifier: GPL-3.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// + +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2023, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +pragma solidity 0.8.17; + + struct TokenRoles { + bool disableMint; + bool disableBurn; + bool disablePartialFreeze; + bool disableAddressFreeze; + bool disableRecovery; + bool disableForceTransfer; + bool disablePause; + } From feff21fa87778dba9b590b826d03803cc3af8b9a Mon Sep 17 00:00:00 2001 From: "ali.arbak" Date: Mon, 12 Feb 2024 17:23:39 +0300 Subject: [PATCH 03/55] Add unit tests for token permissioning --- test/token/token-agent-restrictions.test.ts | 99 ++++++++++ test/token/token-information.test.ts | 43 +++++ test/token/token-recovery.test.ts | 28 +++ test/token/token-transfer.test.ts | 199 +++++++++++++++++++- 4 files changed, 368 insertions(+), 1 deletion(-) create mode 100644 test/token/token-agent-restrictions.test.ts diff --git a/test/token/token-agent-restrictions.test.ts b/test/token/token-agent-restrictions.test.ts new file mode 100644 index 00000000..2cb2d8ca --- /dev/null +++ b/test/token/token-agent-restrictions.test.ts @@ -0,0 +1,99 @@ +import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { expect } from 'chai'; +import { deployFullSuiteFixture } from '../fixtures/deploy-full-suite.fixture'; + +describe('Token - Agent Restrictions', () => { + describe('.setAgentRestrictions()', () => { + describe('when the caller is not the owner', () => { + it('should revert', async () => { + const { + suite: { token }, + accounts: { anotherWallet, tokenAgent }, + } = await loadFixture(deployFullSuiteFixture); + await expect( + token.connect(anotherWallet).setAgentRestrictions(tokenAgent.address, { + disableAddressFreeze: true, + disableBurn: true, + disableForceTransfer: true, + disableMint: true, + disablePartialFreeze: true, + disablePause: true, + disableRecovery: true, + }), + ).to.be.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when the caller is the owner', () => { + describe('when the given address is not agent', () => { + it('should revert', async () => { + const { + suite: { token }, + accounts: { anotherWallet }, + } = await loadFixture(deployFullSuiteFixture); + await expect( + token.setAgentRestrictions(anotherWallet.address, { + disableAddressFreeze: true, + disableBurn: true, + disableForceTransfer: true, + disableMint: true, + disablePartialFreeze: true, + disablePause: true, + disableRecovery: true, + }), + ).to.be.revertedWithCustomError(token, `AddressNotAgent`); + }); + }); + + describe('when the given address is an agent', () => { + it('should set restrictions', async () => { + const { + suite: { token }, + accounts: { tokenAgent }, + } = await loadFixture(deployFullSuiteFixture); + await expect( + token.setAgentRestrictions(tokenAgent.address, { + disableAddressFreeze: true, + disableBurn: true, + disableForceTransfer: true, + disableMint: true, + disablePartialFreeze: true, + disablePause: true, + disableRecovery: true, + }), + ) + .to.emit(token, 'AgentRestrictionsSet') + .withArgs(tokenAgent.address, true, true, true, true, true, true, true); + }); + }); + }); + }); + + describe('.getAgentRestrictions()', () => { + it('should return restrictions', async () => { + const { + suite: { token }, + accounts: { tokenAgent }, + } = await loadFixture(deployFullSuiteFixture); + + await token.setAgentRestrictions(tokenAgent.address, { + disableAddressFreeze: true, + disableBurn: true, + disableForceTransfer: true, + disableMint: true, + disablePartialFreeze: true, + disablePause: true, + disableRecovery: true, + }); + + const restrictions = await token.getAgentRestrictions(tokenAgent.address); + expect(restrictions.disableAddressFreeze).to.be.true; + expect(restrictions.disableBurn).to.be.true; + expect(restrictions.disableForceTransfer).to.be.true; + expect(restrictions.disableMint).to.be.true; + expect(restrictions.disablePartialFreeze).to.be.true; + expect(restrictions.disablePause).to.be.true; + expect(restrictions.disableRecovery).to.be.true; + }); + }); +}); diff --git a/test/token/token-information.test.ts b/test/token/token-information.test.ts index c097bb9c..aeedd45c 100644 --- a/test/token/token-information.test.ts +++ b/test/token/token-information.test.ts @@ -156,6 +156,27 @@ describe('Token - Information', () => { }); }); + describe('when agent permission is restricted', () => { + it('should revert', async () => { + const { + suite: { token }, + accounts: { tokenAgent }, + } = await loadFixture(deployFullSuiteFixture); + + await token.setAgentRestrictions(tokenAgent.address, { + disableAddressFreeze: false, + disableBurn: false, + disableForceTransfer: false, + disableMint: false, + disablePartialFreeze: false, + disablePause: true, + disableRecovery: false, + }); + + await expect(token.connect(tokenAgent).pause()).to.be.revertedWithCustomError(token, 'AgentNotAuthorized'); + }); + }); + describe('when the caller is an agent', () => { describe('when the token is not paused', () => { it('should pause the token', async () => { @@ -193,6 +214,28 @@ describe('Token - Information', () => { }); }); + describe('when agent permission is restricted', () => { + it('should revert', async () => { + const { + suite: { token }, + accounts: { tokenAgent }, + } = await loadFixture(deployFullSuiteFixture); + await token.connect(tokenAgent).pause(); + + await token.setAgentRestrictions(tokenAgent.address, { + disableAddressFreeze: false, + disableBurn: false, + disableForceTransfer: false, + disableMint: false, + disablePartialFreeze: false, + disablePause: true, + disableRecovery: false, + }); + + await expect(token.connect(tokenAgent).unpause()).to.be.revertedWithCustomError(token, 'AgentNotAuthorized'); + }); + }); + describe('when the caller is an agent', () => { describe('when the token is paused', () => { it('should unpause the token', async () => { diff --git a/test/token/token-recovery.test.ts b/test/token/token-recovery.test.ts index 94767d14..baa5fc2a 100644 --- a/test/token/token-recovery.test.ts +++ b/test/token/token-recovery.test.ts @@ -23,6 +23,34 @@ describe('Token - Recovery', () => { }); }); + describe('when agent permission is restricted', () => { + it('should reverts', async () => { + const { + suite: { token }, + accounts: { bobWallet, anotherWallet, tokenAgent }, + identities: { bobIdentity }, + } = await loadFixture(deployFullSuiteFixture); + + await bobIdentity + .connect(bobWallet) + .addKey(ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['address'], [anotherWallet.address])), 1, 1); + + await token.setAgentRestrictions(tokenAgent.address, { + disableAddressFreeze: false, + disableBurn: false, + disableForceTransfer: false, + disableMint: false, + disablePartialFreeze: false, + disablePause: false, + disableRecovery: true, + }); + + await expect( + token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.address), + ).to.be.revertedWithCustomError(token, 'AgentNotAuthorized'); + }); + }); + describe('when sender is an agent', () => { describe('when wallet to recover has no balance', () => { it('should revert', async () => { diff --git a/test/token/token-transfer.test.ts b/test/token/token-transfer.test.ts index 0b4d1490..ffb7ec0f 100644 --- a/test/token/token-transfer.test.ts +++ b/test/token/token-transfer.test.ts @@ -301,6 +301,30 @@ describe('Token - Transfers', () => { }); }); + describe('when agent permission is restricted', () => { + it('should revert', async () => { + const { + suite: { token }, + accounts: { aliceWallet, bobWallet, tokenAgent }, + } = await loadFixture(deployFullSuiteFixture); + + await token.setAgentRestrictions(tokenAgent.address, { + disableAddressFreeze: false, + disableBurn: false, + disableForceTransfer: true, + disableMint: false, + disablePartialFreeze: false, + disablePause: false, + disableRecovery: false, + }); + + await expect(token.connect(tokenAgent).forcedTransfer(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWithCustomError( + token, + 'AgentNotAuthorized', + ); + }); + }); + describe('when source wallet has not enough balance', () => { it('should revert', async () => { const { @@ -363,7 +387,7 @@ describe('Token - Transfers', () => { }); }); - describe('.mint', () => { + describe('.mint()', () => { describe('when sender is not an agent', () => { it('should revert', async () => { const { @@ -375,6 +399,27 @@ describe('Token - Transfers', () => { }); }); + describe('when agent permission is restricted', () => { + it('should revert', async () => { + const { + suite: { token }, + accounts: { aliceWallet, tokenAgent }, + } = await loadFixture(deployFullSuiteFixture); + + await token.setAgentRestrictions(tokenAgent.address, { + disableAddressFreeze: false, + disableBurn: false, + disableForceTransfer: false, + disableMint: true, + disablePartialFreeze: false, + disablePause: false, + disableRecovery: false, + }); + + await expect(token.connect(tokenAgent).mint(aliceWallet.address, 100)).to.be.revertedWithCustomError(token, 'AgentNotAuthorized'); + }); + }); + describe('when recipient identity is not verified', () => { it('should revert', async () => { const { @@ -414,6 +459,27 @@ describe('Token - Transfers', () => { }); }); + describe('when agent permission is restricted', () => { + it('should revert', async () => { + const { + suite: { token }, + accounts: { aliceWallet, tokenAgent }, + } = await loadFixture(deployFullSuiteFixture); + + await token.setAgentRestrictions(tokenAgent.address, { + disableAddressFreeze: false, + disableBurn: true, + disableForceTransfer: false, + disableMint: false, + disablePartialFreeze: false, + disablePause: false, + disableRecovery: false, + }); + + await expect(token.connect(tokenAgent).burn(aliceWallet.address, 100)).to.be.revertedWithCustomError(token, 'AgentNotAuthorized'); + }); + }); + describe('when source wallet has not enough balance', () => { it('should revert', async () => { const { @@ -444,4 +510,135 @@ describe('Token - Transfers', () => { }); }); }); + + describe('.freezePartialTokens()', () => { + describe('when sender is not an agent', () => { + it('should revert', async () => { + const { + suite: { token }, + accounts: { aliceWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await expect(token.connect(aliceWallet).freezePartialTokens(aliceWallet.address, 100)).to.be.revertedWith( + 'AgentRole: caller does not have the Agent role', + ); + }); + }); + + describe('when agent permission is restricted', () => { + it('should revert', async () => { + const { + suite: { token }, + accounts: { aliceWallet, tokenAgent }, + } = await loadFixture(deployFullSuiteFixture); + + await token.setAgentRestrictions(tokenAgent.address, { + disableAddressFreeze: false, + disableBurn: false, + disableForceTransfer: false, + disableMint: false, + disablePartialFreeze: true, + disablePause: false, + disableRecovery: false, + }); + + await expect(token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, 100)).to.be.revertedWithCustomError( + token, + 'AgentNotAuthorized', + ); + }); + }); + + describe('when freeze amount exceeds the balance', () => { + it('should revert', async () => { + const { + suite: { token }, + accounts: { aliceWallet, tokenAgent }, + } = await loadFixture(deployFullSuiteFixture); + + await expect(token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, 999999999999)).to.be.revertedWith( + 'Amount exceeds available balance', + ); + }); + }); + + describe('when freeze amount does not exceed the balance', () => { + it('should freeze', async () => { + const { + suite: { token }, + accounts: { aliceWallet, tokenAgent }, + } = await loadFixture(deployFullSuiteFixture); + + await expect(token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, 100)) + .to.emit(token, 'TokensFrozen') + .withArgs(aliceWallet.address, 100); + }); + }); + }); + + describe('.unfreezePartialTokens()', () => { + describe('when sender is not an agent', () => { + it('should revert', async () => { + const { + suite: { token }, + accounts: { aliceWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await expect(token.connect(aliceWallet).unfreezePartialTokens(aliceWallet.address, 100)).to.be.revertedWith( + 'AgentRole: caller does not have the Agent role', + ); + }); + }); + + describe('when agent permission is restricted', () => { + it('should revert', async () => { + const { + suite: { token }, + accounts: { aliceWallet, tokenAgent }, + } = await loadFixture(deployFullSuiteFixture); + + await token.setAgentRestrictions(tokenAgent.address, { + disableAddressFreeze: false, + disableBurn: false, + disableForceTransfer: false, + disableMint: false, + disablePartialFreeze: true, + disablePause: false, + disableRecovery: false, + }); + + await expect(token.connect(tokenAgent).unfreezePartialTokens(aliceWallet.address, 100)).to.be.revertedWithCustomError( + token, + 'AgentNotAuthorized', + ); + }); + }); + + describe('when unfreeze amount exceeds the frozen amount', () => { + it('should revert', async () => { + const { + suite: { token }, + accounts: { aliceWallet, tokenAgent }, + } = await loadFixture(deployFullSuiteFixture); + + await expect(token.connect(tokenAgent).unfreezePartialTokens(aliceWallet.address, 5000)).to.be.revertedWith( + 'Amount should be less than or equal to frozen tokens', + ); + }); + }); + + describe('when freeze amount does not exceed the balance', () => { + it('should freeze', async () => { + const { + suite: { token }, + accounts: { aliceWallet, tokenAgent }, + } = await loadFixture(deployFullSuiteFixture); + + await token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, 200); + await expect(token.connect(tokenAgent).unfreezePartialTokens(aliceWallet.address, 100)) + .to.emit(token, 'TokensUnfrozen') + .withArgs(aliceWallet.address, 100); + }); + }); + }); }); From 22dc570eaab2bd623d03b2d81fda85d41ee8e93e Mon Sep 17 00:00:00 2001 From: "ali.arbak" Date: Wed, 14 Feb 2024 15:19:28 +0300 Subject: [PATCH 04/55] Update natspec --- contracts/token/IToken.sol | 223 +++++++++++++++++++++---------------- 1 file changed, 127 insertions(+), 96 deletions(-) diff --git a/contracts/token/IToken.sol b/contracts/token/IToken.sol index 77e3db39..d087b77f 100644 --- a/contracts/token/IToken.sol +++ b/contracts/token/IToken.sol @@ -280,21 +280,26 @@ interface IToken is IERC20 { function setCompliance(address _compliance) external; /** - * @dev force a transfer of tokens between 2 whitelisted wallets - * In case the `from` address has not enough free tokens (unfrozen tokens) - * but has a total balance higher or equal to the `amount` - * the amount of frozen tokens is reduced in order to have enough free tokens - * to proceed the transfer, in such a case, the remaining balance on the `from` - * account is 100% composed of frozen tokens post-transfer. - * Require that the `to` address is a verified address, - * @param _from The address of the sender - * @param _to The address of the receiver - * @param _amount The number of tokens to transfer - * @return `true` if successful and revert if unsuccessful - * This function can only be called by a wallet set as agent of the token - * emits a `TokensUnfrozen` event if `_amount` is higher than the free balance of `_from` - * emits a `Transfer` event - */ + * @dev Initiates a forced transfer of tokens between two whitelisted wallets. + * If the `from` address does not have sufficient free tokens (unfrozen tokens) + * but possesses a total balance equal to or greater than the specified `amount`, + * the frozen token amount is reduced to ensure enough free tokens for the transfer. + * In such cases, the remaining balance in the `from` account consists entirely of frozen tokens post-transfer. + * It is imperative that the `to` address is a verified and whitelisted address. + * @param _from The address of the sender. + * @param _to The address of the receiver. + * @param _amount The number of tokens to be transferred. + * @return true if the transfer is successful; reverts if unsuccessful. + * This function can only be invoked by a wallet designated as an agent of the token, + * provided the agent is not restricted from initiating forced transfers of the token. + * Emits a `TokensUnfrozen` event if `_amount` is higher than the free balance of `_from`. + * Also emits a `Transfer` event. + * To execute this function, the calling agent must not be restricted from initiating forced transfers of the token. + * If the agent is restricted from this capability, the function call will fail. + * The function can only be called when the contract is not already paused. + * error `AgentNotAuthorized` - Thrown if the agent is restricted from initiating forced transfers of the token, + * indicating they do not have the necessary permissions to execute this function. + */ function forcedTransfer( address _from, address _to, @@ -302,43 +307,49 @@ interface IToken is IERC20 { ) external returns (bool); /** - * @dev mint tokens on a wallet - * Improved version of default mint method. Tokens can be minted - * to an address if only it is a verified address as per the security token. + * @dev Mints tokens to a specified address. + * This enhanced version of the default mint method allows tokens to be minted + * to an address only if it is a verified and whitelisted address according to the security token. * @param _to Address to mint the tokens to. * @param _amount Amount of tokens to mint. - * This function can only be called by a wallet set as agent of the token - * emits a `Transfer` event - */ + * This function can only be called by a wallet designated as an agent of the token, + * provided the agent is not restricted from minting tokens. + * Emits a `Transfer` event upon successful minting. + * To execute this function, the calling agent must not be restricted from minting tokens. + * If the agent is restricted from this capability, the function call will fail. + */ function mint(address _to, uint256 _amount) external; /** - * @dev burn tokens on a wallet - * In case the `account` address has not enough free tokens (unfrozen tokens) - * but has a total balance higher or equal to the `value` amount - * the amount of frozen tokens is reduced in order to have enough free tokens - * to proceed the burn, in such a case, the remaining balance on the `account` - * is 100% composed of frozen tokens post-transaction. + * @dev Burns tokens from a specified address. + * If the account address does not have sufficient free tokens (unfrozen tokens) + * but possesses a total balance equal to or greater than the specified value, + * the frozen token amount is reduced to ensure enough free tokens for the burn. + * In such cases, the remaining balance in the account consists entirely of frozen tokens post-transaction. * @param _userAddress Address to burn the tokens from. * @param _amount Amount of tokens to burn. - * This function can only be called by a wallet set as agent of the token - * emits a `TokensUnfrozen` event if `_amount` is higher than the free balance of `_userAddress` - * emits a `Transfer` event - */ + * This function can only be called by a wallet designated as an agent of the token, + * provided the agent is not restricted from burning tokens. + * Emits a `TokensUnfrozen` event if `_amount` exceeds the free balance of `_userAddress`. + * Also emits a `Transfer` event. + * To execute this function, the calling agent must not be restricted from burning tokens. + * If the agent is restricted from this capability, the function call will fail. + */ function burn(address _userAddress, uint256 _amount) external; /** - * @dev recovery function used to force transfer tokens from a - * lost wallet to a new wallet for an investor. - * @param _lostWallet the wallet that the investor lost - * @param _newWallet the newly provided wallet on which tokens have to be transferred - * @param _investorOnchainID the onchainID of the investor asking for a recovery - * This function can only be called by a wallet set as agent of the token - * emits a `TokensUnfrozen` event if there is some frozen tokens on the lost wallet if the recovery process is successful - * emits a `Transfer` event if the recovery process is successful - * emits a `RecoverySuccess` event if the recovery process is successful - * emits a `RecoveryFails` event if the recovery process fails - */ + * @dev Initiates a recovery process to force transfer tokens from a lost wallet to a new wallet for an investor. + * @param _lostWallet The wallet that the investor lost. + * @param _newWallet The newly provided wallet to which tokens must be transferred. + * @param _investorOnchainID The onchainID of the investor requesting recovery. + * This function can only be called by a wallet designated as an agent of the token, + * provided the agent is not restricted from initiating recovery processes. + * Emits a `TokensUnfrozen` event if there are frozen tokens on the lost wallet and the recovery process is successful. + * Also emits a `Transfer` event and a `RecoverySuccess` event upon successful recovery. + * Emits a `RecoveryFails` event if the recovery process fails. + * To execute this function, the calling agent must not be restricted from initiating recovery processes. + * If the agent is restricted from this capability, the function call will fail. + */ function recoveryAddress( address _lostWallet, address _newWallet, @@ -359,18 +370,22 @@ interface IToken is IERC20 { function batchTransfer(address[] calldata _toList, uint256[] calldata _amounts) external; /** - * @dev function allowing to issue forced transfers in batch - * Require that `_amounts[i]` should not exceed available balance of `_fromList[i]`. - * Require that the `_toList` addresses are all verified addresses - * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_fromList.length` IS TOO HIGH, - * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION - * @param _fromList The addresses of the senders - * @param _toList The addresses of the receivers - * @param _amounts The number of tokens to transfer to the corresponding receiver - * This function can only be called by a wallet set as agent of the token - * emits `TokensUnfrozen` events if `_amounts[i]` is higher than the free balance of `_fromList[i]` - * emits _fromList.length `Transfer` events - */ + * @dev Initiates forced transfers in batch. + * Requires that each _amounts[i] does not exceed the available balance of _fromList[i]. + * Requires that the _toList addresses are all verified and whitelisted addresses. + * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF _fromList.length IS TOO HIGH. + * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. + * @param _fromList The addresses of the senders. + * @param _toList The addresses of the receivers. + * @param _amounts The number of tokens to transfer to the corresponding receiver. + * @return true if the batch transfer is successful; reverts if unsuccessful. + * This function can only be called by a wallet designated as an agent of the token, + * provided the agent is not restricted from initiating forced transfers in batch. + * Emits `TokensUnfrozen` events for each `_amounts[i]` that exceeds the free balance of `_fromList[i]`. + * Also emits _fromList.length `Transfer` events upon successful batch transfer. + * To execute this function, the calling agent must not be restricted from initiating forced transfer. + * If the agent is restricted from this capability, the function call will fail. + */ function batchForcedTransfer( address[] calldata _fromList, address[] calldata _toList, @@ -378,60 +393,76 @@ interface IToken is IERC20 { ) external; /** - * @dev function allowing to mint tokens in batch - * Require that the `_toList` addresses are all verified addresses - * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_toList.length` IS TOO HIGH, - * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION - * @param _toList The addresses of the receivers - * @param _amounts The number of tokens to mint to the corresponding receiver - * This function can only be called by a wallet set as agent of the token - * emits _toList.length `Transfer` events - */ + * @dev Initiates minting of tokens in batch. + * Requires that the `_toList` addresses are all verified and whitelisted addresses. + * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_toList.length` IS TOO HIGH. + * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. + * @param _toList The addresses of the receivers. + * @param _amounts The number of tokens to mint to the corresponding receiver. + * This function can only be called by a wallet designated as an agent of the token, + * provided the agent is not restricted from minting tokens. + * Emits _toList.length `Transfer` events upon successful batch minting. + * To execute this function, the calling agent must not be restricted from minting tokens. + * If the agent is restricted from this capability, the function call will fail. + */ function batchMint(address[] calldata _toList, uint256[] calldata _amounts) external; /** - * @dev function allowing to burn tokens in batch - * Require that the `_userAddresses` addresses are all verified addresses - * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH, - * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION - * @param _userAddresses The addresses of the wallets concerned by the burn - * @param _amounts The number of tokens to burn from the corresponding wallets - * This function can only be called by a wallet set as agent of the token - * emits _userAddresses.length `Transfer` events - */ + * @dev Initiates burning of tokens in batch. + * Requires that the `_userAddresses` addresses are all verified and whitelisted addresses. + * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH. + * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. + * @param _userAddresses The addresses of the wallets concerned by the burn. + * @param _amounts The number of tokens to burn from the corresponding wallets. + * This function can only be called by a wallet designated as an agent of the token, + * provided the agent is not restricted from burning tokens. + * Emits _userAddresses.length `Transfer` events upon successful batch burn. + * To execute this function, the calling agent must not be restricted from burning tokens. + * If the agent is restricted from this capability, the function call will fail. + */ function batchBurn(address[] calldata _userAddresses, uint256[] calldata _amounts) external; /** - * @dev function allowing to set frozen addresses in batch - * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH, - * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION - * @param _userAddresses The addresses for which to update frozen status - * @param _freeze Frozen status of the corresponding address - * This function can only be called by a wallet set as agent of the token - * emits _userAddresses.length `AddressFrozen` events - */ + * @dev Initiates setting of frozen status for addresses in batch. + * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH. + * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. + * @param _userAddresses The addresses for which to update frozen status. + * @param _freeze Frozen status of the corresponding address. + * This function can only be called by a wallet designated as an agent of the token, + * provided the agent is not restricted from setting frozen addresses. + * Emits _userAddresses.length `AddressFrozen` events upon successful batch update of frozen status. + * To execute this function, the calling agent must not be restricted from setting frozen addresses. + * If the agent is restricted from this capability, the function call will fail. + */ function batchSetAddressFrozen(address[] calldata _userAddresses, bool[] calldata _freeze) external; /** - * @dev function allowing to freeze tokens partially in batch - * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH, - * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION - * @param _userAddresses The addresses on which tokens need to be frozen - * @param _amounts the amount of tokens to freeze on the corresponding address - * This function can only be called by a wallet set as agent of the token - * emits _userAddresses.length `TokensFrozen` events - */ + * @dev Initiates partial freezing of tokens in batch. + * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH. + * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. + * @param _userAddresses The addresses on which tokens need to be partially frozen. + * @param _amounts The amount of tokens to freeze on the corresponding address. + * @return true if the batch partial freezing is successful; reverts if unsuccessful. + * This function can only be called by a wallet designated as an agent of the token, + * provided the agent is not restricted from partially freezing tokens. + * Emits _userAddresses.length `TokensFrozen` events upon successful batch partial freezing. + * To execute this function, the calling agent must not be restricted from partially freezing tokens. + * If the agent is restricted from this capability, the function call will fail. + */ function batchFreezePartialTokens(address[] calldata _userAddresses, uint256[] calldata _amounts) external; /** - * @dev function allowing to unfreeze tokens partially in batch - * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH, - * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION - * @param _userAddresses The addresses on which tokens need to be unfrozen - * @param _amounts the amount of tokens to unfreeze on the corresponding address - * This function can only be called by a wallet set as agent of the token - * emits _userAddresses.length `TokensUnfrozen` events - */ + * @dev Initiates partial unfreezing of tokens in batch. + * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH. + * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. + * @param _userAddresses The addresses on which tokens need to be partially unfrozen. + * @param _amounts The amount of tokens to unfreeze on the corresponding address. + * This function can only be called by a wallet designated as an agent of the token, + * provided the agent is not restricted from partially freezing tokens. + * Emits _userAddresses.length `TokensUnfrozen` events upon successful batch partial unfreezing. + * To execute this function, the calling agent must not be restricted from partially freezing tokens. + * If the agent is restricted from this capability, the function call will fail. + */ function batchUnfreezePartialTokens(address[] calldata _userAddresses, uint256[] calldata _amounts) external; /** From 56938c97af40ff7b42279864f46073e0972d63e6 Mon Sep 17 00:00:00 2001 From: "ali.arbak" Date: Wed, 14 Feb 2024 15:21:35 +0300 Subject: [PATCH 05/55] Fix natspec issue --- contracts/token/IToken.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/contracts/token/IToken.sol b/contracts/token/IToken.sol index d087b77f..ce7c1437 100644 --- a/contracts/token/IToken.sol +++ b/contracts/token/IToken.sol @@ -289,7 +289,6 @@ interface IToken is IERC20 { * @param _from The address of the sender. * @param _to The address of the receiver. * @param _amount The number of tokens to be transferred. - * @return true if the transfer is successful; reverts if unsuccessful. * This function can only be invoked by a wallet designated as an agent of the token, * provided the agent is not restricted from initiating forced transfers of the token. * Emits a `TokensUnfrozen` event if `_amount` is higher than the free balance of `_from`. @@ -378,7 +377,6 @@ interface IToken is IERC20 { * @param _fromList The addresses of the senders. * @param _toList The addresses of the receivers. * @param _amounts The number of tokens to transfer to the corresponding receiver. - * @return true if the batch transfer is successful; reverts if unsuccessful. * This function can only be called by a wallet designated as an agent of the token, * provided the agent is not restricted from initiating forced transfers in batch. * Emits `TokensUnfrozen` events for each `_amounts[i]` that exceeds the free balance of `_fromList[i]`. @@ -442,7 +440,6 @@ interface IToken is IERC20 { * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. * @param _userAddresses The addresses on which tokens need to be partially frozen. * @param _amounts The amount of tokens to freeze on the corresponding address. - * @return true if the batch partial freezing is successful; reverts if unsuccessful. * This function can only be called by a wallet designated as an agent of the token, * provided the agent is not restricted from partially freezing tokens. * Emits _userAddresses.length `TokensFrozen` events upon successful batch partial freezing. From 0c853b3f2deb89d78a7d227e6440c6591ca0264f Mon Sep 17 00:00:00 2001 From: "ali.arbak" Date: Wed, 21 Feb 2024 11:20:33 +0300 Subject: [PATCH 06/55] Update version as 4.2.0-beta1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d354820d..3280595c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tokenysolutions/t-rex", - "version": "4.1.2", + "version": "4.2.0-beta1", "description": "A fully compliant environment for the issuance and use of tokenized securities.", "main": "index.js", "directories": { From b9a1e759b38b5f8dc62e51be8ab084cec8cb9020 Mon Sep 17 00:00:00 2001 From: "ali.arbak" Date: Fri, 8 Mar 2024 19:16:26 +0300 Subject: [PATCH 07/55] Implement upgradeable proxies to compliance modules --- .DS_Store | Bin 0 -> 6148 bytes .../modules/AbstractModuleUpgradeable.sol | 147 +++ .../modules/ConditionalTransferModule.sol | 12 +- .../modular/modules/CountryAllowModule.sol | 12 +- .../modular/modules/CountryRestrictModule.sol | 12 +- .../modules/ExchangeMonthlyLimitsModule.sol | 14 +- .../modular/modules/MaxBalanceModule.sol | 12 +- .../modular/modules/SupplyLimitModule.sol | 12 +- .../modules/TimeExchangeLimitsModule.sol | 14 +- .../modules/TimeTransfersLimitsModule.sol | 12 +- .../modular/modules/TransferFeesModule.sol | 14 +- .../modules/TransferRestrictModule.sol | 12 +- hardhat.config.ts | 1 + package-lock.json | 919 ++++++++++++++---- package.json | 1 + .../module-conditional-transfer.test.ts | 64 +- test/compliances/module-country-allow.test.ts | 63 +- .../module-country-restrict.test.ts | 63 +- .../module-exchange-monthly-limits.test.ts | 66 +- test/compliances/module-max-balance.test.ts | 63 +- test/compliances/module-supply-limit.test.ts | 66 +- .../module-time-exchange-limits.test.ts | 66 +- .../module-time-transfer-limits.test.ts | 66 +- test/compliances/module-transfer-fees.test.ts | 63 +- .../module-transfer-restrict.test.ts | 63 +- 25 files changed, 1600 insertions(+), 237 deletions(-) create mode 100644 .DS_Store create mode 100644 contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..7b0e5820b8e619e472083570f7196fab403fcf9a GIT binary patch literal 6148 zcmeHK-AcnS6i&A3T86L-gNcZU%-l9sLa+)E!JkNoxK=?Uh50_BtDPl zB&j$y!7CAW4xD_+`Dw_Pl9MpTcy}^rF;-`cS)hm|8=578e$)ji84Ds;-?(EwyJaa$ zf@~q041bXU+&dd~Z4A2>vM>9WjDko8;C%~5QJAET^Uh1<%G!F>s#-Pc+Ix_hm-^`> z>H6bK9GyuS1x4Qv&ck8WuWug9IQ7GLI93VaU zJ$Q@EB7=|^AO?tmRbjxKe^zZ(7EJ3T28e+lGl1uV07Y~S<{H(}0S#Us(O*GCfj+(^ z5QRb4V6G87AY7*c>Qru?7+j}=U6?r6V6IW8Gp=Ta@0gjnd7*GMJJ^K^XWZ3DEiph0 z%rj8d!#dXglkeaE^GP%!28e-w#Q?ALyj~ZUWNPce;;_~V&>K(`jLS8Cra(uPVu;03 c+yGSqc7Yv0*I=#@EFg3dP&80O4E!nsAN(3kW&i*H literal 0 HcmV?d00001 diff --git a/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol new file mode 100644 index 00000000..b142f92e --- /dev/null +++ b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-3.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2023, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +pragma solidity 0.8.17; + +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import "./IModule.sol"; + +abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUpgradeable, UUPSUpgradeable { + struct AbstractModuleStorage { + /// compliance contract binding status + mapping(address => bool) complianceBound; + } + + // keccak256(abi.encode(uint256(keccak256("ERC3643.storage.AbstractModule")) - 1)) & ~bytes32(uint256(0xff)) + bytes32 private constant _ABSTRACT_MODULE_STORAGE_LOCATION = + 0xf6cc97de1266c180cd39f3b311632644143ce7873d2927755382ad4b39e8ae00; + + /** + * @dev Throws if `_compliance` is not a bound compliance contract address. + */ + modifier onlyBoundCompliance(address _compliance) { + AbstractModuleStorage storage s = _getAbstractModuleStorage(); + require(s.complianceBound[_compliance], "compliance not bound"); + _; + } + + /** + * @dev Throws if called from an address that is not a bound compliance contract. + */ + modifier onlyComplianceCall() { + AbstractModuleStorage storage s = _getAbstractModuleStorage(); + require(s.complianceBound[msg.sender], "only bound compliance can call"); + _; + } + + /** + * @dev See {IModule-bindCompliance}. + */ + function bindCompliance(address _compliance) external override { + AbstractModuleStorage storage s = _getAbstractModuleStorage(); + require(_compliance != address(0), "invalid argument - zero address"); + require(!s.complianceBound[_compliance], "compliance already bound"); + require(msg.sender == _compliance, "only compliance contract can call"); + s.complianceBound[_compliance] = true; + emit ComplianceBound(_compliance); + } + + /** + * @dev See {IModule-unbindCompliance}. + */ + function unbindCompliance(address _compliance) external onlyComplianceCall override { + AbstractModuleStorage storage s = _getAbstractModuleStorage(); + require(_compliance != address(0), "invalid argument - zero address"); + require(msg.sender == _compliance, "only compliance contract can call"); + s.complianceBound[_compliance] = false; + emit ComplianceUnbound(_compliance); + } + + /** + * @dev See {IModule-isComplianceBound}. + */ + function isComplianceBound(address _compliance) external view override returns (bool) { + AbstractModuleStorage storage s = _getAbstractModuleStorage(); + return s.complianceBound[_compliance]; + } + + // solhint-disable-next-line func-name-mixedcase + function __AbstractModule_init() internal onlyInitializing { + __Ownable_init(); + __AbstractModule_init_unchained(); + } + + // solhint-disable-next-line no-empty-blocks, func-name-mixedcase + function __AbstractModule_init_unchained() internal onlyInitializing { } + + // solhint-disable-next-line no-empty-blocks + function _authorizeUpgrade(address /*newImplementation*/) internal override virtual onlyOwner { } + + function _getAbstractModuleStorage() private pure returns (AbstractModuleStorage storage s) { + // solhint-disable-next-line no-inline-assembly + assembly { + s.slot := _ABSTRACT_MODULE_STORAGE_LOCATION + } + } +} diff --git a/contracts/compliance/modular/modules/ConditionalTransferModule.sol b/contracts/compliance/modular/modules/ConditionalTransferModule.sol index 3c2e3c57..46aee9a9 100644 --- a/contracts/compliance/modular/modules/ConditionalTransferModule.sol +++ b/contracts/compliance/modular/modules/ConditionalTransferModule.sol @@ -64,13 +64,13 @@ pragma solidity 0.8.17; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; -import "./AbstractModule.sol"; import "../../../roles/AgentRole.sol"; +import "./AbstractModuleUpgradeable.sol"; /** * this module allows to require the pre-validation of a transfer before allowing it to be executed */ -contract ConditionalTransferModule is AbstractModule { +contract ConditionalTransferModule is AbstractModuleUpgradeable { /// Mapping between transfer details and their approval status (amount of transfers approved) per compliance mapping(address => mapping(bytes32 => uint)) private _transfersApproved; @@ -94,6 +94,14 @@ contract ConditionalTransferModule is AbstractModule { */ event ApprovalRemoved(address _from, address _to, uint _amount, address _token); + /** + * @dev initializes the contract and sets the initial state. + * @notice This function should only be called once during the contract deployment. + */ + function initialize() external initializer { + __AbstractModule_init(); + } + /** * @dev Approves transfers in batch * once a transfer is approved, the sender is allowed to execute it diff --git a/contracts/compliance/modular/modules/CountryAllowModule.sol b/contracts/compliance/modular/modules/CountryAllowModule.sol index d18aa5a7..16e15819 100644 --- a/contracts/compliance/modular/modules/CountryAllowModule.sol +++ b/contracts/compliance/modular/modules/CountryAllowModule.sol @@ -64,9 +64,9 @@ pragma solidity 0.8.17; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; -import "./AbstractModule.sol"; +import "./AbstractModuleUpgradeable.sol"; -contract CountryAllowModule is AbstractModule { +contract CountryAllowModule is AbstractModuleUpgradeable { /// Mapping between country and their allowance status per compliance contract mapping(address => mapping(uint16 => bool)) private _allowedCountries; @@ -92,6 +92,14 @@ contract CountryAllowModule is AbstractModule { /// functions + /** + * @dev initializes the contract and sets the initial state. + * @notice This function should only be called once during the contract deployment. + */ + function initialize() external initializer { + __AbstractModule_init(); + } + /** * @dev Adds country allowance in batch. * Identities from those countries will be allowed to manipulate Tokens linked to this Compliance. diff --git a/contracts/compliance/modular/modules/CountryRestrictModule.sol b/contracts/compliance/modular/modules/CountryRestrictModule.sol index b1d25b75..cd07191a 100644 --- a/contracts/compliance/modular/modules/CountryRestrictModule.sol +++ b/contracts/compliance/modular/modules/CountryRestrictModule.sol @@ -64,9 +64,9 @@ pragma solidity 0.8.17; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; -import "./AbstractModule.sol"; +import "./AbstractModuleUpgradeable.sol"; -contract CountryRestrictModule is AbstractModule { +contract CountryRestrictModule is AbstractModuleUpgradeable { /// Mapping between country and their restriction status per compliance contract mapping(address => mapping(uint16 => bool)) private _restrictedCountries; @@ -84,6 +84,14 @@ contract CountryRestrictModule is AbstractModule { */ event RemovedRestrictedCountry(address indexed _compliance, uint16 _country); + /** + * @dev initializes the contract and sets the initial state. + * @notice This function should only be called once during the contract deployment. + */ + function initialize() external initializer { + __AbstractModule_init(); + } + /** * @dev Adds country restriction. * Identities from those countries will be forbidden to manipulate Tokens linked to this Compliance. diff --git a/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol b/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol index e3bc24c3..b1e530f0 100644 --- a/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol +++ b/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol @@ -65,11 +65,9 @@ pragma solidity 0.8.17; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; import "../../../roles/AgentRole.sol"; -import "./AbstractModule.sol"; +import "./AbstractModuleUpgradeable.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; - -contract ExchangeMonthlyLimitsModule is AbstractModule, Ownable { +contract ExchangeMonthlyLimitsModule is AbstractModuleUpgradeable { /// Struct of transfer Counters struct ExchangeTransferCounter { uint256 monthlyCount; @@ -112,6 +110,14 @@ contract ExchangeMonthlyLimitsModule is AbstractModule, Ownable { error ONCHAINIDNotTaggedAsExchange(address _exchangeID); + /** + * @dev initializes the contract and sets the initial state. + * @notice This function should only be called once during the contract deployment. + */ + function initialize() external initializer { + __AbstractModule_init(); + } + /** * @dev Set the limit of tokens allowed to be transferred monthly. * @param _exchangeID ONCHAINID of the exchange diff --git a/contracts/compliance/modular/modules/MaxBalanceModule.sol b/contracts/compliance/modular/modules/MaxBalanceModule.sol index 8fbfa1d7..53751a47 100644 --- a/contracts/compliance/modular/modules/MaxBalanceModule.sol +++ b/contracts/compliance/modular/modules/MaxBalanceModule.sol @@ -65,9 +65,9 @@ pragma solidity 0.8.17; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; -import "./AbstractModule.sol"; +import "./AbstractModuleUpgradeable.sol"; -contract MaxBalanceModule is AbstractModule { +contract MaxBalanceModule is AbstractModuleUpgradeable { /// state variables @@ -103,6 +103,14 @@ contract MaxBalanceModule is AbstractModule { /// functions + /** + * @dev initializes the contract and sets the initial state. + * @notice This function should only be called once during the contract deployment. + */ + function initialize() external initializer { + __AbstractModule_init(); + } + /** * @dev sets max balance limit for a bound compliance contract * @param _max max amount of tokens owned by an individual diff --git a/contracts/compliance/modular/modules/SupplyLimitModule.sol b/contracts/compliance/modular/modules/SupplyLimitModule.sol index 00bafc30..b67f83ee 100644 --- a/contracts/compliance/modular/modules/SupplyLimitModule.sol +++ b/contracts/compliance/modular/modules/SupplyLimitModule.sol @@ -64,9 +64,9 @@ pragma solidity ^0.8.17; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; -import "./AbstractModule.sol"; +import "./AbstractModuleUpgradeable.sol"; -contract SupplyLimitModule is AbstractModule { +contract SupplyLimitModule is AbstractModuleUpgradeable { /// supply limits array mapping(address => uint256) private _supplyLimits; @@ -77,6 +77,14 @@ contract SupplyLimitModule is AbstractModule { */ event SupplyLimitSet(address _compliance, uint256 _limit); + /** + * @dev initializes the contract and sets the initial state. + * @notice This function should only be called once during the contract deployment. + */ + function initialize() external initializer { + __AbstractModule_init(); + } + /** * @dev sets supply limit. * Supply limit has to be smaller or equal to the actual supply. diff --git a/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol b/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol index 0de7d8e4..9ae84e38 100644 --- a/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol +++ b/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol @@ -65,11 +65,9 @@ pragma solidity 0.8.17; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; import "../../../roles/AgentRole.sol"; -import "./AbstractModule.sol"; +import "./AbstractModuleUpgradeable.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; - -contract TimeExchangeLimitsModule is AbstractModule, Ownable { +contract TimeExchangeLimitsModule is AbstractModuleUpgradeable { /// Struct of transfer Counters struct ExchangeTransferCounter { uint256 value; @@ -129,6 +127,14 @@ contract TimeExchangeLimitsModule is AbstractModule, Ownable { error LimitsArraySizeExceeded(address compliance, uint arraySize); + /** + * @dev initializes the contract and sets the initial state. + * @notice This function should only be called once during the contract deployment. + */ + function initialize() external initializer { + __AbstractModule_init(); + } + /** * @dev Sets the limit of tokens allowed to be transferred to the given exchangeID in a given period of time * @param _exchangeID ONCHAINID of the exchange diff --git a/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol b/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol index a450be8b..265d6d5f 100644 --- a/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol +++ b/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol @@ -65,9 +65,9 @@ pragma solidity 0.8.17; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; import "../../../roles/AgentRole.sol"; -import "./AbstractModule.sol"; +import "./AbstractModuleUpgradeable.sol"; -contract TimeTransfersLimitsModule is AbstractModule { +contract TimeTransfersLimitsModule is AbstractModuleUpgradeable { /// Struct of transfer Counters struct TransferCounter { uint256 value; @@ -104,6 +104,14 @@ contract TimeTransfersLimitsModule is AbstractModule { error LimitsArraySizeExceeded(address compliance, uint arraySize); + /** + * @dev initializes the contract and sets the initial state. + * @notice This function should only be called once during the contract deployment. + */ + function initialize() external initializer { + __AbstractModule_init(); + } + /** * @dev Sets the limit of tokens allowed to be transferred in the given time frame. * @param _limit The limit time and value diff --git a/contracts/compliance/modular/modules/TransferFeesModule.sol b/contracts/compliance/modular/modules/TransferFeesModule.sol index cb2b7d3a..657035fe 100644 --- a/contracts/compliance/modular/modules/TransferFeesModule.sol +++ b/contracts/compliance/modular/modules/TransferFeesModule.sol @@ -65,11 +65,9 @@ pragma solidity 0.8.17; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; import "../../../roles/AgentRole.sol"; -import "./AbstractModule.sol"; +import "./AbstractModuleUpgradeable.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; - -contract TransferFeesModule is AbstractModule, Ownable { +contract TransferFeesModule is AbstractModuleUpgradeable { /// Struct of fees struct Fee { uint256 rate; // min = 0, max = 10000, 0.01% = 1, 1% = 100, 100% = 10000 @@ -92,6 +90,14 @@ contract TransferFeesModule is AbstractModule, Ownable { error CollectorAddressIsNotVerified(address compliance, address collector); + /** + * @dev initializes the contract and sets the initial state. + * @notice This function should only be called once during the contract deployment. + */ + function initialize() external initializer { + __AbstractModule_init(); + } + /** * @dev Sets the fee rate and collector of the given compliance * @param _rate is the rate of the fee (0.01% = 1, 1% = 100, 100% = 10000) diff --git a/contracts/compliance/modular/modules/TransferRestrictModule.sol b/contracts/compliance/modular/modules/TransferRestrictModule.sol index 9d1244b5..971eb92b 100644 --- a/contracts/compliance/modular/modules/TransferRestrictModule.sol +++ b/contracts/compliance/modular/modules/TransferRestrictModule.sol @@ -62,9 +62,9 @@ pragma solidity ^0.8.17; -import "./AbstractModule.sol"; +import "./AbstractModuleUpgradeable.sol"; -contract TransferRestrictModule is AbstractModule { +contract TransferRestrictModule is AbstractModuleUpgradeable { /// allowed user addresses mapping mapping(address => mapping(address => bool)) private _allowedUserAddresses; @@ -82,6 +82,14 @@ contract TransferRestrictModule is AbstractModule { */ event UserDisallowed(address _compliance, address _userAddress); + /** + * @dev initializes the contract and sets the initial state. + * @notice This function should only be called once during the contract deployment. + */ + function initialize() external initializer { + __AbstractModule_init(); + } + /** * @dev allows a user address for transfer. * @param _userAddress is the address of the user diff --git a/hardhat.config.ts b/hardhat.config.ts index 688a158c..a9e8ab6e 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,6 +1,7 @@ import '@xyrusworx/hardhat-solidity-json'; import '@nomicfoundation/hardhat-toolbox'; import { HardhatUserConfig } from 'hardhat/config'; +import '@openzeppelin/hardhat-upgrades'; import 'solidity-coverage'; import '@nomiclabs/hardhat-solhint'; import '@primitivefi/hardhat-dodoc'; diff --git a/package-lock.json b/package-lock.json index 0fb59117..281fef5c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@tokenysolutions/t-rex", - "version": "4.1.2-beta1", + "version": "4.1.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@tokenysolutions/t-rex", - "version": "4.1.2-beta1", + "version": "4.1.3", "license": "SEE LICENSE IN LICENSE.md", "devDependencies": { "@commitlint/cli": "^17.6.1", @@ -15,6 +15,7 @@ "@onchain-id/solidity": "^2.0.0", "@openzeppelin/contracts": "^4.8.3", "@openzeppelin/contracts-upgradeable": "^4.8.3", + "@openzeppelin/hardhat-upgrades": "^1.28.0", "@primitivefi/hardhat-dodoc": "^0.2.3", "@typescript-eslint/eslint-plugin": "^6.7.4", "@typescript-eslint/parser": "^6.7.4", @@ -39,6 +40,62 @@ "solhint-plugin-prettier": "^0.0.5" } }, + "node_modules/@aws-crypto/sha256-js": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-1.2.2.tgz", + "integrity": "sha512-Nr1QJIbW/afYYGzYvrF70LtaHrIRtd4TNAglX8BvlfxJLZ45SAmueIKYl5tWoNBPzp65ymXGFK0Bb1vZUpuc9g==", + "dev": true, + "dependencies": { + "@aws-crypto/util": "^1.2.2", + "@aws-sdk/types": "^3.1.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/util": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-1.2.2.tgz", + "integrity": "sha512-H8PjG5WJ4wz0UXAFXeJjWCW1vkvIJ3qUUD+rGRwJ2/hj+xT58Qle2MTql/2MGzkU+1JLAFuR6aJpLAjHwhmwwg==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "^3.1.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.523.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.523.0.tgz", + "integrity": "sha512-AqGIu4u+SxPiUuNBp2acCVcq80KDUFjxe6e3cMTvKWTzCbrVk1AXv0dAaJnCmdkWIha6zJDWxpIk/aL4EGhZ9A==", + "dev": true, + "dependencies": { + "@smithy/types": "^2.10.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/types/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "dev": true, + "dependencies": { + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/util-utf8-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, "node_modules/@babel/code-frame": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", @@ -2446,6 +2503,101 @@ "integrity": "sha512-jjaHAVRMrE4UuZNfDwjlLGDxTHWIOwTJS2ldnc278a0gevfXfPr8hxKEVBGFBE96kl2G3VHDZhUimw/+G3TG2A==", "dev": true }, + "node_modules/@openzeppelin/defender-base-client": { + "version": "1.54.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-base-client/-/defender-base-client-1.54.1.tgz", + "integrity": "sha512-DRGz/7KN3ZQwu28YWMOaojrC7jjPkz/uCwkC8/C8B11qwZhA5qIVvyhYHhhFOCl0J84+E3TNdvkPD2q3p2WaJw==", + "dev": true, + "dependencies": { + "amazon-cognito-identity-js": "^6.0.1", + "async-retry": "^1.3.3", + "axios": "^1.4.0", + "lodash": "^4.17.19", + "node-fetch": "^2.6.0" + } + }, + "node_modules/@openzeppelin/hardhat-upgrades": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-1.28.0.tgz", + "integrity": "sha512-7sb/Jf+X+uIufOBnmHR0FJVWuxEs2lpxjJnLNN6eCJCP8nD0v+Ot5lTOW2Qb/GFnh+fLvJtEkhkowz4ZQ57+zQ==", + "dev": true, + "dependencies": { + "@openzeppelin/defender-base-client": "^1.46.0", + "@openzeppelin/platform-deploy-client": "^0.8.0", + "@openzeppelin/upgrades-core": "^1.27.0", + "chalk": "^4.1.0", + "debug": "^4.1.1", + "proper-lockfile": "^4.1.1" + }, + "bin": { + "migrate-oz-cli-project": "dist/scripts/migrate-oz-cli-project.js" + }, + "peerDependencies": { + "@nomiclabs/hardhat-ethers": "^2.0.0", + "@nomiclabs/hardhat-etherscan": "^3.1.0", + "ethers": "^5.0.5", + "hardhat": "^2.0.2" + }, + "peerDependenciesMeta": { + "@nomiclabs/harhdat-etherscan": { + "optional": true + } + } + }, + "node_modules/@openzeppelin/platform-deploy-client": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/platform-deploy-client/-/platform-deploy-client-0.8.0.tgz", + "integrity": "sha512-POx3AsnKwKSV/ZLOU/gheksj0Lq7Is1q2F3pKmcFjGZiibf+4kjGxr4eSMrT+2qgKYZQH1ZLQZ+SkbguD8fTvA==", + "deprecated": "@openzeppelin/platform-deploy-client is deprecated. Please use @openzeppelin/defender-sdk-deploy-client", + "dev": true, + "dependencies": { + "@ethersproject/abi": "^5.6.3", + "@openzeppelin/defender-base-client": "^1.46.0", + "axios": "^0.21.2", + "lodash": "^4.17.19", + "node-fetch": "^2.6.0" + } + }, + "node_modules/@openzeppelin/platform-deploy-client/node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/@openzeppelin/upgrades-core": { + "version": "1.32.5", + "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.32.5.tgz", + "integrity": "sha512-R0wprsyJ4xWiRW05kaTfZZkRVpG2g0af3/hpjE7t2mX0Eb2n40MQLokTwqIk4LDzpp910JfLSpB0vBuZ6WNPog==", + "dev": true, + "dependencies": { + "cbor": "^9.0.0", + "chalk": "^4.1.0", + "compare-versions": "^6.0.0", + "debug": "^4.1.1", + "ethereumjs-util": "^7.0.3", + "minimist": "^1.2.7", + "proper-lockfile": "^4.1.1", + "solidity-ast": "^0.4.51" + }, + "bin": { + "openzeppelin-upgrades-core": "dist/cli/cli.js" + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/cbor": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", + "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", + "dev": true, + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -2625,6 +2777,24 @@ "node": ">=6" } }, + "node_modules/@smithy/types": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.11.0.tgz", + "integrity": "sha512-AR0SXO7FuAskfNhyGfSTThpLRntDI5bOrU0xrpVYU0rZyjl3LBXInZFMTP/NNSd7IS6Ksdtar0QvnrPRIhVrLQ==", + "dev": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/types/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, "node_modules/@solidity-parser/parser": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.1.tgz", @@ -3213,6 +3383,30 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/amazon-cognito-identity-js": { + "version": "6.3.12", + "resolved": "https://registry.npmjs.org/amazon-cognito-identity-js/-/amazon-cognito-identity-js-6.3.12.tgz", + "integrity": "sha512-s7NKDZgx336cp+oDeUtB2ZzT8jWJp/v2LWuYl+LQtMEODe22RF1IJ4nRiDATp+rp1pTffCZcm44Quw4jx2bqNg==", + "dev": true, + "dependencies": { + "@aws-crypto/sha256-js": "1.2.2", + "buffer": "4.9.2", + "fast-base64-decode": "^1.0.0", + "isomorphic-unfetch": "^3.0.0", + "js-cookie": "^2.2.1" + } + }, + "node_modules/amazon-cognito-identity-js/node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, "node_modules/amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", @@ -3339,13 +3533,16 @@ } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3395,6 +3592,25 @@ "node": ">=0.10.0" } }, + "node_modules/array.prototype.findlast": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.4.tgz", + "integrity": "sha512-BMtLxpV+8BD+6ZPFIWmnUBpQoy+A+ujcg4rhp2iwCRJYA7PEh2MS4NL3lz8EiDlLrJPp2hg9qWihr5pd//jcGw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array.prototype.flat": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", @@ -3451,6 +3667,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -3498,6 +3736,15 @@ "dev": true, "peer": true }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "dev": true, + "dependencies": { + "retry": "0.13.1" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -3515,10 +3762,13 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -3767,13 +4017,19 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4342,6 +4598,12 @@ "dot-prop": "^5.1.0" } }, + "node_modules/compare-versions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz", + "integrity": "sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==", + "dev": true + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -4643,12 +4905,30 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "node_modules/define-properties": { + "node_modules/define-data-property": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -4839,45 +5119,52 @@ } }, "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", + "version": "1.22.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz", + "integrity": "sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.1", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.0", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.5", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -4886,52 +5173,55 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-abstract/node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true, + "peer": true + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, - "peer": true + "engines": { + "node": ">= 0.4" + } }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "node_modules/es-to-primitive": { @@ -5632,7 +5922,6 @@ "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz", "integrity": "sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A==", "dev": true, - "peer": true, "dependencies": { "@types/bn.js": "^5.1.0", "bn.js": "^5.1.2", @@ -5649,7 +5938,6 @@ "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", "dev": true, - "peer": true, "dependencies": { "@types/node": "*" } @@ -5658,15 +5946,13 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/ethereumjs-util/node_modules/ethereum-cryptography": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", "dev": true, - "peer": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -5811,6 +6097,12 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/fast-base64-decode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz", + "integrity": "sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==", + "dev": true + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -6065,21 +6357,24 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" }, "engines": { "node": ">= 0.4" @@ -6123,14 +6418,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6158,13 +6458,14 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -7062,21 +7363,21 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, "engines": { "node": ">= 0.4" @@ -7098,12 +7399,12 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -7170,6 +7471,18 @@ "minimalistic-assert": "^1.0.1" } }, + "node_modules/hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -7389,13 +7702,13 @@ "dev": true }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -7422,14 +7735,16 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7588,9 +7903,9 @@ } }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "engines": { "node": ">= 0.4" @@ -7667,12 +7982,15 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7733,16 +8051,12 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -7787,6 +8101,16 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "node_modules/isomorphic-unfetch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz", + "integrity": "sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==", + "dev": true, + "dependencies": { + "node-fetch": "^2.6.1", + "unfetch": "^4.2.0" + } + }, "node_modules/jackspeak": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", @@ -7805,6 +8129,12 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/js-cookie": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", + "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==", + "dev": true + }, "node_modules/js-sdsl": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", @@ -8640,10 +8970,13 @@ } }, "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/minimist-options": { "version": "4.1.0", @@ -8978,6 +9311,26 @@ "semver": "bin/semver" } }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-gyp-build": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", @@ -8994,7 +9347,6 @@ "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", "dev": true, - "peer": true, "engines": { "node": ">=12.19" } @@ -9080,9 +9432,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9098,14 +9450,14 @@ } }, "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, "engines": { @@ -9466,6 +9818,15 @@ "node": ">=4" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -9553,6 +9914,26 @@ "asap": "~2.0.6" } }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "node_modules/proper-lockfile/node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -9830,14 +10211,15 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -9964,6 +10346,15 @@ "node": ">=8" } }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -10122,6 +10513,30 @@ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", "dev": true }, + "node_modules/safe-array-concat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -10138,15 +10553,18 @@ } }, "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -10300,6 +10718,38 @@ "dev": true, "peer": true }, + "node_modules/set-function-length": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -10627,6 +11077,15 @@ "semver": "bin/semver.js" } }, + "node_modules/solidity-ast": { + "version": "0.4.55", + "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.55.tgz", + "integrity": "sha512-qeEU/r/K+V5lrAw8iswf2/yfWAnSGs3WKPHI+zAFKFjX0dIBVXEU/swQ8eJQYHf6PJWUZFO2uWV4V1wEOkeQbA==", + "dev": true, + "dependencies": { + "array.prototype.findlast": "^1.2.2" + } + }, "node_modules/solidity-comments-extractor": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz", @@ -11259,14 +11718,14 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -11276,28 +11735,28 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11636,6 +12095,12 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, "node_modules/trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", @@ -11900,15 +12365,74 @@ "node": ">= 4.0.0" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", + "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11984,6 +12508,12 @@ "node": ">=12.18" } }, + "node_modules/unfetch": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", + "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==", + "dev": true + }, "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -12102,6 +12632,22 @@ "xhr-request-promise": "^0.1.2" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -12141,17 +12687,16 @@ "peer": true }, "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", + "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.5", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.1" }, "engines": { "node": ">= 0.4" diff --git a/package.json b/package.json index 9321c362..563ab442 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "@onchain-id/solidity": "^2.0.0", "@openzeppelin/contracts": "^4.8.3", "@openzeppelin/contracts-upgradeable": "^4.8.3", + "@openzeppelin/hardhat-upgrades": "^1.28.0", "@primitivefi/hardhat-dodoc": "^0.2.3", "@xyrusworx/hardhat-solidity-json": "^1.0.2", "eslint": "^8.39.0", diff --git a/test/compliances/module-conditional-transfer.test.ts b/test/compliances/module-conditional-transfer.test.ts index 104f9263..f27c66fa 100644 --- a/test/compliances/module-conditional-transfer.test.ts +++ b/test/compliances/module-conditional-transfer.test.ts @@ -1,5 +1,5 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; -import { ethers } from 'hardhat'; +import { ethers, upgrades } from 'hardhat'; import { expect } from 'chai'; import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; @@ -8,7 +8,9 @@ describe('ConditionalTransferModule', () => { const context = await loadFixture(deployComplianceFixture); const { compliance } = context.suite; - const conditionalTransferModule = await ethers.deployContract('ConditionalTransferModule'); + const ConditionalTransferModule = await ethers.getContractFactory('ConditionalTransferModule'); + const conditionalTransferModule = await upgrades.deployProxy(ConditionalTransferModule, []); + await compliance.addModule(conditionalTransferModule.address); const mockContract = await ethers.deployContract('MockContract'); @@ -42,6 +44,64 @@ describe('ConditionalTransferModule', () => { }); }); + describe('.owner', () => { + it('should return owner', async () => { + const context = await loadFixture(deployComplianceWithConditionalTransferModule); + await expect(context.suite.conditionalTransferModule.owner()).to.eventually.be.eq(context.accounts.deployer.address); + }); + }); + + describe('.transferOwnership', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployComplianceWithConditionalTransferModule); + await expect( + context.suite.conditionalTransferModule.connect(context.accounts.aliceWallet).transferOwnership(context.accounts.bobWallet.address), + ).to.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when calling with owner account', () => { + it('should transfer ownership', async () => { + // given + const context = await loadFixture(deployComplianceWithConditionalTransferModule); + + // when + await context.suite.conditionalTransferModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + + // then + const owner = await context.suite.conditionalTransferModule.owner(); + expect(owner).to.eq(context.accounts.bobWallet.address); + }); + }); + }); + + describe('.upgradeTo', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployComplianceWithConditionalTransferModule); + await expect( + context.suite.conditionalTransferModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero), + ).to.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when calling with owner account', () => { + it('should upgrade proxy', async () => { + // given + const context = await loadFixture(deployComplianceWithConditionalTransferModule); + const newImplementation = await ethers.deployContract('ConditionalTransferModule'); + + // when + await context.suite.conditionalTransferModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + + // then + const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.conditionalTransferModule.address); + expect(implementationAddress).to.eq(newImplementation.address); + }); + }); + }); + describe('.batchApproveTransfers', () => { describe('when the sender is not the compliance', () => { it('should revert', async () => { diff --git a/test/compliances/module-country-allow.test.ts b/test/compliances/module-country-allow.test.ts index eeed3e98..b7c28391 100644 --- a/test/compliances/module-country-allow.test.ts +++ b/test/compliances/module-country-allow.test.ts @@ -1,5 +1,5 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; -import { ethers } from 'hardhat'; +import { ethers, upgrades } from 'hardhat'; import { expect } from 'chai'; import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; @@ -8,7 +8,8 @@ describe('CountryAllowModule', () => { const context = await loadFixture(deployComplianceFixture); const { compliance } = context.suite; - const countryAllowModule = await ethers.deployContract('CountryAllowModule'); + const CountryAllowModule = await ethers.getContractFactory('CountryAllowModule'); + const countryAllowModule = await upgrades.deployProxy(CountryAllowModule, []); await compliance.addModule(countryAllowModule.address); return { ...context, suite: { ...context.suite, countryAllowModule } }; @@ -38,6 +39,64 @@ describe('CountryAllowModule', () => { }); }); + describe('.owner', () => { + it('should return owner', async () => { + const context = await loadFixture(deployComplianceWithCountryAllowModule); + await expect(context.suite.countryAllowModule.owner()).to.eventually.be.eq(context.accounts.deployer.address); + }); + }); + + describe('.transferOwnership', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployComplianceWithCountryAllowModule); + await expect( + context.suite.countryAllowModule.connect(context.accounts.aliceWallet).transferOwnership(context.accounts.bobWallet.address), + ).to.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when calling with owner account', () => { + it('should transfer ownership', async () => { + // given + const context = await loadFixture(deployComplianceWithCountryAllowModule); + + // when + await context.suite.countryAllowModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + + // then + const owner = await context.suite.countryAllowModule.owner(); + expect(owner).to.eq(context.accounts.bobWallet.address); + }); + }); + }); + + describe('.upgradeTo', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployComplianceWithCountryAllowModule); + await expect(context.suite.countryAllowModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero)).to.revertedWith( + 'Ownable: caller is not the owner', + ); + }); + }); + + describe('when calling with owner account', () => { + it('should upgrade proxy', async () => { + // given + const context = await loadFixture(deployComplianceWithCountryAllowModule); + const newImplementation = await ethers.deployContract('CountryAllowModule'); + + // when + await context.suite.countryAllowModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + + // then + const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.countryAllowModule.address); + expect(implementationAddress).to.eq(newImplementation.address); + }); + }); + }); + describe('.batchAllowCountries()', () => { describe('when calling not via the Compliance contract', () => { it('should revert', async () => { diff --git a/test/compliances/module-country-restrict.test.ts b/test/compliances/module-country-restrict.test.ts index 87671117..2c1b7077 100644 --- a/test/compliances/module-country-restrict.test.ts +++ b/test/compliances/module-country-restrict.test.ts @@ -1,5 +1,5 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; -import { ethers } from 'hardhat'; +import { ethers, upgrades } from 'hardhat'; import { expect } from 'chai'; import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; @@ -8,7 +8,8 @@ describe('CountryRestrictModule', () => { const context = await loadFixture(deployComplianceFixture); const { compliance } = context.suite; - const countryRestrictModule = await ethers.deployContract('CountryRestrictModule'); + const CountryRestrictModule = await ethers.getContractFactory('CountryRestrictModule'); + const countryRestrictModule = await upgrades.deployProxy(CountryRestrictModule, []); await compliance.addModule(countryRestrictModule.address); return { ...context, suite: { ...context.suite, countryRestrictModule } }; @@ -38,6 +39,64 @@ describe('CountryRestrictModule', () => { }); }); + describe('.owner', () => { + it('should return owner', async () => { + const context = await loadFixture(deployComplianceWithCountryRestrictModule); + await expect(context.suite.countryRestrictModule.owner()).to.eventually.be.eq(context.accounts.deployer.address); + }); + }); + + describe('.transferOwnership', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployComplianceWithCountryRestrictModule); + await expect( + context.suite.countryRestrictModule.connect(context.accounts.aliceWallet).transferOwnership(context.accounts.bobWallet.address), + ).to.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when calling with owner account', () => { + it('should transfer ownership', async () => { + // given + const context = await loadFixture(deployComplianceWithCountryRestrictModule); + + // when + await context.suite.countryRestrictModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + + // then + const owner = await context.suite.countryRestrictModule.owner(); + expect(owner).to.eq(context.accounts.bobWallet.address); + }); + }); + }); + + describe('.upgradeTo', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployComplianceWithCountryRestrictModule); + await expect( + context.suite.countryRestrictModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero), + ).to.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when calling with owner account', () => { + it('should upgrade proxy', async () => { + // given + const context = await loadFixture(deployComplianceWithCountryRestrictModule); + const newImplementation = await ethers.deployContract('CountryRestrictModule'); + + // when + await context.suite.countryRestrictModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + + // then + const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.countryRestrictModule.address); + expect(implementationAddress).to.eq(newImplementation.address); + }); + }); + }); + describe('.addCountryRestriction()', () => { describe('when the sender is a random wallet', () => { it('should reverts', async () => { diff --git a/test/compliances/module-exchange-monthly-limits.test.ts b/test/compliances/module-exchange-monthly-limits.test.ts index 1ff23098..0c87ce42 100644 --- a/test/compliances/module-exchange-monthly-limits.test.ts +++ b/test/compliances/module-exchange-monthly-limits.test.ts @@ -1,5 +1,5 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; -import { ethers } from 'hardhat'; +import { ethers, upgrades } from 'hardhat'; import { expect } from 'chai'; import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; @@ -7,7 +7,8 @@ import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-ful async function deployExchangeMonthlyLimitsFixture() { const context = await loadFixture(deployComplianceFixture); - const complianceModule = await ethers.deployContract('ExchangeMonthlyLimitsModule'); + const ExchangeMonthlyLimitsModule = await ethers.getContractFactory('ExchangeMonthlyLimitsModule'); + const complianceModule = await upgrades.deployProxy(ExchangeMonthlyLimitsModule, []); await context.suite.compliance.addModule(complianceModule.address); return { @@ -21,7 +22,8 @@ async function deployExchangeMonthlyLimitsFixture() { async function deployExchangeMonthlyLimitsFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); - const complianceModule = await ethers.deployContract('ExchangeMonthlyLimitsModule'); + const ExchangeMonthlyLimitsModule = await ethers.getContractFactory('ExchangeMonthlyLimitsModule'); + const complianceModule = await upgrades.deployProxy(ExchangeMonthlyLimitsModule, []); await context.suite.compliance.bindToken(context.suite.token.address); await context.suite.compliance.addModule(complianceModule.address); @@ -64,6 +66,64 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { }); }); + describe('.owner', () => { + it('should return owner', async () => { + const context = await loadFixture(deployExchangeMonthlyLimitsFixture); + await expect(context.contracts.complianceModule.owner()).to.eventually.be.eq(context.accounts.deployer.address); + }); + }); + + describe('.transferOwnership', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployExchangeMonthlyLimitsFixture); + await expect( + context.contracts.complianceModule.connect(context.accounts.aliceWallet).transferOwnership(context.accounts.bobWallet.address), + ).to.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when calling with owner account', () => { + it('should transfer ownership', async () => { + // given + const context = await loadFixture(deployExchangeMonthlyLimitsFixture); + + // when + await context.contracts.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + + // then + const owner = await context.contracts.complianceModule.owner(); + expect(owner).to.eq(context.accounts.bobWallet.address); + }); + }); + }); + + describe('.upgradeTo', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployExchangeMonthlyLimitsFixture); + await expect( + context.contracts.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero), + ).to.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when calling with owner account', () => { + it('should upgrade proxy', async () => { + // given + const context = await loadFixture(deployExchangeMonthlyLimitsFixture); + const newImplementation = await ethers.deployContract('ExchangeMonthlyLimitsModule'); + + // when + await context.contracts.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + + // then + const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.contracts.complianceModule.address); + expect(implementationAddress).to.eq(newImplementation.address); + }); + }); + }); + describe('.setExchangeMonthlyLimit', () => { describe('when calling directly', () => { it('should revert', async () => { diff --git a/test/compliances/module-max-balance.test.ts b/test/compliances/module-max-balance.test.ts index be0d1f10..9d69620c 100644 --- a/test/compliances/module-max-balance.test.ts +++ b/test/compliances/module-max-balance.test.ts @@ -1,12 +1,13 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; -import { ethers } from 'hardhat'; +import { ethers, upgrades } from 'hardhat'; import { expect } from 'chai'; import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; async function deployMaxBalanceFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); - const complianceModule = await ethers.deployContract('MaxBalanceModule'); + const MaxBalanceModule = await ethers.getContractFactory('MaxBalanceModule'); + const complianceModule = await upgrades.deployProxy(MaxBalanceModule, []); await context.suite.token.connect(context.accounts.tokenAgent).burn(context.accounts.aliceWallet.address, 1000); await context.suite.token.connect(context.accounts.tokenAgent).burn(context.accounts.bobWallet.address, 500); await context.suite.compliance.bindToken(context.suite.token.address); @@ -101,6 +102,64 @@ describe('Compliance Module: MaxBalance', () => { }); }); + describe('.owner', () => { + it('should return owner', async () => { + const context = await loadFixture(deployMaxBalanceFullSuite); + await expect(context.suite.complianceModule.owner()).to.eventually.be.eq(context.accounts.deployer.address); + }); + }); + + describe('.transferOwnership', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployMaxBalanceFullSuite); + await expect( + context.suite.complianceModule.connect(context.accounts.aliceWallet).transferOwnership(context.accounts.bobWallet.address), + ).to.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when calling with owner account', () => { + it('should transfer ownership', async () => { + // given + const context = await loadFixture(deployMaxBalanceFullSuite); + + // when + await context.suite.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + + // then + const owner = await context.suite.complianceModule.owner(); + expect(owner).to.eq(context.accounts.bobWallet.address); + }); + }); + }); + + describe('.upgradeTo', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployMaxBalanceFullSuite); + await expect(context.suite.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero)).to.revertedWith( + 'Ownable: caller is not the owner', + ); + }); + }); + + describe('when calling with owner account', () => { + it('should upgrade proxy', async () => { + // given + const context = await loadFixture(deployMaxBalanceFullSuite); + const newImplementation = await ethers.deployContract('MaxBalanceModule'); + + // when + await context.suite.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + + // then + const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.complianceModule.address); + expect(implementationAddress).to.eq(newImplementation.address); + }); + }); + }); + describe('.preSetModuleState', () => { describe('when calling directly', () => { it('should revert', async () => { diff --git a/test/compliances/module-supply-limit.test.ts b/test/compliances/module-supply-limit.test.ts index f1b8a7ff..522d50d8 100644 --- a/test/compliances/module-supply-limit.test.ts +++ b/test/compliances/module-supply-limit.test.ts @@ -1,5 +1,5 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; -import { ethers } from 'hardhat'; +import { ethers, upgrades } from 'hardhat'; import { expect } from 'chai'; import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; @@ -7,7 +7,8 @@ import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-ful async function deploySupplyLimitFixture() { const context = await loadFixture(deployComplianceFixture); - const complianceModule = await ethers.deployContract('SupplyLimitModule'); + const SupplyLimitModule = await ethers.getContractFactory('SupplyLimitModule'); + const complianceModule = await upgrades.deployProxy(SupplyLimitModule, []); await context.suite.compliance.addModule(complianceModule.address); return { @@ -21,7 +22,8 @@ async function deploySupplyLimitFixture() { async function deploySupplyLimitFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); - const complianceModule = await ethers.deployContract('SupplyLimitModule'); + const SupplyLimitModule = await ethers.getContractFactory('SupplyLimitModule'); + const complianceModule = await upgrades.deployProxy(SupplyLimitModule, []); await context.suite.compliance.bindToken(context.suite.token.address); await context.suite.compliance.addModule(complianceModule.address); @@ -64,6 +66,64 @@ describe('Compliance Module: SupplyLimit', () => { }); }); + describe('.owner', () => { + it('should return owner', async () => { + const context = await loadFixture(deploySupplyLimitFixture); + await expect(context.suite.complianceModule.owner()).to.eventually.be.eq(context.accounts.deployer.address); + }); + }); + + describe('.transferOwnership', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deploySupplyLimitFixture); + await expect( + context.suite.complianceModule.connect(context.accounts.aliceWallet).transferOwnership(context.accounts.bobWallet.address), + ).to.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when calling with owner account', () => { + it('should transfer ownership', async () => { + // given + const context = await loadFixture(deploySupplyLimitFixture); + + // when + await context.suite.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + + // then + const owner = await context.suite.complianceModule.owner(); + expect(owner).to.eq(context.accounts.bobWallet.address); + }); + }); + }); + + describe('.upgradeTo', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deploySupplyLimitFixture); + await expect(context.suite.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero)).to.revertedWith( + 'Ownable: caller is not the owner', + ); + }); + }); + + describe('when calling with owner account', () => { + it('should upgrade proxy', async () => { + // given + const context = await loadFixture(deploySupplyLimitFixture); + const newImplementation = await ethers.deployContract('SupplyLimitModule'); + + // when + await context.suite.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + + // then + const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.complianceModule.address); + expect(implementationAddress).to.eq(newImplementation.address); + }); + }); + }); + describe('.setSupplyLimit', () => { describe('when calling directly', () => { it('should revert', async () => { diff --git a/test/compliances/module-time-exchange-limits.test.ts b/test/compliances/module-time-exchange-limits.test.ts index 21ba292e..f8c584b8 100644 --- a/test/compliances/module-time-exchange-limits.test.ts +++ b/test/compliances/module-time-exchange-limits.test.ts @@ -1,5 +1,5 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; -import { ethers } from 'hardhat'; +import { ethers, upgrades } from 'hardhat'; import { expect } from 'chai'; import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; @@ -7,7 +7,8 @@ import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-ful async function deployTimeExchangeLimitsFixture() { const context = await loadFixture(deployComplianceFixture); - const complianceModule = await ethers.deployContract('TimeExchangeLimitsModule'); + const TimeExchangeLimitsModule = await ethers.getContractFactory('TimeExchangeLimitsModule'); + const complianceModule = await upgrades.deployProxy(TimeExchangeLimitsModule, []); await context.suite.compliance.addModule(complianceModule.address); return { @@ -21,7 +22,8 @@ async function deployTimeExchangeLimitsFixture() { async function deployTimeExchangeLimitsFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); - const complianceModule = await ethers.deployContract('TimeExchangeLimitsModule'); + const TimeExchangeLimitsModule = await ethers.getContractFactory('TimeExchangeLimitsModule'); + const complianceModule = await upgrades.deployProxy(TimeExchangeLimitsModule, []); await context.suite.compliance.bindToken(context.suite.token.address); await context.suite.compliance.addModule(complianceModule.address); @@ -50,6 +52,64 @@ describe('Compliance Module: TimeExchangeLimits', () => { }); }); + describe('.owner', () => { + it('should return owner', async () => { + const context = await loadFixture(deployTimeExchangeLimitsFixture); + await expect(context.contracts.complianceModule.owner()).to.eventually.be.eq(context.accounts.deployer.address); + }); + }); + + describe('.transferOwnership', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployTimeExchangeLimitsFixture); + await expect( + context.contracts.complianceModule.connect(context.accounts.aliceWallet).transferOwnership(context.accounts.bobWallet.address), + ).to.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when calling with owner account', () => { + it('should transfer ownership', async () => { + // given + const context = await loadFixture(deployTimeExchangeLimitsFixture); + + // when + await context.contracts.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + + // then + const owner = await context.contracts.complianceModule.owner(); + expect(owner).to.eq(context.accounts.bobWallet.address); + }); + }); + }); + + describe('.upgradeTo', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployTimeExchangeLimitsFixture); + await expect( + context.contracts.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero), + ).to.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when calling with owner account', () => { + it('should upgrade proxy', async () => { + // given + const context = await loadFixture(deployTimeExchangeLimitsFixture); + const newImplementation = await ethers.deployContract('TimeExchangeLimitsModule'); + + // when + await context.contracts.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + + // then + const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.contracts.complianceModule.address); + expect(implementationAddress).to.eq(newImplementation.address); + }); + }); + }); + describe('.setExchangeLimit', () => { describe('when calling directly', () => { it('should revert', async () => { diff --git a/test/compliances/module-time-transfer-limits.test.ts b/test/compliances/module-time-transfer-limits.test.ts index 2592b85f..4686eaa2 100644 --- a/test/compliances/module-time-transfer-limits.test.ts +++ b/test/compliances/module-time-transfer-limits.test.ts @@ -1,5 +1,5 @@ import { loadFixture, time } from '@nomicfoundation/hardhat-network-helpers'; -import { ethers } from 'hardhat'; +import { ethers, upgrades } from 'hardhat'; import { expect } from 'chai'; import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; @@ -7,7 +7,8 @@ import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-ful async function deployTimeTransferLimitsFixture() { const context = await loadFixture(deployComplianceFixture); - const complianceModule = await ethers.deployContract('TimeTransfersLimitsModule'); + const TimeTransfersLimitsModule = await ethers.getContractFactory('TimeTransfersLimitsModule'); + const complianceModule = await upgrades.deployProxy(TimeTransfersLimitsModule, []); await context.suite.compliance.addModule(complianceModule.address); return { @@ -21,7 +22,8 @@ async function deployTimeTransferLimitsFixture() { async function deployTimeTransferLimitsFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); - const complianceModule = await ethers.deployContract('TimeTransfersLimitsModule'); + const TimeTransfersLimitsModule = await ethers.getContractFactory('TimeTransfersLimitsModule'); + const complianceModule = await upgrades.deployProxy(TimeTransfersLimitsModule, []); await context.suite.compliance.bindToken(context.suite.token.address); await context.suite.compliance.addModule(complianceModule.address); @@ -50,6 +52,64 @@ describe('Compliance Module: TimeTransferLimits', () => { }); }); + describe('.owner', () => { + it('should return owner', async () => { + const context = await loadFixture(deployTimeTransferLimitsFixture); + await expect(context.contracts.complianceModule.owner()).to.eventually.be.eq(context.accounts.deployer.address); + }); + }); + + describe('.transferOwnership', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployTimeTransferLimitsFixture); + await expect( + context.contracts.complianceModule.connect(context.accounts.aliceWallet).transferOwnership(context.accounts.bobWallet.address), + ).to.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when calling with owner account', () => { + it('should transfer ownership', async () => { + // given + const context = await loadFixture(deployTimeTransferLimitsFixture); + + // when + await context.contracts.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + + // then + const owner = await context.contracts.complianceModule.owner(); + expect(owner).to.eq(context.accounts.bobWallet.address); + }); + }); + }); + + describe('.upgradeTo', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployTimeTransferLimitsFixture); + await expect( + context.contracts.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero), + ).to.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when calling with owner account', () => { + it('should upgrade proxy', async () => { + // given + const context = await loadFixture(deployTimeTransferLimitsFixture); + const newImplementation = await ethers.deployContract('TimeTransfersLimitsModule'); + + // when + await context.contracts.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + + // then + const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.contracts.complianceModule.address); + expect(implementationAddress).to.eq(newImplementation.address); + }); + }); + }); + describe('.setTimeTransferLimit', () => { describe('when calling directly', () => { it('should revert', async () => { diff --git a/test/compliances/module-transfer-fees.test.ts b/test/compliances/module-transfer-fees.test.ts index 1520fbbc..32a04648 100644 --- a/test/compliances/module-transfer-fees.test.ts +++ b/test/compliances/module-transfer-fees.test.ts @@ -1,11 +1,12 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; -import { ethers } from 'hardhat'; +import { ethers, upgrades } from 'hardhat'; import { expect } from 'chai'; import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; async function deployTransferFeesFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); - const complianceModule = await ethers.deployContract('TransferFeesModule'); + const TransferFeesModule = await ethers.getContractFactory('TransferFeesModule'); + const complianceModule = await upgrades.deployProxy(TransferFeesModule, []); await context.suite.token.addAgent(complianceModule.address); await context.suite.compliance.bindToken(context.suite.token.address); await context.suite.compliance.addModule(complianceModule.address); @@ -30,6 +31,64 @@ describe('Compliance Module: TransferFees', () => { expect(await context.suite.compliance.isModuleBound(context.suite.complianceModule.address)).to.be.true; }); + describe('.owner', () => { + it('should return owner', async () => { + const context = await loadFixture(deployTransferFeesFullSuite); + await expect(context.suite.complianceModule.owner()).to.eventually.be.eq(context.accounts.deployer.address); + }); + }); + + describe('.transferOwnership', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployTransferFeesFullSuite); + await expect( + context.suite.complianceModule.connect(context.accounts.aliceWallet).transferOwnership(context.accounts.bobWallet.address), + ).to.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when calling with owner account', () => { + it('should transfer ownership', async () => { + // given + const context = await loadFixture(deployTransferFeesFullSuite); + + // when + await context.suite.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + + // then + const owner = await context.suite.complianceModule.owner(); + expect(owner).to.eq(context.accounts.bobWallet.address); + }); + }); + }); + + describe('.upgradeTo', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployTransferFeesFullSuite); + await expect(context.suite.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero)).to.revertedWith( + 'Ownable: caller is not the owner', + ); + }); + }); + + describe('when calling with owner account', () => { + it('should upgrade proxy', async () => { + // given + const context = await loadFixture(deployTransferFeesFullSuite); + const newImplementation = await ethers.deployContract('TransferFeesModule'); + + // when + await context.suite.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + + // then + const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.complianceModule.address); + expect(implementationAddress).to.eq(newImplementation.address); + }); + }); + }); + describe('.setFee', () => { describe('when calling directly', () => { it('should revert', async () => { diff --git a/test/compliances/module-transfer-restrict.test.ts b/test/compliances/module-transfer-restrict.test.ts index ae8bce2a..d8f86e00 100644 --- a/test/compliances/module-transfer-restrict.test.ts +++ b/test/compliances/module-transfer-restrict.test.ts @@ -1,11 +1,12 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; -import { ethers } from 'hardhat'; +import { ethers, upgrades } from 'hardhat'; import { expect } from 'chai'; import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; async function deployTransferRestrictFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); - const complianceModule = await ethers.deployContract('TransferRestrictModule'); + const TransferRestrictModule = await ethers.getContractFactory('TransferRestrictModule'); + const complianceModule = await upgrades.deployProxy(TransferRestrictModule, []); await context.suite.compliance.bindToken(context.suite.token.address); await context.suite.compliance.addModule(complianceModule.address); @@ -49,6 +50,64 @@ describe('Compliance Module: TransferRestrict', () => { }); }); + describe('.owner', () => { + it('should return owner', async () => { + const context = await loadFixture(deployTransferRestrictFullSuite); + await expect(context.suite.complianceModule.owner()).to.eventually.be.eq(context.accounts.deployer.address); + }); + }); + + describe('.transferOwnership', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployTransferRestrictFullSuite); + await expect( + context.suite.complianceModule.connect(context.accounts.aliceWallet).transferOwnership(context.accounts.bobWallet.address), + ).to.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when calling with owner account', () => { + it('should transfer ownership', async () => { + // given + const context = await loadFixture(deployTransferRestrictFullSuite); + + // when + await context.suite.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + + // then + const owner = await context.suite.complianceModule.owner(); + expect(owner).to.eq(context.accounts.bobWallet.address); + }); + }); + }); + + describe('.upgradeTo', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployTransferRestrictFullSuite); + await expect(context.suite.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero)).to.revertedWith( + 'Ownable: caller is not the owner', + ); + }); + }); + + describe('when calling with owner account', () => { + it('should upgrade proxy', async () => { + // given + const context = await loadFixture(deployTransferRestrictFullSuite); + const newImplementation = await ethers.deployContract('TransferRestrictModule'); + + // when + await context.suite.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + + // then + const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.complianceModule.address); + expect(implementationAddress).to.eq(newImplementation.address); + }); + }); + }); + describe('.allowUser', () => { describe('when calling directly', () => { it('should revert', async () => { From b8d9e4b84f3b7b938d61725fa0d6d276324a7130 Mon Sep 17 00:00:00 2001 From: "ali.arbak" Date: Mon, 11 Mar 2024 16:43:21 +0300 Subject: [PATCH 08/55] Add module proxy --- .../TestUpgradedCountryAllowModule.sol | 80 +++++++++++++++++++ .../modular/modules/ModuleProxy.sol | 69 ++++++++++++++++ index.d.ts | 2 + index.js | 4 + .../module-conditional-transfer.test.ts | 5 +- test/compliances/module-country-allow.test.ts | 31 +++++-- .../module-country-restrict.test.ts | 6 +- .../module-exchange-monthly-limits.test.ts | 6 +- test/compliances/module-max-balance.test.ts | 7 +- test/compliances/module-supply-limit.test.ts | 6 +- .../module-time-exchange-limits.test.ts | 6 +- .../module-time-transfer-limits.test.ts | 7 +- test/compliances/module-transfer-fees.test.ts | 7 +- .../module-transfer-restrict.test.ts | 6 +- 14 files changed, 217 insertions(+), 25 deletions(-) create mode 100644 contracts/_testContracts/TestUpgradedCountryAllowModule.sol create mode 100644 contracts/compliance/modular/modules/ModuleProxy.sol diff --git a/contracts/_testContracts/TestUpgradedCountryAllowModule.sol b/contracts/_testContracts/TestUpgradedCountryAllowModule.sol new file mode 100644 index 00000000..3a3316a7 --- /dev/null +++ b/contracts/_testContracts/TestUpgradedCountryAllowModule.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-3.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2023, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +pragma solidity 0.8.17; + +import "../compliance/modular/modules/CountryAllowModule.sol"; + +contract TestUpgradedCountryAllowModule is CountryAllowModule { + /// new field + uint256 private _newField; + + // setter for _newField + function setNewField(uint256 value) external onlyOwner { + _newField = value; + } + + // getter for _newField + function getNewField() external view returns (uint256) { + return _newField; + } +} diff --git a/contracts/compliance/modular/modules/ModuleProxy.sol b/contracts/compliance/modular/modules/ModuleProxy.sol new file mode 100644 index 00000000..71c5586a --- /dev/null +++ b/contracts/compliance/modular/modules/ModuleProxy.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-3.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2023, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +pragma solidity 0.8.17; + +import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + +contract ModuleProxy is ERC1967Proxy { + constructor(address implementation, bytes memory _data) ERC1967Proxy(implementation, _data) { } +} \ No newline at end of file diff --git a/index.d.ts b/index.d.ts index 65d49032..5aa94f57 100644 --- a/index.d.ts +++ b/index.d.ts @@ -57,6 +57,8 @@ export namespace contracts { export const ModularCompliance: ContractJSON; // compliance/modular/modules export const AbstractModule: ContractJSON; + export const AbstractModuleUpgradeable: ContractJSON; + export const ModuleProxy: ContractJSON; export const ConditionalTransferModule: ContractJSON; export const CountryAllowModule: ContractJSON; export const CountryRestrictModule: ContractJSON; diff --git a/index.js b/index.js index 4a2d8819..5d2563ec 100644 --- a/index.js +++ b/index.js @@ -60,6 +60,8 @@ const ModularCompliance = require('./artifacts/contracts/compliance/modular/Modu // compliance/modular/modules const IModule = require('./artifacts/contracts/compliance/modular/modules/IModule.sol/IModule.json'); const AbstractModule = require('./artifacts/contracts/compliance/modular/modules/AbstractModule.sol/AbstractModule.json'); +const AbstractModuleUpgradeable = require('./artifacts/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol/AbstractModuleUpgradeable.json'); +const ModuleProxy = require('./artifacts/contracts/compliance/modular/modules/ModuleProxy.sol/ModuleProxy.json'); const ConditionalTransferModule = require('./artifacts/contracts/compliance/modular/modules/ConditionalTransferModule.sol/ConditionalTransferModule.json'); const CountryAllowModule = require('./artifacts/contracts/compliance/modular/modules/CountryAllowModule.sol/CountryAllowModule.json'); const CountryRestrictModule = require('./artifacts/contracts/compliance/modular/modules/CountryRestrictModule.sol/CountryRestrictModule.json'); @@ -121,6 +123,8 @@ module.exports = { ModularCompliance, // compliance/modular/modules AbstractModule, + AbstractModuleUpgradeable, + ModuleProxy, ConditionalTransferModule, CountryAllowModule, CountryRestrictModule, diff --git a/test/compliances/module-conditional-transfer.test.ts b/test/compliances/module-conditional-transfer.test.ts index f27c66fa..5999d766 100644 --- a/test/compliances/module-conditional-transfer.test.ts +++ b/test/compliances/module-conditional-transfer.test.ts @@ -8,8 +8,9 @@ describe('ConditionalTransferModule', () => { const context = await loadFixture(deployComplianceFixture); const { compliance } = context.suite; - const ConditionalTransferModule = await ethers.getContractFactory('ConditionalTransferModule'); - const conditionalTransferModule = await upgrades.deployProxy(ConditionalTransferModule, []); + const module = await ethers.deployContract('ConditionalTransferModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); + const conditionalTransferModule = await ethers.getContractAt('ConditionalTransferModule', proxy.address); await compliance.addModule(conditionalTransferModule.address); diff --git a/test/compliances/module-country-allow.test.ts b/test/compliances/module-country-allow.test.ts index b7c28391..7a400d23 100644 --- a/test/compliances/module-country-allow.test.ts +++ b/test/compliances/module-country-allow.test.ts @@ -8,8 +8,9 @@ describe('CountryAllowModule', () => { const context = await loadFixture(deployComplianceFixture); const { compliance } = context.suite; - const CountryAllowModule = await ethers.getContractFactory('CountryAllowModule'); - const countryAllowModule = await upgrades.deployProxy(CountryAllowModule, []); + const module = await ethers.deployContract('CountryAllowModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); + const countryAllowModule = await ethers.getContractAt('CountryAllowModule', proxy.address); await compliance.addModule(countryAllowModule.address); return { ...context, suite: { ...context.suite, countryAllowModule } }; @@ -84,15 +85,33 @@ describe('CountryAllowModule', () => { describe('when calling with owner account', () => { it('should upgrade proxy', async () => { // given - const context = await loadFixture(deployComplianceWithCountryAllowModule); - const newImplementation = await ethers.deployContract('CountryAllowModule'); + const { + suite: { countryAllowModule, compliance }, + accounts: { deployer }, + } = await loadFixture(deployComplianceWithCountryAllowModule); + + await compliance + .connect(deployer) + .callModuleFunction( + new ethers.utils.Interface(['function addAllowedCountry(uint16 country)']).encodeFunctionData('addAllowedCountry', [42]), + countryAllowModule.address, + ); + + const newImplementation = await ethers.deployContract('TestUpgradedCountryAllowModule'); // when - await context.suite.countryAllowModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + await countryAllowModule.connect(deployer).upgradeTo(newImplementation.address); // then - const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.countryAllowModule.address); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(countryAllowModule.address); expect(implementationAddress).to.eq(newImplementation.address); + + const upgradedContract = await ethers.getContractAt('TestUpgradedCountryAllowModule', countryAllowModule.address); + expect(await upgradedContract.isCountryAllowed(compliance.address, 42)).to.be.true; + expect(await upgradedContract.isComplianceBound(compliance.address)).to.be.true; + + await upgradedContract.connect(deployer).setNewField(222); + expect(await upgradedContract.getNewField()).to.be.eq(222); }); }); }); diff --git a/test/compliances/module-country-restrict.test.ts b/test/compliances/module-country-restrict.test.ts index 2c1b7077..322a0d3a 100644 --- a/test/compliances/module-country-restrict.test.ts +++ b/test/compliances/module-country-restrict.test.ts @@ -8,10 +8,10 @@ describe('CountryRestrictModule', () => { const context = await loadFixture(deployComplianceFixture); const { compliance } = context.suite; - const CountryRestrictModule = await ethers.getContractFactory('CountryRestrictModule'); - const countryRestrictModule = await upgrades.deployProxy(CountryRestrictModule, []); + const module = await ethers.deployContract('CountryRestrictModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); + const countryRestrictModule = await ethers.getContractAt('CountryRestrictModule', proxy.address); await compliance.addModule(countryRestrictModule.address); - return { ...context, suite: { ...context.suite, countryRestrictModule } }; } diff --git a/test/compliances/module-exchange-monthly-limits.test.ts b/test/compliances/module-exchange-monthly-limits.test.ts index 0c87ce42..358c1ac1 100644 --- a/test/compliances/module-exchange-monthly-limits.test.ts +++ b/test/compliances/module-exchange-monthly-limits.test.ts @@ -7,8 +7,10 @@ import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-ful async function deployExchangeMonthlyLimitsFixture() { const context = await loadFixture(deployComplianceFixture); - const ExchangeMonthlyLimitsModule = await ethers.getContractFactory('ExchangeMonthlyLimitsModule'); - const complianceModule = await upgrades.deployProxy(ExchangeMonthlyLimitsModule, []); + const module = await ethers.deployContract('ExchangeMonthlyLimitsModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('ExchangeMonthlyLimitsModule', proxy.address); + await context.suite.compliance.addModule(complianceModule.address); return { diff --git a/test/compliances/module-max-balance.test.ts b/test/compliances/module-max-balance.test.ts index 9d69620c..c7c5f622 100644 --- a/test/compliances/module-max-balance.test.ts +++ b/test/compliances/module-max-balance.test.ts @@ -6,8 +6,11 @@ import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-ful async function deployMaxBalanceFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); - const MaxBalanceModule = await ethers.getContractFactory('MaxBalanceModule'); - const complianceModule = await upgrades.deployProxy(MaxBalanceModule, []); + + const module = await ethers.deployContract('MaxBalanceModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('MaxBalanceModule', proxy.address); + await context.suite.token.connect(context.accounts.tokenAgent).burn(context.accounts.aliceWallet.address, 1000); await context.suite.token.connect(context.accounts.tokenAgent).burn(context.accounts.bobWallet.address, 500); await context.suite.compliance.bindToken(context.suite.token.address); diff --git a/test/compliances/module-supply-limit.test.ts b/test/compliances/module-supply-limit.test.ts index 522d50d8..eba24e25 100644 --- a/test/compliances/module-supply-limit.test.ts +++ b/test/compliances/module-supply-limit.test.ts @@ -7,8 +7,10 @@ import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-ful async function deploySupplyLimitFixture() { const context = await loadFixture(deployComplianceFixture); - const SupplyLimitModule = await ethers.getContractFactory('SupplyLimitModule'); - const complianceModule = await upgrades.deployProxy(SupplyLimitModule, []); + const module = await ethers.deployContract('SupplyLimitModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('SupplyLimitModule', proxy.address); + await context.suite.compliance.addModule(complianceModule.address); return { diff --git a/test/compliances/module-time-exchange-limits.test.ts b/test/compliances/module-time-exchange-limits.test.ts index f8c584b8..f87e55a3 100644 --- a/test/compliances/module-time-exchange-limits.test.ts +++ b/test/compliances/module-time-exchange-limits.test.ts @@ -7,8 +7,10 @@ import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-ful async function deployTimeExchangeLimitsFixture() { const context = await loadFixture(deployComplianceFixture); - const TimeExchangeLimitsModule = await ethers.getContractFactory('TimeExchangeLimitsModule'); - const complianceModule = await upgrades.deployProxy(TimeExchangeLimitsModule, []); + const module = await ethers.deployContract('TimeExchangeLimitsModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('TimeExchangeLimitsModule', proxy.address); + await context.suite.compliance.addModule(complianceModule.address); return { diff --git a/test/compliances/module-time-transfer-limits.test.ts b/test/compliances/module-time-transfer-limits.test.ts index 4686eaa2..9ee60278 100644 --- a/test/compliances/module-time-transfer-limits.test.ts +++ b/test/compliances/module-time-transfer-limits.test.ts @@ -22,8 +22,11 @@ async function deployTimeTransferLimitsFixture() { async function deployTimeTransferLimitsFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); - const TimeTransfersLimitsModule = await ethers.getContractFactory('TimeTransfersLimitsModule'); - const complianceModule = await upgrades.deployProxy(TimeTransfersLimitsModule, []); + + const module = await ethers.deployContract('TimeTransfersLimitsModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('TimeTransfersLimitsModule', proxy.address); + await context.suite.compliance.bindToken(context.suite.token.address); await context.suite.compliance.addModule(complianceModule.address); diff --git a/test/compliances/module-transfer-fees.test.ts b/test/compliances/module-transfer-fees.test.ts index 32a04648..174639ea 100644 --- a/test/compliances/module-transfer-fees.test.ts +++ b/test/compliances/module-transfer-fees.test.ts @@ -5,8 +5,11 @@ import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-ful async function deployTransferFeesFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); - const TransferFeesModule = await ethers.getContractFactory('TransferFeesModule'); - const complianceModule = await upgrades.deployProxy(TransferFeesModule, []); + + const module = await ethers.deployContract('TransferFeesModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('TransferFeesModule', proxy.address); + await context.suite.token.addAgent(complianceModule.address); await context.suite.compliance.bindToken(context.suite.token.address); await context.suite.compliance.addModule(complianceModule.address); diff --git a/test/compliances/module-transfer-restrict.test.ts b/test/compliances/module-transfer-restrict.test.ts index d8f86e00..8ea37162 100644 --- a/test/compliances/module-transfer-restrict.test.ts +++ b/test/compliances/module-transfer-restrict.test.ts @@ -5,8 +5,10 @@ import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-ful async function deployTransferRestrictFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); - const TransferRestrictModule = await ethers.getContractFactory('TransferRestrictModule'); - const complianceModule = await upgrades.deployProxy(TransferRestrictModule, []); + const module = await ethers.deployContract('TransferRestrictModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('TransferRestrictModule', proxy.address); + await context.suite.compliance.bindToken(context.suite.token.address); await context.suite.compliance.addModule(complianceModule.address); From cd90523f0d3b8fda51eb60e598477494aa10dc44 Mon Sep 17 00:00:00 2001 From: "ali.arbak" Date: Mon, 11 Mar 2024 17:06:08 +0300 Subject: [PATCH 09/55] Fix lint issue --- contracts/compliance/modular/modules/ModuleProxy.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/compliance/modular/modules/ModuleProxy.sol b/contracts/compliance/modular/modules/ModuleProxy.sol index 71c5586a..32d921a4 100644 --- a/contracts/compliance/modular/modules/ModuleProxy.sol +++ b/contracts/compliance/modular/modules/ModuleProxy.sol @@ -65,5 +65,6 @@ pragma solidity 0.8.17; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; contract ModuleProxy is ERC1967Proxy { + // solhint-disable-next-line no-empty-blocks constructor(address implementation, bytes memory _data) ERC1967Proxy(implementation, _data) { } } \ No newline at end of file From db8daec63a2b7266d94477bf23ef97906e5c41c5 Mon Sep 17 00:00:00 2001 From: "ali.arbak" Date: Mon, 11 Mar 2024 18:19:51 +0300 Subject: [PATCH 10/55] Add initializer tests --- .DS_Store | Bin 6148 -> 0 bytes .../module-conditional-transfer.test.ts | 15 ++++++++++++++ test/compliances/module-country-allow.test.ts | 19 ++++++++++++++++-- .../module-country-restrict.test.ts | 15 ++++++++++++++ .../module-exchange-monthly-limits.test.ts | 15 ++++++++++++++ test/compliances/module-max-balance.test.ts | 15 ++++++++++++++ test/compliances/module-supply-limit.test.ts | 15 ++++++++++++++ .../module-time-exchange-limits.test.ts | 15 ++++++++++++++ .../module-time-transfer-limits.test.ts | 15 ++++++++++++++ test/compliances/module-transfer-fees.test.ts | 16 +++++++++++++++ .../module-transfer-restrict.test.ts | 16 +++++++++++++++ 11 files changed, 154 insertions(+), 2 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 7b0e5820b8e619e472083570f7196fab403fcf9a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK-AcnS6i&A3T86L-gNcZU%-l9sLa+)E!JkNoxK=?Uh50_BtDPl zB&j$y!7CAW4xD_+`Dw_Pl9MpTcy}^rF;-`cS)hm|8=578e$)ji84Ds;-?(EwyJaa$ zf@~q041bXU+&dd~Z4A2>vM>9WjDko8;C%~5QJAET^Uh1<%G!F>s#-Pc+Ix_hm-^`> z>H6bK9GyuS1x4Qv&ck8WuWug9IQ7GLI93VaU zJ$Q@EB7=|^AO?tmRbjxKe^zZ(7EJ3T28e+lGl1uV07Y~S<{H(}0S#Us(O*GCfj+(^ z5QRb4V6G87AY7*c>Qru?7+j}=U6?r6V6IW8Gp=Ta@0gjnd7*GMJJ^K^XWZ3DEiph0 z%rj8d!#dXglkeaE^GP%!28e-w#Q?ALyj~ZUWNPce;;_~V&>K(`jLS8Cra(uPVu;03 c+yGSqc7Yv0*I=#@EFg3dP&80O4E!nsAN(3kW&i*H diff --git a/test/compliances/module-conditional-transfer.test.ts b/test/compliances/module-conditional-transfer.test.ts index 5999d766..5134cffd 100644 --- a/test/compliances/module-conditional-transfer.test.ts +++ b/test/compliances/module-conditional-transfer.test.ts @@ -52,6 +52,21 @@ describe('ConditionalTransferModule', () => { }); }); + describe('.initialize', () => { + it('should be called only once', async () => { + // given + const { + accounts: { deployer }, + } = await loadFixture(deployComplianceFixture); + const module = (await ethers.deployContract('ConditionalTransferModule')).connect(deployer); + await module.initialize(); + + // when & then + await expect(module.initialize()).to.be.revertedWith('Initializable: contract is already initialized'); + expect(await module.owner()).to.be.eq(deployer.address); + }); + }); + describe('.transferOwnership', () => { describe('when calling directly', () => { it('should revert', async () => { diff --git a/test/compliances/module-country-allow.test.ts b/test/compliances/module-country-allow.test.ts index 7a400d23..bf446d86 100644 --- a/test/compliances/module-country-allow.test.ts +++ b/test/compliances/module-country-allow.test.ts @@ -47,6 +47,21 @@ describe('CountryAllowModule', () => { }); }); + describe('.initialize', () => { + it('should be called only once', async () => { + // given + const { + accounts: { deployer }, + } = await loadFixture(deployComplianceFixture); + const module = (await ethers.deployContract('CountryAllowModule')).connect(deployer); + await module.initialize(); + + // when & then + await expect(module.initialize()).to.be.revertedWith('Initializable: contract is already initialized'); + expect(await module.owner()).to.be.eq(deployer.address); + }); + }); + describe('.transferOwnership', () => { describe('when calling directly', () => { it('should revert', async () => { @@ -107,11 +122,11 @@ describe('CountryAllowModule', () => { expect(implementationAddress).to.eq(newImplementation.address); const upgradedContract = await ethers.getContractAt('TestUpgradedCountryAllowModule', countryAllowModule.address); - expect(await upgradedContract.isCountryAllowed(compliance.address, 42)).to.be.true; - expect(await upgradedContract.isComplianceBound(compliance.address)).to.be.true; + expect(await upgradedContract.getNewField()).to.be.eq(0); await upgradedContract.connect(deployer).setNewField(222); expect(await upgradedContract.getNewField()).to.be.eq(222); + expect(await upgradedContract.isCountryAllowed(compliance.address, 42)).to.be.true; }); }); }); diff --git a/test/compliances/module-country-restrict.test.ts b/test/compliances/module-country-restrict.test.ts index 322a0d3a..b11c5669 100644 --- a/test/compliances/module-country-restrict.test.ts +++ b/test/compliances/module-country-restrict.test.ts @@ -46,6 +46,21 @@ describe('CountryRestrictModule', () => { }); }); + describe('.initialize', () => { + it('should be called only once', async () => { + // given + const { + accounts: { deployer }, + } = await loadFixture(deployComplianceFixture); + const module = (await ethers.deployContract('CountryRestrictModule')).connect(deployer); + await module.initialize(); + + // when & then + await expect(module.initialize()).to.be.revertedWith('Initializable: contract is already initialized'); + expect(await module.owner()).to.be.eq(deployer.address); + }); + }); + describe('.transferOwnership', () => { describe('when calling directly', () => { it('should revert', async () => { diff --git a/test/compliances/module-exchange-monthly-limits.test.ts b/test/compliances/module-exchange-monthly-limits.test.ts index 358c1ac1..8adda7e2 100644 --- a/test/compliances/module-exchange-monthly-limits.test.ts +++ b/test/compliances/module-exchange-monthly-limits.test.ts @@ -75,6 +75,21 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { }); }); + describe('.initialize', () => { + it('should be called only once', async () => { + // given + const { + accounts: { deployer }, + } = await loadFixture(deployComplianceFixture); + const module = (await ethers.deployContract('ExchangeMonthlyLimitsModule')).connect(deployer); + await module.initialize(); + + // when & then + await expect(module.initialize()).to.be.revertedWith('Initializable: contract is already initialized'); + expect(await module.owner()).to.be.eq(deployer.address); + }); + }); + describe('.transferOwnership', () => { describe('when calling directly', () => { it('should revert', async () => { diff --git a/test/compliances/module-max-balance.test.ts b/test/compliances/module-max-balance.test.ts index c7c5f622..73d37199 100644 --- a/test/compliances/module-max-balance.test.ts +++ b/test/compliances/module-max-balance.test.ts @@ -112,6 +112,21 @@ describe('Compliance Module: MaxBalance', () => { }); }); + describe('.initialize', () => { + it('should be called only once', async () => { + // given + const { + accounts: { deployer }, + } = await loadFixture(deployComplianceFixture); + const module = (await ethers.deployContract('MaxBalanceModule')).connect(deployer); + await module.initialize(); + + // when & then + await expect(module.initialize()).to.be.revertedWith('Initializable: contract is already initialized'); + expect(await module.owner()).to.be.eq(deployer.address); + }); + }); + describe('.transferOwnership', () => { describe('when calling directly', () => { it('should revert', async () => { diff --git a/test/compliances/module-supply-limit.test.ts b/test/compliances/module-supply-limit.test.ts index eba24e25..a3c800f1 100644 --- a/test/compliances/module-supply-limit.test.ts +++ b/test/compliances/module-supply-limit.test.ts @@ -75,6 +75,21 @@ describe('Compliance Module: SupplyLimit', () => { }); }); + describe('.initialize', () => { + it('should be called only once', async () => { + // given + const { + accounts: { deployer }, + } = await loadFixture(deployComplianceFixture); + const module = (await ethers.deployContract('SupplyLimitModule')).connect(deployer); + await module.initialize(); + + // when & then + await expect(module.initialize()).to.be.revertedWith('Initializable: contract is already initialized'); + expect(await module.owner()).to.be.eq(deployer.address); + }); + }); + describe('.transferOwnership', () => { describe('when calling directly', () => { it('should revert', async () => { diff --git a/test/compliances/module-time-exchange-limits.test.ts b/test/compliances/module-time-exchange-limits.test.ts index f87e55a3..4362b4da 100644 --- a/test/compliances/module-time-exchange-limits.test.ts +++ b/test/compliances/module-time-exchange-limits.test.ts @@ -61,6 +61,21 @@ describe('Compliance Module: TimeExchangeLimits', () => { }); }); + describe('.initialize', () => { + it('should be called only once', async () => { + // given + const { + accounts: { deployer }, + } = await loadFixture(deployComplianceFixture); + const module = (await ethers.deployContract('TimeExchangeLimitsModule')).connect(deployer); + await module.initialize(); + + // when & then + await expect(module.initialize()).to.be.revertedWith('Initializable: contract is already initialized'); + expect(await module.owner()).to.be.eq(deployer.address); + }); + }); + describe('.transferOwnership', () => { describe('when calling directly', () => { it('should revert', async () => { diff --git a/test/compliances/module-time-transfer-limits.test.ts b/test/compliances/module-time-transfer-limits.test.ts index 9ee60278..c3120b61 100644 --- a/test/compliances/module-time-transfer-limits.test.ts +++ b/test/compliances/module-time-transfer-limits.test.ts @@ -62,6 +62,21 @@ describe('Compliance Module: TimeTransferLimits', () => { }); }); + describe('.initialize', () => { + it('should be called only once', async () => { + // given + const { + accounts: { deployer }, + } = await loadFixture(deployComplianceFixture); + const module = (await ethers.deployContract('TimeTransfersLimitsModule')).connect(deployer); + await module.initialize(); + + // when & then + await expect(module.initialize()).to.be.revertedWith('Initializable: contract is already initialized'); + expect(await module.owner()).to.be.eq(deployer.address); + }); + }); + describe('.transferOwnership', () => { describe('when calling directly', () => { it('should revert', async () => { diff --git a/test/compliances/module-transfer-fees.test.ts b/test/compliances/module-transfer-fees.test.ts index 174639ea..c63e5b6f 100644 --- a/test/compliances/module-transfer-fees.test.ts +++ b/test/compliances/module-transfer-fees.test.ts @@ -2,6 +2,7 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { ethers, upgrades } from 'hardhat'; import { expect } from 'chai'; import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; +import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; async function deployTransferFeesFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); @@ -66,6 +67,21 @@ describe('Compliance Module: TransferFees', () => { }); }); + describe('.initialize', () => { + it('should be called only once', async () => { + // given + const { + accounts: { deployer }, + } = await loadFixture(deployComplianceFixture); + const module = (await ethers.deployContract('TransferFeesModule')).connect(deployer); + await module.initialize(); + + // when & then + await expect(module.initialize()).to.be.revertedWith('Initializable: contract is already initialized'); + expect(await module.owner()).to.be.eq(deployer.address); + }); + }); + describe('.upgradeTo', () => { describe('when calling directly', () => { it('should revert', async () => { diff --git a/test/compliances/module-transfer-restrict.test.ts b/test/compliances/module-transfer-restrict.test.ts index 8ea37162..3a560dff 100644 --- a/test/compliances/module-transfer-restrict.test.ts +++ b/test/compliances/module-transfer-restrict.test.ts @@ -2,6 +2,7 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { ethers, upgrades } from 'hardhat'; import { expect } from 'chai'; import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; +import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; async function deployTransferRestrictFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); @@ -59,6 +60,21 @@ describe('Compliance Module: TransferRestrict', () => { }); }); + describe('.initialize', () => { + it('should be called only once', async () => { + // given + const { + accounts: { deployer }, + } = await loadFixture(deployComplianceFixture); + const module = (await ethers.deployContract('TransferRestrictModule')).connect(deployer); + await module.initialize(); + + // when & then + await expect(module.initialize()).to.be.revertedWith('Initializable: contract is already initialized'); + expect(await module.owner()).to.be.eq(deployer.address); + }); + }); + describe('.transferOwnership', () => { describe('when calling directly', () => { it('should revert', async () => { From a67c2a822388bd4e0bc9f63f006414753c299139 Mon Sep 17 00:00:00 2001 From: "ali.arbak" Date: Fri, 15 Mar 2024 16:26:09 +0300 Subject: [PATCH 11/55] Update changelog and package version --- CHANGELOG.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53268eda..074ef788 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log All notable changes to this project will be documented in this file. +## [4.1.4] + +### Added + +- Introduced **AbstractModuleUpgradeable**: Enables compliance modules to be compatible with ERC-1967 and ERC-1822 standards. +- Introduced **ModuleProxy**: ERC-1967 compliant proxy contract for Upgradeable compliance modules. + +### Update +- Upgraded all compliance modules to inherit from `AbstractModuleUpgradeable` and made them Upgradeable. + ## [4.1.3] ### Update diff --git a/package.json b/package.json index 563ab442..0ef2ea2a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tokenysolutions/t-rex", - "version": "4.1.3", + "version": "4.1.4", "description": "A fully compliant environment for the issuance and use of tokenized securities.", "main": "index.js", "directories": { From 3fa85964348326acf93672dee3eb3b792a3120a2 Mon Sep 17 00:00:00 2001 From: "ali.arbak" Date: Thu, 4 Apr 2024 13:22:42 +0300 Subject: [PATCH 12/55] Add token listing restrictions module --- CHANGELOG.md | 8 + .../TokenListingRestrictionsModule.sol | 381 ++++++++++ index.d.ts | 1 + index.js | 2 + package.json | 2 +- .../module-token-listing-restrictions.test.ts | 707 ++++++++++++++++++ 6 files changed, 1100 insertions(+), 1 deletion(-) create mode 100644 contracts/compliance/modular/modules/TokenListingRestrictionsModule.sol create mode 100644 test/compliances/module-token-listing-restrictions.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 074ef788..8b03d6fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ # Change Log All notable changes to this project will be documented in this file. +## [4.1.5] + +### Added +- Introduced **Token Listing Restrictions Module**: Investors can determine which tokens they can receive by whitelisting or blacklisting them + Token issuers can choose the listing type they prefer for their tokens: + WHITELISTING: investors must whitelist/allow the token address in order to receive it. + BLACKLISTING: investors can receive the token by default. If they do not want to receive it, they need to blacklist/disallow it. + ## [4.1.4] ### Added diff --git a/contracts/compliance/modular/modules/TokenListingRestrictionsModule.sol b/contracts/compliance/modular/modules/TokenListingRestrictionsModule.sol new file mode 100644 index 00000000..b2255aea --- /dev/null +++ b/contracts/compliance/modular/modules/TokenListingRestrictionsModule.sol @@ -0,0 +1,381 @@ +// SPDX-License-Identifier: GPL-3.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2023, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +pragma solidity 0.8.17; + +import "../IModularCompliance.sol"; +import "../../../token/IToken.sol"; +import "./AbstractModuleUpgradeable.sol"; + +contract TokenListingRestrictionsModule is AbstractModuleUpgradeable { + enum ListingType { + NOT_CONFIGURED, // default value (token is not configured yet) + WHITELISTING, + BLACKLISTING + } + + enum InvestorAddressType { + WALLET, + ONCHAINID + } + + /// Mapping between token and listing type + mapping(address => ListingType) private _tokenListingType; + + /// Mapping between tokenAddress and investor (wallet or OID address) + /// and listing status (whitelisted or blacklisted depending on the listing type of the token) + mapping(address => mapping(address => bool)) private _tokenInvestorListingStatus; + + /// events + /** + * this event is emitted whenever a token is configured with a non-zero listing type + * the event is emitted by 'configureToken'. + * _tokenAddress is the address of the configured token + * _listingType is the configured listing type for the token (1: WHITELISTING, 2: BLACKLISTING) + */ + event TokenListingConfigured(address _tokenAddress, ListingType _listingType); + + /** + * this event is emitted whenever a token is listed (whitelisted or blacklisted) for an investor + * the event is emitted by 'listToken'. + * _tokenAddress is the address of the listed token + * _investorAddress is the investor address (a wallet or an ONCHAINID address) + */ + event TokenListed(address _tokenAddress, address _investorAddress); + + /** + * this event is emitted whenever a token is unlisted for an investor + * the event is emitted by 'unlistToken'. + * _tokenAddress is the address of the unlisted token + * _investorAddress is the investor address (a wallet or an ONCHAINID address) + */ + event TokenUnlisted(address _tokenAddress, address _investorAddress); + + /// Custom Errors + error TokenAlreadyConfigured(address _tokenAddress); + + error TokenIsNotConfigured(address _tokenAddress); + + error TokenAlreadyListed(address _tokenAddress, address _investorAddress); + + error TokenIsNotListed(address _tokenAddress, address _investorAddress); + + error IdentityNotFound(address _tokenAddress, address _userAddress); + + error InvalidListingTypeForConfiguration(ListingType _listingType); + + /// functions + /** + * @dev initializes the contract and sets the initial state. + * @notice This function should only be called once during the contract deployment. + */ + function initialize() external initializer { + __AbstractModule_init(); + } + + /** + * @dev Configures the listing type of a token + * Can only be called once per token + * @param _listingType can be WHITELISTING(1) or BLACKLISTING(2) + * WHITELISTING(1): investors must whitelist/allow the token address in order to receive it + * BLACKLISTING(2): investors can receive this token by default. If they do not want to receive it, + * they need to blacklist/disallow it. + * Only the owner of the Compliance smart contract can call this function + */ + function configureToken(ListingType _listingType) external onlyComplianceCall { + address tokenAddress = _getBoundTokenAddress(msg.sender); + if (_listingType == ListingType.NOT_CONFIGURED) { + revert InvalidListingTypeForConfiguration(_listingType); + } + + if (_tokenListingType[tokenAddress] != ListingType.NOT_CONFIGURED) { + revert TokenAlreadyConfigured(tokenAddress); + } + + _tokenListingType[tokenAddress] = _listingType; + emit TokenListingConfigured(tokenAddress, _listingType); + } + + /** + * @dev Lists a token for the investor (caller) + * If the token listing type is WHITELISTING, it will be whitelisted/allowed for the investor. + * If the token listing type is BLACKLISTING, it will be blaclisted/disallowed for the investor. + * @param _tokenAddress is the address of the token to be listed + * @param _addressType can be WALLET(0) or ONCHAINID(1) + * If it is WALLET, the token will be listed only for the caller wallet address + * If it is ONCHAINID, the token will be listed for the ONCHAINID (it will be applied to all wallet addresses of the OID) + * It will revert if the listing type of the token is not configured + */ + function listToken(address _tokenAddress, InvestorAddressType _addressType) external { + if (_tokenListingType[_tokenAddress] == ListingType.NOT_CONFIGURED) { + revert TokenIsNotConfigured(_tokenAddress); + } + + address investorAddress = _getInvestorAddressByAddressType(_tokenAddress, msg.sender, _addressType); + if (_tokenInvestorListingStatus[_tokenAddress][investorAddress]) { + revert TokenAlreadyListed(_tokenAddress, investorAddress); + } + + _tokenInvestorListingStatus[_tokenAddress][investorAddress] = true; + emit TokenListed(_tokenAddress, investorAddress); + } + + /** + * @dev Lists multiple tokens for the investor (caller) + * If the token listing type is WHITELISTING, it will be whitelisted/allowed for the investor. + * If the token listing type is BLACKLISTING, it will be blaclisted/disallowed for the investor. + * @param _tokenAddresses is the array of addresses of tokens to be listed + * @param _addressType can be WALLET(0) or ONCHAINID(1) + * If it is WALLET, the token will be listed only for the caller wallet address + * If it is ONCHAINID, the token will be listed for the ONCHAINID (it will be applied to all wallet addresses of the OID) + * It will revert if the listing type of the token is not configured + */ + function batchListTokens(address[] calldata _tokenAddresses, InvestorAddressType _addressType) external { + address investorAddress = msg.sender; + for (uint256 i = 0; i < _tokenAddresses.length; i++) { + address tokenAddress = _tokenAddresses[i]; + if (_tokenListingType[tokenAddress] == ListingType.NOT_CONFIGURED) { + revert TokenIsNotConfigured(tokenAddress); + } + + if (_addressType != InvestorAddressType.WALLET) { + investorAddress = _getInvestorAddressByAddressType(tokenAddress, msg.sender, _addressType); + } + + if (_tokenInvestorListingStatus[tokenAddress][investorAddress]) { + revert TokenAlreadyListed(tokenAddress, investorAddress); + } + + _tokenInvestorListingStatus[tokenAddress][investorAddress] = true; + emit TokenListed(tokenAddress, investorAddress); + } + } + + /** + * @dev Unlists a token for the investor (caller) + * @param _tokenAddress is the address of the token to be unlisted + * @param _addressType can be WALLET(0) or ONCHAINID(1) + * If it is WALLET, the token will be unlisted only for the caller wallet address + * If it is ONCHAINID, the token will be unlisted for the ONCHAINID + */ + function unlistToken(address _tokenAddress, InvestorAddressType _addressType) external { + address investorAddress = _getInvestorAddressByAddressType(_tokenAddress, msg.sender, _addressType); + if (!_tokenInvestorListingStatus[_tokenAddress][investorAddress]) { + revert TokenIsNotListed(_tokenAddress, investorAddress); + } + + _tokenInvestorListingStatus[_tokenAddress][investorAddress] = false; + emit TokenUnlisted(_tokenAddress, investorAddress); + } + + /** + * @dev Unlists multiple tokens for the investor (caller) + * @param _tokenAddresses is the array of addresses of tokens to be unlisted + * @param _addressType can be WALLET(0) or ONCHAINID(1) + * If it is WALLET, the token will be unlisted only for the caller wallet address + * If it is ONCHAINID, the token will be unlisted for the ONCHAINID + */ + function batchUnlistTokens(address[] calldata _tokenAddresses, InvestorAddressType _addressType) external { + address investorAddress = msg.sender; + for (uint256 i = 0; i < _tokenAddresses.length; i++) { + address tokenAddress = _tokenAddresses[i]; + if (_addressType != InvestorAddressType.WALLET) { + investorAddress = _getInvestorAddressByAddressType(tokenAddress, msg.sender, _addressType); + } + + if (!_tokenInvestorListingStatus[tokenAddress][investorAddress]) { + revert TokenIsNotListed(tokenAddress, investorAddress); + } + + _tokenInvestorListingStatus[tokenAddress][investorAddress] = false; + emit TokenUnlisted(tokenAddress, investorAddress); + } + } + + /** + * @dev See {IModule-moduleTransferAction}. + * no transfer action required in this module + */ + // solhint-disable-next-line no-empty-blocks + function moduleTransferAction(address _from, address _to, uint256 _value) external override onlyComplianceCall {} + + /** + * @dev See {IModule-moduleMintAction}. + * no mint action required in this module + */ + // solhint-disable-next-line no-empty-blocks + function moduleMintAction(address _to, uint256 _value) external override onlyComplianceCall {} + + /** + * @dev See {IModule-moduleBurnAction}. + * no burn action required in this module + */ + // solhint-disable-next-line no-empty-blocks + function moduleBurnAction(address _from, uint256 _value) external override onlyComplianceCall {} + + /** + * @dev See {IModule-moduleCheck}. + * checks whether the _to address allows this token to receive + * returns TRUE if the token is allowed for the address of _to (or for the OID of _to) + * returns FALSE if the token is not allowed for the address of _to + */ + function moduleCheck( + address /*_from*/, + address _to, + uint256 /*_value*/, + address _compliance + ) external view override returns (bool) { + if (_to == address(0)) { + return true; + } + + address tokenAddress = _getBoundTokenAddress(_compliance); + ListingType listingType = _tokenListingType[tokenAddress]; + if (listingType == ListingType.NOT_CONFIGURED) { + return true; + } + + bool listed = _tokenInvestorListingStatus[tokenAddress][_to] + || _tokenInvestorListingStatus[tokenAddress][_getIdentityByTokenAddress(tokenAddress, _to)]; + + if (listingType == ListingType.BLACKLISTING) { + return !listed; + } + + return listed; + } + + /** + * @dev Returns the configured listing type of the given token address + * @param _tokenAddress the token smart contract to be checked + * returns the listing type of the token: + * NOT_CONFIGURED(0): The token is not configured for this module yet + * WHITELISTING(1): investors must whitelist/allow the token address in order to receive it + * BLACKLISTING(2): investors can receive this token by default. If they do not want to receive it, + * they need to blacklist/disallow it. + */ + function getTokenListingType(address _tokenAddress) external view returns (ListingType) { + return _tokenListingType[_tokenAddress]; + } + + /** + * @dev Returns the listing status of the given investor address for the token + * @param _tokenAddress the token smart contract to be checked + * @param _investorAddress the WALLET or ONCHAINID address of an investor to be checked + * returns the listing status of the given investor. + * If it is true: + * - if the listing type of the token is WHITELISTING(1): investor can receive this token. + * - if the listing type of the token is BLACKLISTING(2): investor can not receive this token. + * If it is false: + * - if the listing type of the token is WHITELISTING(1): investor can not receive this token. + * - if the listing type of the token is BLACKLISTING(2): investor can receive this token. + */ + function getInvestorListingStatus(address _tokenAddress, address _investorAddress) external view returns (bool) { + return _tokenInvestorListingStatus[_tokenAddress][_investorAddress]; + } + + /** + * @dev See {IModule-canComplianceBind}. + */ + function canComplianceBind(address /*_compliance*/) external pure override returns (bool) { + return true; + } + + /** + * @dev See {IModule-isPlugAndPlay}. + */ + function isPlugAndPlay() external pure override returns (bool) { + return true; + } + + /** + * @dev See {IModule-name}. + */ + function name() public pure returns (string memory _name) { + return "TokenListingRestrictionsModule"; + } + + function _getInvestorAddressByAddressType( + address _tokenAddress, + address _userAddress, + InvestorAddressType _addressType + ) internal view returns (address) { + if (_addressType == InvestorAddressType.WALLET) { + return _userAddress; + } + + address identity = _getIdentityByTokenAddress(_tokenAddress, _userAddress); + if (identity == address(0)) { + revert IdentityNotFound(_tokenAddress, _userAddress); + } + + return identity; + } + + function _getIdentityByTokenAddress(address _tokenAddress, address _userAddress) internal view returns (address) { + return address(IToken(_tokenAddress).identityRegistry().identity(_userAddress)); + } + + function _getBoundTokenAddress(address _compliance) internal view returns (address) { + return IModularCompliance(_compliance).getTokenBound(); + } +} diff --git a/index.d.ts b/index.d.ts index 5aa94f57..0b23e0f9 100644 --- a/index.d.ts +++ b/index.d.ts @@ -69,6 +69,7 @@ export namespace contracts { export const SupplyLimitModule: ContractJSON; export const TransferFeesModule: ContractJSON; export const TransferRestrictModule: ContractJSON; + export const TokenListingRestrictionsModule: ContractJSON; } export namespace interfaces { diff --git a/index.js b/index.js index 5d2563ec..0d843d22 100644 --- a/index.js +++ b/index.js @@ -72,6 +72,7 @@ const TimeTransfersLimitsModule = require('./artifacts/contracts/compliance/modu const SupplyLimitModule = require('./artifacts/contracts/compliance/modular/modules/SupplyLimitModule.sol/SupplyLimitModule.json'); const TransferFeesModule = require('./artifacts/contracts/compliance/modular/modules/TransferFeesModule.sol/TransferFeesModule.json'); const TransferRestrictModule = require('./artifacts/contracts/compliance/modular/modules/TransferRestrictModule.sol/TransferRestrictModule.json'); +const TokenListingRestrictionsModule = require('./artifacts/contracts/compliance/modular/modules/TokenListingRestrictionsModule.sol/TokenListingRestrictionsModule.json'); module.exports = { contracts: { @@ -135,6 +136,7 @@ module.exports = { SupplyLimitModule, TransferFeesModule, TransferRestrictModule, + TokenListingRestrictionsModule, }, interfaces: { IToken, diff --git a/package.json b/package.json index 0ef2ea2a..029ecf50 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tokenysolutions/t-rex", - "version": "4.1.4", + "version": "4.1.5", "description": "A fully compliant environment for the issuance and use of tokenized securities.", "main": "index.js", "directories": { diff --git a/test/compliances/module-token-listing-restrictions.test.ts b/test/compliances/module-token-listing-restrictions.test.ts new file mode 100644 index 00000000..bb49f827 --- /dev/null +++ b/test/compliances/module-token-listing-restrictions.test.ts @@ -0,0 +1,707 @@ +import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { ethers, upgrades } from 'hardhat'; +import { expect } from 'chai'; +import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; +import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; +import { compliance } from '../../typechain-types/contracts'; + +async function deployTokenListingRestrictionsFullSuite() { + const context = await loadFixture(deploySuiteWithModularCompliancesFixture); + const module = await ethers.deployContract('TokenListingRestrictionsModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('TokenListingRestrictionsModule', proxy.address); + + await context.suite.compliance.bindToken(context.suite.token.address); + await context.suite.compliance.addModule(complianceModule.address); + + return { + ...context, + suite: { + ...context.suite, + complianceModule, + }, + }; +} + +describe('Compliance Module: TokenListingRestrictions', () => { + it('should deploy the TokenListingRestrictions contract and bind it to the compliance', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + + expect(context.suite.complianceModule.address).not.to.be.undefined; + expect(await context.suite.compliance.isModuleBound(context.suite.complianceModule.address)).to.be.true; + }); + + describe('.name', () => { + it('should return the name of the module', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + + expect(await context.suite.complianceModule.name()).to.be.equal('TokenListingRestrictionsModule'); + }); + }); + + describe('.isPlugAndPlay', () => { + it('should return true', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + expect(await context.suite.complianceModule.isPlugAndPlay()).to.be.true; + }); + }); + + describe('.canComplianceBind', () => { + it('should return true', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + const complianceModule = await ethers.deployContract('TokenListingRestrictionsModule'); + expect(await complianceModule.canComplianceBind(context.suite.compliance.address)).to.be.true; + }); + }); + + describe('.owner', () => { + it('should return owner', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await expect(context.suite.complianceModule.owner()).to.eventually.be.eq(context.accounts.deployer.address); + }); + }); + + describe('.initialize', () => { + it('should be called only once', async () => { + // given + const { + accounts: { deployer }, + } = await loadFixture(deployComplianceFixture); + const module = (await ethers.deployContract('TokenListingRestrictionsModule')).connect(deployer); + await module.initialize(); + + // when & then + await expect(module.initialize()).to.be.revertedWith('Initializable: contract is already initialized'); + expect(await module.owner()).to.be.eq(deployer.address); + }); + }); + + describe('.transferOwnership', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await expect( + context.suite.complianceModule.connect(context.accounts.aliceWallet).transferOwnership(context.accounts.bobWallet.address), + ).to.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when calling with owner account', () => { + it('should transfer ownership', async () => { + // given + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + + // when + await context.suite.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + + // then + const owner = await context.suite.complianceModule.owner(); + expect(owner).to.eq(context.accounts.bobWallet.address); + }); + }); + }); + + describe('.upgradeTo', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await expect(context.suite.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero)).to.revertedWith( + 'Ownable: caller is not the owner', + ); + }); + }); + + describe('when calling with owner account', () => { + it('should upgrade proxy', async () => { + // given + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + const newImplementation = await ethers.deployContract('TokenListingRestrictionsModule'); + + // when + await context.suite.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + + // then + const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.complianceModule.address); + expect(implementationAddress).to.eq(newImplementation.address); + }); + }); + }); + + describe('.configureToken', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await expect(context.suite.complianceModule.configureToken(1)).to.revertedWith('only bound compliance can call'); + }); + }); + + describe('when calling via compliance', () => { + describe('when given listing type is zero (NOT_CONFIGURED)', () => { + it('should revert', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await expect( + context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [0]), + context.suite.complianceModule.address, + ), + ).to.be.revertedWithCustomError(context.suite.complianceModule, `InvalidListingTypeForConfiguration`); + }); + }); + + describe('when token is already configured', () => { + it('should revert', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + await expect( + context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [2]), + context.suite.complianceModule.address, + ), + ).to.be.revertedWithCustomError(context.suite.complianceModule, `TokenAlreadyConfigured`); + }); + }); + + describe('when token is not configured before', () => { + it('should configure the token', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + + const tx = await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + await expect(tx).to.emit(context.suite.complianceModule, 'TokenListingConfigured').withArgs(context.suite.token.address, 1); + }); + }); + }); + }); + + describe('.listToken', () => { + describe('when token is not configured', () => { + it('should revert', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await expect( + context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1), + ).to.be.revertedWithCustomError(context.suite.complianceModule, `TokenIsNotConfigured`); + }); + }); + + describe('when token is configured', () => { + describe('when token is listed before', () => { + it('should revert', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1); + + await expect( + context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1), + ).to.be.revertedWithCustomError(context.suite.complianceModule, `TokenAlreadyListed`); + }); + }); + + describe('when token is not already listed', () => { + describe('when the investor address type is WALLET', () => { + it('should list the token', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 0); + + await expect(tx) + .to.emit(context.suite.complianceModule, 'TokenListed') + .withArgs(context.suite.token.address, context.accounts.aliceWallet.address); + }); + }); + + describe('when the investor address type is ONCHAINID', () => { + describe('when identity does not exist', () => { + it('should revert', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + await expect( + context.suite.complianceModule.connect(context.accounts.anotherWallet).listToken(context.suite.token.address, 1), + ).to.be.revertedWithCustomError(context.suite.complianceModule, `IdentityNotFound`); + }); + }); + + describe('when identity exists', () => { + it('should list the token', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1); + + await expect(tx) + .to.emit(context.suite.complianceModule, 'TokenListed') + .withArgs(context.suite.token.address, context.identities.aliceIdentity.address); + }); + }); + }); + }); + }); + }); + + describe('.batchListTokens', () => { + describe('when token is not configured', () => { + it('should revert', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await expect( + context.suite.complianceModule.connect(context.accounts.aliceWallet).batchListTokens([context.suite.token.address], 1), + ).to.be.revertedWithCustomError(context.suite.complianceModule, `TokenIsNotConfigured`); + }); + }); + + describe('when token is configured', () => { + describe('when token is listed before', () => { + it('should revert', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1); + + await expect( + context.suite.complianceModule.connect(context.accounts.aliceWallet).batchListTokens([context.suite.token.address], 1), + ).to.be.revertedWithCustomError(context.suite.complianceModule, `TokenAlreadyListed`); + }); + }); + + describe('when token is not already listed', () => { + describe('when the investor address type is WALLET', () => { + it('should list tokens', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).batchListTokens([context.suite.token.address], 0); + + await expect(tx) + .to.emit(context.suite.complianceModule, 'TokenListed') + .withArgs(context.suite.token.address, context.accounts.aliceWallet.address); + }); + }); + + describe('when the investor address type is ONCHAINID', () => { + it('should list tokens', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).batchListTokens([context.suite.token.address], 1); + + await expect(tx) + .to.emit(context.suite.complianceModule, 'TokenListed') + .withArgs(context.suite.token.address, context.identities.aliceIdentity.address); + }); + }); + }); + }); + }); + + describe('.unlistToken', () => { + describe('when token is not listed', () => { + it('should revert', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + await expect( + context.suite.complianceModule.connect(context.accounts.aliceWallet).unlistToken(context.suite.token.address, 1), + ).to.be.revertedWithCustomError(context.suite.complianceModule, `TokenIsNotListed`); + }); + }); + + describe('when token is listed', () => { + describe('when the investor address type is WALLET', () => { + it('should unlist the token', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 0); + + const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).unlistToken(context.suite.token.address, 0); + + await expect(tx) + .to.emit(context.suite.complianceModule, 'TokenUnlisted') + .withArgs(context.suite.token.address, context.accounts.aliceWallet.address); + }); + }); + + describe('when the investor address type is ONCHAINID', () => { + it('should unlist the token', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1); + + const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).unlistToken(context.suite.token.address, 1); + + await expect(tx) + .to.emit(context.suite.complianceModule, 'TokenUnlisted') + .withArgs(context.suite.token.address, context.identities.aliceIdentity.address); + }); + }); + }); + }); + + describe('.batchUnlistTokens', () => { + describe('when token is not listed', () => { + it('should revert', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + await expect( + context.suite.complianceModule.connect(context.accounts.aliceWallet).batchUnlistTokens([context.suite.token.address], 1), + ).to.be.revertedWithCustomError(context.suite.complianceModule, `TokenIsNotListed`); + }); + }); + + describe('when token is not listed', () => { + describe('when the investor address type is WALLET', () => { + it('should unlist tokens', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 0); + + const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).batchUnlistTokens([context.suite.token.address], 0); + + await expect(tx) + .to.emit(context.suite.complianceModule, 'TokenUnlisted') + .withArgs(context.suite.token.address, context.accounts.aliceWallet.address); + }); + }); + + describe('when the investor address type is ONCHAINID', () => { + it('should unlist tokens', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1); + + const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).batchUnlistTokens([context.suite.token.address], 1); + + await expect(tx) + .to.emit(context.suite.complianceModule, 'TokenUnlisted') + .withArgs(context.suite.token.address, context.identities.aliceIdentity.address); + }); + }); + }); + }); + + describe('.getTokenListingType', () => { + describe('when token is not configured', () => { + it('should return NOT_CONFIGURED(0)', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + const result = await context.suite.complianceModule.getTokenListingType(context.suite.token.address); + expect(result).to.be.eq(0); + }); + }); + + describe('when token is configured', () => { + it('should return token listing type', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + const result = await context.suite.complianceModule.getTokenListingType(context.suite.token.address); + expect(result).to.be.eq(1); + }); + }); + }); + + describe('.getInvestorListingStatus', () => { + describe('when token is not listed', () => { + it('should return false', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + const result = await context.suite.complianceModule.getInvestorListingStatus( + context.suite.token.address, + context.accounts.aliceWallet.address, + ); + expect(result).to.be.false; + }); + }); + + describe('when token is listed', () => { + it('should return true', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 0); + + const result = await context.suite.complianceModule.getInvestorListingStatus( + context.suite.token.address, + context.accounts.aliceWallet.address, + ); + expect(result).to.be.true; + }); + }); + }); + + describe('.moduleCheck', () => { + describe('when receiver is the null address', () => { + it('should return true', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + const from = context.accounts.aliceWallet.address; + + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + const result = await context.suite.complianceModule.moduleCheck(from, ethers.constants.AddressZero, 10, context.suite.compliance.address); + expect(result).to.be.true; + }); + }); + + describe('when token is not configured', () => { + it('should return true', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + const from = context.accounts.aliceWallet.address; + const to = context.accounts.bobWallet.address; + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + expect(result).to.be.true; + }); + }); + + describe('when the listing type is WHITELISTING', () => { + describe('when token is not listed', () => { + it('should return false', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + const to = context.accounts.aliceWallet.address; + const from = context.accounts.bobWallet.address; + + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + expect(result).to.be.false; + }); + }); + + describe('when token is listed for the wallet', () => { + it('should return true', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + const to = context.accounts.aliceWallet.address; + const from = context.accounts.bobWallet.address; + + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 0); + + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + expect(result).to.be.true; + }); + }); + + describe('when token is listed for the OID', () => { + it('should return true', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + const to = context.accounts.aliceWallet.address; + const from = context.accounts.bobWallet.address; + + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.address, + ); + + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1); + + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + expect(result).to.be.true; + }); + }); + }); + + describe('when the listing type is BLACKLISTING', () => { + describe('when token is not listed', () => { + it('should return true', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + const to = context.accounts.aliceWallet.address; + const from = context.accounts.bobWallet.address; + + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [2]), + context.suite.complianceModule.address, + ); + + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + expect(result).to.be.true; + }); + }); + + describe('when token is listed for the wallet', () => { + it('should return false', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + const to = context.accounts.aliceWallet.address; + const from = context.accounts.bobWallet.address; + + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [2]), + context.suite.complianceModule.address, + ); + + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 0); + + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + expect(result).to.be.false; + }); + }); + + describe('when token is listed for the OID', () => { + it('should return false', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + const to = context.accounts.aliceWallet.address; + const from = context.accounts.bobWallet.address; + + await context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [2]), + context.suite.complianceModule.address, + ); + + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1); + + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + expect(result).to.be.false; + }); + }); + }); + }); + + describe('.moduleMintAction', () => { + describe('when calling from a random wallet', () => { + it('should revert', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + + await expect(context.suite.complianceModule.moduleMintAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWith( + 'only bound compliance can call', + ); + }); + }); + + describe('when calling as the compliance', () => { + it('should do nothing', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + + await expect( + context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ + context.accounts.anotherWallet.address, + 10, + ]), + context.suite.complianceModule.address, + ), + ).to.eventually.be.fulfilled; + }); + }); + }); + + describe('.moduleBurnAction', () => { + describe('when calling from a random wallet', () => { + it('should revert', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + + await expect(context.suite.complianceModule.moduleBurnAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWith( + 'only bound compliance can call', + ); + }); + }); + + describe('when calling as the compliance', () => { + it('should do nothing', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + + await expect( + context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ + context.accounts.anotherWallet.address, + 10, + ]), + context.suite.complianceModule.address, + ), + ).to.eventually.be.fulfilled; + }); + }); + }); + + describe('.moduleTransfer', () => { + describe('when calling from a random wallet', () => { + it('should revert', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + + await expect( + context.suite.complianceModule.moduleTransferAction(context.accounts.aliceWallet.address, context.accounts.anotherWallet.address, 10), + ).to.be.revertedWith('only bound compliance can call'); + }); + }); + + describe('when calling as the compliance', () => { + it('should do nothing', async () => { + const context = await loadFixture(deployTokenListingRestrictionsFullSuite); + + await expect( + context.suite.compliance.callModuleFunction( + new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + 'moduleTransferAction', + [context.accounts.aliceWallet.address, context.accounts.anotherWallet.address, 80], + ), + context.suite.complianceModule.address, + ), + ).to.eventually.be.fulfilled; + }); + }); + }); +}); From 72a7324b74b8a85af13f667befe08d941d4707b5 Mon Sep 17 00:00:00 2001 From: "ali.arbak" Date: Thu, 4 Apr 2024 13:28:33 +0300 Subject: [PATCH 13/55] Remove unused variable --- test/compliances/module-token-listing-restrictions.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/test/compliances/module-token-listing-restrictions.test.ts b/test/compliances/module-token-listing-restrictions.test.ts index bb49f827..5ba6049a 100644 --- a/test/compliances/module-token-listing-restrictions.test.ts +++ b/test/compliances/module-token-listing-restrictions.test.ts @@ -3,7 +3,6 @@ import { ethers, upgrades } from 'hardhat'; import { expect } from 'chai'; import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; -import { compliance } from '../../typechain-types/contracts'; async function deployTokenListingRestrictionsFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); From f8cd846d4ebb04cddaf7b9e1759e534f8f838a8c Mon Sep 17 00:00:00 2001 From: "ali.arbak" Date: Mon, 8 Apr 2024 16:07:26 +0300 Subject: [PATCH 14/55] Ignore transfer restrict checks when sender or recipient is null address --- .../modules/TransferRestrictModule.sol | 4 ++++ .../module-transfer-restrict.test.ts | 20 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/contracts/compliance/modular/modules/TransferRestrictModule.sol b/contracts/compliance/modular/modules/TransferRestrictModule.sol index 971eb92b..4d12864e 100644 --- a/contracts/compliance/modular/modules/TransferRestrictModule.sol +++ b/contracts/compliance/modular/modules/TransferRestrictModule.sol @@ -172,6 +172,10 @@ contract TransferRestrictModule is AbstractModuleUpgradeable { uint256 /*_value*/, address _compliance ) external view override returns (bool) { + if (_from == address(0) || _to == address(0)) { + return true; + } + if(_allowedUserAddresses[_compliance][_from]) { return true; } diff --git a/test/compliances/module-transfer-restrict.test.ts b/test/compliances/module-transfer-restrict.test.ts index 3a560dff..34e1937a 100644 --- a/test/compliances/module-transfer-restrict.test.ts +++ b/test/compliances/module-transfer-restrict.test.ts @@ -294,6 +294,26 @@ describe('Compliance Module: TransferRestrict', () => { }); }); + describe('when sender is the null address', () => { + it('should return true', async () => { + const context = await loadFixture(deployTransferRestrictFullSuite); + const to = context.accounts.anotherWallet.address; + const from = ethers.constants.AddressZero; + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + expect(result).to.be.true; + }); + }); + + describe('when recipient is the null address', () => { + it('should return true', async () => { + const context = await loadFixture(deployTransferRestrictFullSuite); + const to = ethers.constants.AddressZero; + const from = context.accounts.aliceWallet.address; + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + expect(result).to.be.true; + }); + }); + describe('when sender is allowed', () => { it('should return true', async () => { const context = await loadFixture(deployTransferRestrictFullSuite); From 37ec6e857cd40838ffc7ad1482430872252d42b7 Mon Sep 17 00:00:00 2001 From: joachimlebrun Date: Mon, 6 May 2024 16:25:46 +0800 Subject: [PATCH 15/55] :bookmark:() update license --- contracts/DVA/DVATransferManager.sol | 8 +++++++- contracts/DVA/IDVATransferManager.sol | 8 +++++++- contracts/DVD/DVDTransferManager.sol | 8 +++++++- .../modular/modules/ConditionalTransferModule.sol | 8 +++++++- .../compliance/modular/modules/CountryAllowModule.sol | 8 +++++++- .../compliance/modular/modules/CountryRestrictModule.sol | 8 +++++++- .../modular/modules/ExchangeMonthlyLimitsModule.sol | 8 +++++++- contracts/compliance/modular/modules/MaxBalanceModule.sol | 8 +++++++- .../compliance/modular/modules/SupplyLimitModule.sol | 8 +++++++- .../modular/modules/TimeExchangeLimitsModule.sol | 8 +++++++- .../modular/modules/TimeTransfersLimitsModule.sol | 8 +++++++- .../compliance/modular/modules/TransferFeesModule.sol | 8 +++++++- .../compliance/modular/modules/TransferRestrictModule.sol | 8 +++++++- 13 files changed, 91 insertions(+), 13 deletions(-) diff --git a/contracts/DVA/DVATransferManager.sol b/contracts/DVA/DVATransferManager.sol index 0cf98a88..6b0b4bed 100644 --- a/contracts/DVA/DVATransferManager.sol +++ b/contracts/DVA/DVATransferManager.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-3.0 +// This contract is also licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= @@ -44,7 +45,7 @@ * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * - * Copyright (C) 2023, Tokeny sàrl. + * Copyright (C) 2024, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,6 +59,11 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * This specific smart contract is also licensed under the Creative Commons + * Attribution-NonCommercial 4.0 International License (CC-BY-NC-4.0), + * which prohibits commercial use. For commercial inquiries, please contact + * Tokeny sàrl for licensing options. */ pragma solidity 0.8.17; diff --git a/contracts/DVA/IDVATransferManager.sol b/contracts/DVA/IDVATransferManager.sol index 4e9b26e8..52764a61 100644 --- a/contracts/DVA/IDVATransferManager.sol +++ b/contracts/DVA/IDVATransferManager.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-3.0 +// This contract is also licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= @@ -44,7 +45,7 @@ * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * - * Copyright (C) 2023, Tokeny sàrl. + * Copyright (C) 2024, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,6 +59,11 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * This specific smart contract is also licensed under the Creative Commons + * Attribution-NonCommercial 4.0 International License (CC-BY-NC-4.0), + * which prohibits commercial use. For commercial inquiries, please contact + * Tokeny sàrl for licensing options. */ pragma solidity 0.8.17; diff --git a/contracts/DVD/DVDTransferManager.sol b/contracts/DVD/DVDTransferManager.sol index cbc76331..ff493e23 100644 --- a/contracts/DVD/DVDTransferManager.sol +++ b/contracts/DVD/DVDTransferManager.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-3.0 +// This contract is also licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= @@ -44,7 +45,7 @@ * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * - * Copyright (C) 2023, Tokeny sàrl. + * Copyright (C) 2024, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,6 +59,11 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * This specific smart contract is also licensed under the Creative Commons + * Attribution-NonCommercial 4.0 International License (CC-BY-NC-4.0), + * which prohibits commercial use. For commercial inquiries, please contact + * Tokeny sàrl for licensing options. */ pragma solidity 0.8.17; diff --git a/contracts/compliance/modular/modules/ConditionalTransferModule.sol b/contracts/compliance/modular/modules/ConditionalTransferModule.sol index 46aee9a9..803dbe07 100644 --- a/contracts/compliance/modular/modules/ConditionalTransferModule.sol +++ b/contracts/compliance/modular/modules/ConditionalTransferModule.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-3.0 +// This contract is also licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= @@ -44,7 +45,7 @@ * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * - * Copyright (C) 2023, Tokeny sàrl. + * Copyright (C) 2024, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,6 +59,11 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * This specific smart contract is also licensed under the Creative Commons + * Attribution-NonCommercial 4.0 International License (CC-BY-NC-4.0), + * which prohibits commercial use. For commercial inquiries, please contact + * Tokeny sàrl for licensing options. */ pragma solidity 0.8.17; diff --git a/contracts/compliance/modular/modules/CountryAllowModule.sol b/contracts/compliance/modular/modules/CountryAllowModule.sol index 16e15819..29446e26 100644 --- a/contracts/compliance/modular/modules/CountryAllowModule.sol +++ b/contracts/compliance/modular/modules/CountryAllowModule.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-3.0 +// This contract is also licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= @@ -44,7 +45,7 @@ * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * - * Copyright (C) 2023, Tokeny sàrl. + * Copyright (C) 2024, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,6 +59,11 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * This specific smart contract is also licensed under the Creative Commons + * Attribution-NonCommercial 4.0 International License (CC-BY-NC-4.0), + * which prohibits commercial use. For commercial inquiries, please contact + * Tokeny sàrl for licensing options. */ pragma solidity 0.8.17; diff --git a/contracts/compliance/modular/modules/CountryRestrictModule.sol b/contracts/compliance/modular/modules/CountryRestrictModule.sol index cd07191a..edb789c4 100644 --- a/contracts/compliance/modular/modules/CountryRestrictModule.sol +++ b/contracts/compliance/modular/modules/CountryRestrictModule.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-3.0 +// This contract is also licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= @@ -44,7 +45,7 @@ * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * - * Copyright (C) 2023, Tokeny sàrl. + * Copyright (C) 2024, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,6 +59,11 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * This specific smart contract is also licensed under the Creative Commons + * Attribution-NonCommercial 4.0 International License (CC-BY-NC-4.0), + * which prohibits commercial use. For commercial inquiries, please contact + * Tokeny sàrl for licensing options. */ pragma solidity 0.8.17; diff --git a/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol b/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol index b1e530f0..ebd4f273 100644 --- a/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol +++ b/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-3.0 +// This contract is also licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= @@ -44,7 +45,7 @@ * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * - * Copyright (C) 2023, Tokeny sàrl. + * Copyright (C) 2024, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,6 +59,11 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * This specific smart contract is also licensed under the Creative Commons + * Attribution-NonCommercial 4.0 International License (CC-BY-NC-4.0), + * which prohibits commercial use. For commercial inquiries, please contact + * Tokeny sàrl for licensing options. */ pragma solidity 0.8.17; diff --git a/contracts/compliance/modular/modules/MaxBalanceModule.sol b/contracts/compliance/modular/modules/MaxBalanceModule.sol index 53751a47..fc5616a2 100644 --- a/contracts/compliance/modular/modules/MaxBalanceModule.sol +++ b/contracts/compliance/modular/modules/MaxBalanceModule.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-3.0 +// This contract is also licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= @@ -44,7 +45,7 @@ * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * - * Copyright (C) 2023, Tokeny sàrl. + * Copyright (C) 2024, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,6 +59,11 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * This specific smart contract is also licensed under the Creative Commons + * Attribution-NonCommercial 4.0 International License (CC-BY-NC-4.0), + * which prohibits commercial use. For commercial inquiries, please contact + * Tokeny sàrl for licensing options. */ pragma solidity 0.8.17; diff --git a/contracts/compliance/modular/modules/SupplyLimitModule.sol b/contracts/compliance/modular/modules/SupplyLimitModule.sol index b67f83ee..1b4e83cc 100644 --- a/contracts/compliance/modular/modules/SupplyLimitModule.sol +++ b/contracts/compliance/modular/modules/SupplyLimitModule.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-3.0 +// This contract is also licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= @@ -44,7 +45,7 @@ * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * - * Copyright (C) 2023, Tokeny sàrl. + * Copyright (C) 2024, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,6 +59,11 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * This specific smart contract is also licensed under the Creative Commons + * Attribution-NonCommercial 4.0 International License (CC-BY-NC-4.0), + * which prohibits commercial use. For commercial inquiries, please contact + * Tokeny sàrl for licensing options. */ pragma solidity ^0.8.17; diff --git a/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol b/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol index 9ae84e38..a591961b 100644 --- a/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol +++ b/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-3.0 +// This contract is also licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= @@ -44,7 +45,7 @@ * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * - * Copyright (C) 2023, Tokeny sàrl. + * Copyright (C) 2024, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,6 +59,11 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * This specific smart contract is also licensed under the Creative Commons + * Attribution-NonCommercial 4.0 International License (CC-BY-NC-4.0), + * which prohibits commercial use. For commercial inquiries, please contact + * Tokeny sàrl for licensing options. */ pragma solidity 0.8.17; diff --git a/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol b/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol index 265d6d5f..18ef472e 100644 --- a/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol +++ b/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-3.0 +// This contract is also licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= @@ -44,7 +45,7 @@ * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * - * Copyright (C) 2023, Tokeny sàrl. + * Copyright (C) 2024, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,6 +59,11 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * This specific smart contract is also licensed under the Creative Commons + * Attribution-NonCommercial 4.0 International License (CC-BY-NC-4.0), + * which prohibits commercial use. For commercial inquiries, please contact + * Tokeny sàrl for licensing options. */ pragma solidity 0.8.17; diff --git a/contracts/compliance/modular/modules/TransferFeesModule.sol b/contracts/compliance/modular/modules/TransferFeesModule.sol index 657035fe..b1584ade 100644 --- a/contracts/compliance/modular/modules/TransferFeesModule.sol +++ b/contracts/compliance/modular/modules/TransferFeesModule.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-3.0 +// This contract is also licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= @@ -44,7 +45,7 @@ * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * - * Copyright (C) 2023, Tokeny sàrl. + * Copyright (C) 2024, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,6 +59,11 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * This specific smart contract is also licensed under the Creative Commons + * Attribution-NonCommercial 4.0 International License (CC-BY-NC-4.0), + * which prohibits commercial use. For commercial inquiries, please contact + * Tokeny sàrl for licensing options. */ pragma solidity 0.8.17; diff --git a/contracts/compliance/modular/modules/TransferRestrictModule.sol b/contracts/compliance/modular/modules/TransferRestrictModule.sol index 971eb92b..22744f01 100644 --- a/contracts/compliance/modular/modules/TransferRestrictModule.sol +++ b/contracts/compliance/modular/modules/TransferRestrictModule.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-3.0 +// This contract is also licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= @@ -44,7 +45,7 @@ * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * - * Copyright (C) 2023, Tokeny sàrl. + * Copyright (C) 2024, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,6 +59,11 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * This specific smart contract is also licensed under the Creative Commons + * Attribution-NonCommercial 4.0 International License (CC-BY-NC-4.0), + * which prohibits commercial use. For commercial inquiries, please contact + * Tokeny sàrl for licensing options. */ pragma solidity ^0.8.17; From ca7deb42262f47b1ae75edbba35484929837a947 Mon Sep 17 00:00:00 2001 From: anonkey <6380129+anonkey@users.noreply.github.com> Date: Sun, 26 May 2024 20:42:27 +0200 Subject: [PATCH 16/55] =?UTF-8?q?=E2=99=BB(dependencies)=20upgrade=20ether?= =?UTF-8?q?s=206=20and=20other=20dependencies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/publish-prerelease.yml | 10 +- .github/workflows/publish-release.yml | 10 +- .github/workflows/push_checking.yml | 10 +- .husky/commit-msg | 3 - .husky/pre-commit | 4 - package-lock.json | 9606 +++++++++-------- package.json | 58 +- scripts/commit-msg.js | 31 + test/agentManager.test.ts | 247 +- test/agentRole.test.ts | 6 +- .../trex-implementation-authority.test.ts | 204 +- test/compliance.test.ts | 110 +- .../module-conditional-transfer.test.ts | 119 +- test/compliances/module-country-allow.test.ts | 119 +- .../module-country-restrict.test.ts | 158 +- .../module-exchange-monthly-limits.test.ts | 207 +- test/compliances/module-max-balance.test.ts | 172 +- test/compliances/module-supply-limit.test.ts | 63 +- .../module-time-exchange-limits.test.ts | 294 +- .../module-time-transfer-limits.test.ts | 184 +- test/compliances/module-transfer-fees.test.ts | 111 +- .../module-transfer-restrict.test.ts | 101 +- test/dva.test.ts | 156 +- test/dvd.test.ts | 106 +- test/factory.test.ts | 105 +- test/fixtures/deploy-full-suite.fixture.ts | 130 +- test/gateway.test.ts | 382 +- .../identity-registry-storage.test.ts | 47 +- test/registries/identity-registry.test.ts | 60 +- .../trusted-issuers-registry.test.ts | 34 +- test/token/token-information.test.ts | 20 +- test/token/token-recovery.test.ts | 20 +- test/token/token-transfer.test.ts | 56 +- 33 files changed, 6744 insertions(+), 6199 deletions(-) create mode 100644 scripts/commit-msg.js diff --git a/.github/workflows/publish-prerelease.yml b/.github/workflows/publish-prerelease.yml index c0f558c7..69f28f4d 100644 --- a/.github/workflows/publish-prerelease.yml +++ b/.github/workflows/publish-prerelease.yml @@ -6,13 +6,13 @@ on: jobs: build: - if: 'github.event.release.prerelease' + if: "github.event.release.prerelease" runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 - run: npm ci - run: npm run build - name: Run test coverage @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 registry-url: https://registry.npmjs.org/ - run: npm ci - run: npm run build @@ -47,9 +47,9 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 registry-url: https://npm.pkg.github.com/ - scope: '@tokenysolutions' + scope: "@tokenysolutions" - run: npm ci - run: npm run build - run: npm publish --tag beta diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index fe60abe1..8d511ac9 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -6,13 +6,13 @@ on: jobs: build: - if: '!github.event.release.prerelease' + if: "!github.event.release.prerelease" runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 - run: npm ci - run: npm run build - name: Run test coverage @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 registry-url: https://registry.npmjs.org/ - run: npm ci - run: npm run build @@ -47,9 +47,9 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 registry-url: https://npm.pkg.github.com/ - scope: '@tokenysolutions' + scope: "@tokenysolutions" - run: npm ci - run: npm run build - run: npm publish diff --git a/.github/workflows/push_checking.yml b/.github/workflows/push_checking.yml index f21a4134..9e66d322 100644 --- a/.github/workflows/push_checking.yml +++ b/.github/workflows/push_checking.yml @@ -6,11 +6,11 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [16.x] + node-version: [18.x] steps: - name: Checkout - uses: 'actions/checkout@master' + uses: "actions/checkout@master" - name: Set Node.js uses: actions/setup-node@v3 @@ -20,6 +20,8 @@ jobs: run: npm ci - name: Lint Solidity sources run: npm run lint:sol + - name: Build contracts + run: npm run build - name: Lint TypeScript sources run: npm run lint:ts @@ -28,11 +30,11 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [16.x] + node-version: [18.x] steps: - name: Checkout - uses: 'actions/checkout@master' + uses: "actions/checkout@master" - name: Set Node.js uses: actions/setup-node@v3 diff --git a/.husky/commit-msg b/.husky/commit-msg index 5059dcbc..e2674005 100644 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -1,4 +1 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" - node ./scripts/commit-msg.js $1 && npx --no-install commitlint --edit $1 diff --git a/.husky/pre-commit b/.husky/pre-commit index d24fdfc6..e69de29b 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +0,0 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" - -npx lint-staged diff --git a/package-lock.json b/package-lock.json index 281fef5c..c127e410 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,44 +1,51 @@ { "name": "@tokenysolutions/t-rex", - "version": "4.1.3", + "version": "4.1.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@tokenysolutions/t-rex", - "version": "4.1.3", + "version": "4.1.4", "license": "SEE LICENSE IN LICENSE.md", "devDependencies": { - "@commitlint/cli": "^17.6.1", - "@nomicfoundation/hardhat-toolbox": "^2.0.2", - "@nomiclabs/hardhat-solhint": "^3.0.1", - "@onchain-id/solidity": "^2.0.0", + "@commitlint/cli": "^19.3.0", + "@nomicfoundation/hardhat-toolbox": "^5.0.0", + "@nomiclabs/hardhat-solhint": "^3.1.0", + "@onchain-id/solidity": "^2.2.1", "@openzeppelin/contracts": "^4.8.3", "@openzeppelin/contracts-upgradeable": "^4.8.3", - "@openzeppelin/hardhat-upgrades": "^1.28.0", + "@openzeppelin/hardhat-upgrades": "^3.1.0", "@primitivefi/hardhat-dodoc": "^0.2.3", - "@typescript-eslint/eslint-plugin": "^6.7.4", - "@typescript-eslint/parser": "^6.7.4", + "@typescript-eslint/eslint-plugin": "^7.10.0", + "@typescript-eslint/parser": "^7.10.0", "@xyrusworx/hardhat-solidity-json": "^1.0.2", - "eslint": "^8.39.0", + "eslint": "^8.0.0", "eslint-config-airbnb-base": "^15.0.0", - "eslint-config-prettier": "^8.8.0", + "eslint-config-prettier": "^8.0.0", "eslint-import-resolver-typescript": "^3.6.1", - "eslint-plugin-chai-friendly": "^0.7.2", - "eslint-plugin-import": "^2.27.5", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-security": "^1.7.1", + "eslint-plugin-chai-friendly": "^0.8.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-security": "^3.0.0", "eth-gas-reporter": "^0.2.27", - "fs-extra": "^11.1.1", - "glob": "^10.2.6", - "hardhat": "^2.14.0", - "husky": "^8.0.3", - "lint-staged": "^13.2.2", - "prettier": "^2.8.8", - "prettier-plugin-solidity": "^1.1.3", - "solhint": "^3.4.1", - "solhint-plugin-prettier": "^0.0.5" - } + "fs-extra": "^11.2.0", + "glob": "^10.4.1", + "hardhat": "^2.22.4", + "husky": "^9.0.11", + "lint-staged": "^15.2.5", + "prettier": "^3.2.5", + "prettier-plugin-solidity": "^1.3.1", + "solhint": "^5.0.1", + "solhint-plugin-prettier": "^0.1.0" + } + }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", + "dev": true, + "peer": true }, "node_modules/@aws-crypto/sha256-js": { "version": "1.2.2", @@ -63,16 +70,16 @@ } }, "node_modules/@aws-sdk/types": { - "version": "3.523.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.523.0.tgz", - "integrity": "sha512-AqGIu4u+SxPiUuNBp2acCVcq80KDUFjxe6e3cMTvKWTzCbrVk1AXv0dAaJnCmdkWIha6zJDWxpIk/aL4EGhZ9A==", + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.577.0.tgz", + "integrity": "sha512-FT2JZES3wBKN/alfmhlo+3ZOq/XJ0C7QOZcDNrpKjB0kqYoKjhVKZ/Hx6ArR0czkKfHzBBEs6y40ebIHx2nSmA==", "dev": true, "dependencies": { - "@smithy/types": "^2.10.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/types/node_modules/tslib": { @@ -97,35 +104,37 @@ "dev": true }, "node_modules/@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz", + "integrity": "sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.14.5" + "@babel/highlight": "^7.24.6", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", - "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==", + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz", + "integrity": "sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.6.tgz", + "integrity": "sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/helper-validator-identifier": "^7.24.6", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -157,25 +166,19 @@ "node": ">=4" } }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "dependencies": { - "color-name": "1.1.3" + "engines": { + "node": ">=0.8.0" } }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "engines": { "node": ">=4" @@ -193,134 +196,47 @@ "node": ">=4" } }, - "node_modules/@chainsafe/as-sha256": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz", - "integrity": "sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg==", - "dev": true - }, - "node_modules/@chainsafe/persistent-merkle-tree": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz", - "integrity": "sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ==", - "dev": true, - "dependencies": { - "@chainsafe/as-sha256": "^0.3.1" - } - }, - "node_modules/@chainsafe/ssz": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.9.4.tgz", - "integrity": "sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ==", + "node_modules/@commitlint/cli": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.3.0.tgz", + "integrity": "sha512-LgYWOwuDR7BSTQ9OLZ12m7F/qhNY+NpAyPBgo4YNMkACE7lGuUnuQq1yi9hz1KA4+3VqpOYl8H1rY/LYK43v7g==", "dev": true, "dependencies": { - "@chainsafe/as-sha256": "^0.3.1", - "@chainsafe/persistent-merkle-tree": "^0.4.2", - "case": "^1.6.3" - } - }, - "node_modules/@commitlint/cli": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.7.2.tgz", - "integrity": "sha512-t3N7TZq7lOeqTOyEgfGcaltHqEJf7YDlPg75MldeVPPyz14jZq/+mbGF9tueDLFX8R6RwdymrN6D+U5XwZ8Iwg==", - "dev": true, - "dependencies": { - "@commitlint/format": "^17.4.4", - "@commitlint/lint": "^17.7.0", - "@commitlint/load": "^17.7.2", - "@commitlint/read": "^17.5.1", - "@commitlint/types": "^17.4.4", - "execa": "^5.0.0", - "lodash.isfunction": "^3.0.9", - "resolve-from": "5.0.0", - "resolve-global": "1.0.0", + "@commitlint/format": "^19.3.0", + "@commitlint/lint": "^19.2.2", + "@commitlint/load": "^19.2.0", + "@commitlint/read": "^19.2.1", + "@commitlint/types": "^19.0.3", + "execa": "^8.0.1", "yargs": "^17.0.0" }, "bin": { "commitlint": "cli.js" }, "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/cli/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@commitlint/cli/node_modules/yargs": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", - "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@commitlint/cli/node_modules/yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", - "dev": true, - "engines": { - "node": ">=12" + "node": ">=v18" } }, "node_modules/@commitlint/config-validator": { - "version": "17.6.7", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.6.7.tgz", - "integrity": "sha512-vJSncmnzwMvpr3lIcm0I8YVVDJTzyjy7NZAeXbTXy+MPUdAr9pKyyg7Tx/ebOQ9kqzE6O9WT6jg2164br5UdsQ==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.0.3.tgz", + "integrity": "sha512-2D3r4PKjoo59zBc2auodrSCaUnCSALCx54yveOFwwP/i2kfEAQrygwOleFWswLqK0UL/F9r07MFi5ev2ohyM4Q==", "dev": true, "dependencies": { - "@commitlint/types": "^17.4.4", + "@commitlint/types": "^19.0.3", "ajv": "^8.11.0" }, "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/config-validator/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "node": ">=v18" } }, - "node_modules/@commitlint/config-validator/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "node_modules/@commitlint/ensure": { - "version": "17.6.7", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-17.6.7.tgz", - "integrity": "sha512-mfDJOd1/O/eIb/h4qwXzUxkmskXDL9vNPnZ4AKYKiZALz4vHzwMxBSYtyL2mUIDeU9DRSpEUins8SeKtFkYHSw==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-19.0.3.tgz", + "integrity": "sha512-SZEpa/VvBLoT+EFZVb91YWbmaZ/9rPH3ESrINOl0HD2kMYsjvl0tF7nMHh0EpTcv4+gTtZBAe1y/SS6/OhfZzQ==", "dev": true, "dependencies": { - "@commitlint/types": "^17.4.4", + "@commitlint/types": "^19.0.3", "lodash.camelcase": "^4.3.0", "lodash.kebabcase": "^4.1.1", "lodash.snakecase": "^4.1.1", @@ -328,193 +244,184 @@ "lodash.upperfirst": "^4.3.1" }, "engines": { - "node": ">=v14" + "node": ">=v18" } }, "node_modules/@commitlint/execute-rule": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-17.4.0.tgz", - "integrity": "sha512-LIgYXuCSO5Gvtc0t9bebAMSwd68ewzmqLypqI2Kke1rqOqqDbMpYcYfoPfFlv9eyLIh4jocHWwCK5FS7z9icUA==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-19.0.0.tgz", + "integrity": "sha512-mtsdpY1qyWgAO/iOK0L6gSGeR7GFcdW7tIjcNFxcWkfLDF5qVbPHKuGATFqRMsxcO8OUKNj0+3WOHB7EHm4Jdw==", "dev": true, "engines": { - "node": ">=v14" + "node": ">=v18" } }, "node_modules/@commitlint/format": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-17.4.4.tgz", - "integrity": "sha512-+IS7vpC4Gd/x+uyQPTAt3hXs5NxnkqAZ3aqrHd5Bx/R9skyCAWusNlNbw3InDbAK6j166D9asQM8fnmYIa+CXQ==", + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-19.3.0.tgz", + "integrity": "sha512-luguk5/aF68HiF4H23ACAfk8qS8AHxl4LLN5oxPc24H+2+JRPsNr1OS3Gaea0CrH7PKhArBMKBz5RX9sA5NtTg==", "dev": true, "dependencies": { - "@commitlint/types": "^17.4.4", - "chalk": "^4.1.0" + "@commitlint/types": "^19.0.3", + "chalk": "^5.3.0" }, "engines": { - "node": ">=v14" + "node": ">=v18" } }, "node_modules/@commitlint/is-ignored": { - "version": "17.7.0", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-17.7.0.tgz", - "integrity": "sha512-043rA7m45tyEfW7Zv2vZHF++176MLHH9h70fnPoYlB1slKBeKl8BwNIlnPg4xBdRBVNPaCqvXxWswx2GR4c9Hw==", + "version": "19.2.2", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.2.2.tgz", + "integrity": "sha512-eNX54oXMVxncORywF4ZPFtJoBm3Tvp111tg1xf4zWXGfhBPKpfKG6R+G3G4v5CPlRROXpAOpQ3HMhA9n1Tck1g==", "dev": true, "dependencies": { - "@commitlint/types": "^17.4.4", - "semver": "7.5.4" + "@commitlint/types": "^19.0.3", + "semver": "^7.6.0" }, "engines": { - "node": ">=v14" + "node": ">=v18" } }, "node_modules/@commitlint/lint": { - "version": "17.7.0", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-17.7.0.tgz", - "integrity": "sha512-TCQihm7/uszA5z1Ux1vw+Nf3yHTgicus/+9HiUQk+kRSQawByxZNESeQoX9ujfVd3r4Sa+3fn0JQAguG4xvvbA==", + "version": "19.2.2", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.2.2.tgz", + "integrity": "sha512-xrzMmz4JqwGyKQKTpFzlN0dx0TAiT7Ran1fqEBgEmEj+PU98crOFtysJgY+QdeSagx6EDRigQIXJVnfrI0ratA==", "dev": true, "dependencies": { - "@commitlint/is-ignored": "^17.7.0", - "@commitlint/parse": "^17.7.0", - "@commitlint/rules": "^17.7.0", - "@commitlint/types": "^17.4.4" + "@commitlint/is-ignored": "^19.2.2", + "@commitlint/parse": "^19.0.3", + "@commitlint/rules": "^19.0.3", + "@commitlint/types": "^19.0.3" }, "engines": { - "node": ">=v14" + "node": ">=v18" } }, "node_modules/@commitlint/load": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-17.7.2.tgz", - "integrity": "sha512-XA7WTnsjHZ4YH6ZYsrnxgLdXzriwMMq+utZUET6spbOEEIPBCDLdOQXS26P+v3TTO4hUHOEhzUquaBv3jbBixw==", - "dev": true, - "dependencies": { - "@commitlint/config-validator": "^17.6.7", - "@commitlint/execute-rule": "^17.4.0", - "@commitlint/resolve-extends": "^17.6.7", - "@commitlint/types": "^17.4.4", - "@types/node": "20.5.1", - "chalk": "^4.1.0", - "cosmiconfig": "^8.0.0", - "cosmiconfig-typescript-loader": "^4.0.0", + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-19.2.0.tgz", + "integrity": "sha512-XvxxLJTKqZojCxaBQ7u92qQLFMMZc4+p9qrIq/9kJDy8DOrEa7P1yx7Tjdc2u2JxIalqT4KOGraVgCE7eCYJyQ==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^19.0.3", + "@commitlint/execute-rule": "^19.0.0", + "@commitlint/resolve-extends": "^19.1.0", + "@commitlint/types": "^19.0.3", + "chalk": "^5.3.0", + "cosmiconfig": "^9.0.0", + "cosmiconfig-typescript-loader": "^5.0.0", "lodash.isplainobject": "^4.0.6", "lodash.merge": "^4.6.2", - "lodash.uniq": "^4.5.0", - "resolve-from": "^5.0.0", - "ts-node": "^10.8.1", - "typescript": "^4.6.4 || ^5.0.0" + "lodash.uniq": "^4.5.0" }, "engines": { - "node": ">=v14" + "node": ">=v18" } }, - "node_modules/@commitlint/load/node_modules/@types/node": { - "version": "20.5.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.1.tgz", - "integrity": "sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg==", - "dev": true - }, "node_modules/@commitlint/message": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-17.4.2.tgz", - "integrity": "sha512-3XMNbzB+3bhKA1hSAWPCQA3lNxR4zaeQAQcHj0Hx5sVdO6ryXtgUBGGv+1ZCLMgAPRixuc6en+iNAzZ4NzAa8Q==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-19.0.0.tgz", + "integrity": "sha512-c9czf6lU+9oF9gVVa2lmKaOARJvt4soRsVmbR7Njwp9FpbBgste5i7l/2l5o8MmbwGh4yE1snfnsy2qyA2r/Fw==", "dev": true, "engines": { - "node": ">=v14" + "node": ">=v18" } }, "node_modules/@commitlint/parse": { - "version": "17.7.0", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-17.7.0.tgz", - "integrity": "sha512-dIvFNUMCUHqq5Abv80mIEjLVfw8QNuA4DS7OWip4pcK/3h5wggmjVnlwGCDvDChkw2TjK1K6O+tAEV78oxjxag==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-19.0.3.tgz", + "integrity": "sha512-Il+tNyOb8VDxN3P6XoBBwWJtKKGzHlitEuXA5BP6ir/3loWlsSqDr5aecl6hZcC/spjq4pHqNh0qPlfeWu38QA==", "dev": true, "dependencies": { - "@commitlint/types": "^17.4.4", - "conventional-changelog-angular": "^6.0.0", - "conventional-commits-parser": "^4.0.0" + "@commitlint/types": "^19.0.3", + "conventional-changelog-angular": "^7.0.0", + "conventional-commits-parser": "^5.0.0" }, "engines": { - "node": ">=v14" + "node": ">=v18" } }, "node_modules/@commitlint/read": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-17.5.1.tgz", - "integrity": "sha512-7IhfvEvB//p9aYW09YVclHbdf1u7g7QhxeYW9ZHSO8Huzp8Rz7m05aCO1mFG7G8M+7yfFnXB5xOmG18brqQIBg==", + "version": "19.2.1", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-19.2.1.tgz", + "integrity": "sha512-qETc4+PL0EUv7Q36lJbPG+NJiBOGg7SSC7B5BsPWOmei+Dyif80ErfWQ0qXoW9oCh7GTpTNRoaVhiI8RbhuaNw==", "dev": true, "dependencies": { - "@commitlint/top-level": "^17.4.0", - "@commitlint/types": "^17.4.4", - "fs-extra": "^11.0.0", - "git-raw-commits": "^2.0.11", - "minimist": "^1.2.6" + "@commitlint/top-level": "^19.0.0", + "@commitlint/types": "^19.0.3", + "execa": "^8.0.1", + "git-raw-commits": "^4.0.0", + "minimist": "^1.2.8" }, "engines": { - "node": ">=v14" + "node": ">=v18" } }, "node_modules/@commitlint/resolve-extends": { - "version": "17.6.7", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.6.7.tgz", - "integrity": "sha512-PfeoAwLHtbOaC9bGn/FADN156CqkFz6ZKiVDMjuC2N5N0740Ke56rKU7Wxdwya8R8xzLK9vZzHgNbuGhaOVKIg==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.1.0.tgz", + "integrity": "sha512-z2riI+8G3CET5CPgXJPlzftH+RiWYLMYv4C9tSLdLXdr6pBNimSKukYP9MS27ejmscqCTVA4almdLh0ODD2KYg==", "dev": true, "dependencies": { - "@commitlint/config-validator": "^17.6.7", - "@commitlint/types": "^17.4.4", - "import-fresh": "^3.0.0", + "@commitlint/config-validator": "^19.0.3", + "@commitlint/types": "^19.0.3", + "global-directory": "^4.0.1", + "import-meta-resolve": "^4.0.0", "lodash.mergewith": "^4.6.2", - "resolve-from": "^5.0.0", - "resolve-global": "^1.0.0" + "resolve-from": "^5.0.0" }, "engines": { - "node": ">=v14" + "node": ">=v18" } }, "node_modules/@commitlint/rules": { - "version": "17.7.0", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-17.7.0.tgz", - "integrity": "sha512-J3qTh0+ilUE5folSaoK91ByOb8XeQjiGcdIdiB/8UT1/Rd1itKo0ju/eQVGyFzgTMYt8HrDJnGTmNWwcMR1rmA==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.0.3.tgz", + "integrity": "sha512-TspKb9VB6svklxNCKKwxhELn7qhtY1rFF8ls58DcFd0F97XoG07xugPjjbVnLqmMkRjZDbDIwBKt9bddOfLaPw==", "dev": true, "dependencies": { - "@commitlint/ensure": "^17.6.7", - "@commitlint/message": "^17.4.2", - "@commitlint/to-lines": "^17.4.0", - "@commitlint/types": "^17.4.4", - "execa": "^5.0.0" + "@commitlint/ensure": "^19.0.3", + "@commitlint/message": "^19.0.0", + "@commitlint/to-lines": "^19.0.0", + "@commitlint/types": "^19.0.3", + "execa": "^8.0.1" }, "engines": { - "node": ">=v14" + "node": ">=v18" } }, "node_modules/@commitlint/to-lines": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-17.4.0.tgz", - "integrity": "sha512-LcIy/6ZZolsfwDUWfN1mJ+co09soSuNASfKEU5sCmgFCvX5iHwRYLiIuoqXzOVDYOy7E7IcHilr/KS0e5T+0Hg==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-19.0.0.tgz", + "integrity": "sha512-vkxWo+VQU5wFhiP9Ub9Sre0FYe019JxFikrALVoD5UGa8/t3yOJEpEhxC5xKiENKKhUkTpEItMTRAjHw2SCpZw==", "dev": true, "engines": { - "node": ">=v14" + "node": ">=v18" } }, "node_modules/@commitlint/top-level": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-17.4.0.tgz", - "integrity": "sha512-/1loE/g+dTTQgHnjoCy0AexKAEFyHsR2zRB4NWrZ6lZSMIxAhBJnmCqwao7b4H8888PsfoTBCLBYIw8vGnej8g==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-19.0.0.tgz", + "integrity": "sha512-KKjShd6u1aMGNkCkaX4aG1jOGdn7f8ZI8TR1VEuNqUOjWTOdcDSsmglinglJ18JTjuBX5I1PtjrhQCRcixRVFQ==", "dev": true, "dependencies": { - "find-up": "^5.0.0" + "find-up": "^7.0.0" }, "engines": { - "node": ">=v14" + "node": ">=v18" } }, "node_modules/@commitlint/types": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-17.4.4.tgz", - "integrity": "sha512-amRN8tRLYOsxRr6mTnGGGvB5EmW/4DDjLMgiwK3CCVEmN6Sr/6xePGEpWaspKkckILuUORCwe6VfDBw6uj4axQ==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-19.0.3.tgz", + "integrity": "sha512-tpyc+7i6bPG9mvaBbtKUeghfyZSDgWquIDfMgqYtTbmZ9Y9VzEm2je9EYcQ0aoz5o7NvGS+rcDec93yO08MHYA==", "dev": true, "dependencies": { - "chalk": "^4.1.0" + "@types/conventional-commits-parser": "^5.0.0", + "chalk": "^5.3.0" }, "engines": { - "node": ">=v14" + "node": ">=v18" } }, "node_modules/@cspotcode/source-map-support": { @@ -522,6 +429,7 @@ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, + "peer": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -545,23 +453,23 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", - "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.1", + "espree": "^9.6.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -576,24 +484,38 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "dependencies": { - "argparse": "^2.0.1" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -607,14 +529,110 @@ } }, "node_modules/@eslint/js": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.39.0.tgz", - "integrity": "sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@ethereumjs/rlp": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", + "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", + "dev": true, + "peer": true, + "bin": { + "rlp": "bin/rlp" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@ethereumjs/util": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", + "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==", + "dev": true, + "peer": true, + "dependencies": { + "@ethereumjs/rlp": "^4.0.1", + "ethereum-cryptography": "^2.0.0", + "micro-ftch": "^0.3.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@ethereumjs/util/node_modules/@noble/curves": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", + "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", + "dev": true, + "peer": true, + "dependencies": { + "@noble/hashes": "1.3.3" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/@scure/bip32": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.3.tgz", + "integrity": "sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==", + "dev": true, + "peer": true, + "dependencies": { + "@noble/curves": "~1.3.0", + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/@scure/bip39": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.2.tgz", + "integrity": "sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==", + "dev": true, + "peer": true, + "dependencies": { + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/ethereum-cryptography": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz", + "integrity": "sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==", + "dev": true, + "peer": true, + "dependencies": { + "@noble/curves": "1.3.0", + "@noble/hashes": "1.3.3", + "@scure/bip32": "1.3.3", + "@scure/bip39": "1.2.2" + } + }, "node_modules/@ethersproject/abi": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", @@ -773,12 +791,6 @@ "bn.js": "^5.2.1" } }, - "node_modules/@ethersproject/bignumber/node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "dev": true - }, "node_modules/@ethersproject/bytes": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", @@ -933,6 +945,12 @@ "scrypt-js": "3.0.1" } }, + "node_modules/@ethersproject/json-wallets/node_modules/aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", + "dev": true + }, "node_modules/@ethersproject/keccak256": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", @@ -953,12 +971,6 @@ "js-sha3": "0.8.0" } }, - "node_modules/@ethersproject/keccak256/node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "dev": true - }, "node_modules/@ethersproject/logger": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", @@ -1071,12 +1083,6 @@ "ws": "7.4.6" } }, - "node_modules/@ethersproject/providers/node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "dev": true - }, "node_modules/@ethersproject/providers/node_modules/ws": { "version": "7.4.6", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", @@ -1183,12 +1189,6 @@ "hash.js": "1.1.7" } }, - "node_modules/@ethersproject/signing-key/node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "dev": true - }, "node_modules/@ethersproject/solidity": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", @@ -1361,20 +1361,39 @@ "@ethersproject/strings": "^5.7.0" } }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1401,9 +1420,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, "node_modules/@isaacs/cliui": { @@ -1435,18 +1454,6 @@ "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/@isaacs/cliui/node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -1503,25 +1510,28 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "peer": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true, + "peer": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, + "peer": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -1543,6 +1553,21 @@ "node": ">=12.0.0" } }, + "node_modules/@metamask/eth-sig-util/node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@metamask/eth-sig-util/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, "node_modules/@metamask/eth-sig-util/node_modules/ethereum-cryptography": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", @@ -1581,11 +1606,31 @@ "rlp": "^2.2.3" } }, - "node_modules/@metamask/eth-sig-util/node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "dev": true + "node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dev": true, + "peer": true, + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } }, "node_modules/@noble/hashes": { "version": "1.2.0", @@ -1646,228 +1691,132 @@ "node": ">= 8" } }, - "node_modules/@nomicfoundation/ethereumjs-block": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.1.tgz", - "integrity": "sha512-u1Yioemi6Ckj3xspygu/SfFvm8vZEO8/Yx5a1QLzi6nVU0jz3Pg2OmHKJ5w+D9Ogk1vhwRiqEBAqcb0GVhCyHw==", + "node_modules/@nomicfoundation/edr": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.3.8.tgz", + "integrity": "sha512-u2UJ5QpznSHVkZRh6ePWoeVb6kmPrrqh08gCnZ9FHlJV9CITqlrTQHJkacd+INH31jx88pTAJnxePE4XAiH5qg==", "dev": true, "dependencies": { - "@nomicfoundation/ethereumjs-common": "4.0.1", - "@nomicfoundation/ethereumjs-rlp": "5.0.1", - "@nomicfoundation/ethereumjs-trie": "6.0.1", - "@nomicfoundation/ethereumjs-tx": "5.0.1", - "@nomicfoundation/ethereumjs-util": "9.0.1", - "ethereum-cryptography": "0.1.3", - "ethers": "^5.7.1" + "@nomicfoundation/edr-darwin-arm64": "0.3.8", + "@nomicfoundation/edr-darwin-x64": "0.3.8", + "@nomicfoundation/edr-linux-arm64-gnu": "0.3.8", + "@nomicfoundation/edr-linux-arm64-musl": "0.3.8", + "@nomicfoundation/edr-linux-x64-gnu": "0.3.8", + "@nomicfoundation/edr-linux-x64-musl": "0.3.8", + "@nomicfoundation/edr-win32-x64-msvc": "0.3.8" }, "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-block/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-blockchain": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.1.tgz", - "integrity": "sha512-NhzndlGg829XXbqJEYrF1VeZhAwSPgsK/OB7TVrdzft3y918hW5KNd7gIZ85sn6peDZOdjBsAXIpXZ38oBYE5A==", + "node_modules/@nomicfoundation/edr-darwin-arm64": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.3.8.tgz", + "integrity": "sha512-eB0leCexS8sQEmfyD72cdvLj9djkBzQGP4wSQw6SNf2I4Sw4Cnzb3d45caG2FqFFjbvfqL0t+badUUIceqQuMw==", "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-block": "5.0.1", - "@nomicfoundation/ethereumjs-common": "4.0.1", - "@nomicfoundation/ethereumjs-ethash": "3.0.1", - "@nomicfoundation/ethereumjs-rlp": "5.0.1", - "@nomicfoundation/ethereumjs-trie": "6.0.1", - "@nomicfoundation/ethereumjs-tx": "5.0.1", - "@nomicfoundation/ethereumjs-util": "9.0.1", - "abstract-level": "^1.0.3", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "level": "^8.0.0", - "lru-cache": "^5.1.1", - "memory-level": "^1.0.0" - }, "engines": { - "node": ">=14" + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-blockchain/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "node_modules/@nomicfoundation/edr-darwin-x64": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.3.8.tgz", + "integrity": "sha512-JksVCS1N5ClwVF14EvO25HCQ+Laljh/KRfHERMVAC9ZwPbTuAd/9BtKvToCBi29uCHWqsXMI4lxCApYQv2nznw==", "dev": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" + "engines": { + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-blockchain/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.3.8.tgz", + "integrity": "sha512-raCE+fOeNXhVBLUo87cgsHSGvYYRB6arih4eG6B9KGACWK5Veebtm9xtKeiD8YCsdUlUfat6F7ibpeNm91fpsA==", "dev": true, - "dependencies": { - "yallist": "^3.0.2" + "engines": { + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-blockchain/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/@nomicfoundation/ethereumjs-common": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.1.tgz", - "integrity": "sha512-OBErlkfp54GpeiE06brBW/TTbtbuBJV5YI5Nz/aB2evTDo+KawyEzPjBlSr84z/8MFfj8wS2wxzQX1o32cev5g==", + "node_modules/@nomicfoundation/edr-linux-arm64-musl": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.3.8.tgz", + "integrity": "sha512-PwiDp4wBZWMCIy29eKkv8moTKRrpiSDlrc+GQMSZLhOAm8T33JKKXPwD/2EbplbhCygJDGXZdtEKl9x9PaH66A==", "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-util": "9.0.1", - "crc-32": "^1.2.0" + "engines": { + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-ethash": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.1.tgz", - "integrity": "sha512-KDjGIB5igzWOp8Ik5I6QiRH5DH+XgILlplsHR7TEuWANZA759G6krQ6o8bvj+tRUz08YygMQu/sGd9mJ1DYT8w==", + "node_modules/@nomicfoundation/edr-linux-x64-gnu": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.3.8.tgz", + "integrity": "sha512-6AcvA/XKoipGap5jJmQ9Y6yT7Uf39D9lu2hBcDCXnXbMcXaDGw4mn1/L4R63D+9VGZyu1PqlcJixCUZlGGIWlg==", "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-block": "5.0.1", - "@nomicfoundation/ethereumjs-rlp": "5.0.1", - "@nomicfoundation/ethereumjs-util": "9.0.1", - "abstract-level": "^1.0.3", - "bigint-crypto-utils": "^3.0.23", - "ethereum-cryptography": "0.1.3" - }, "engines": { - "node": ">=14" + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-ethash/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "node_modules/@nomicfoundation/edr-linux-x64-musl": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.3.8.tgz", + "integrity": "sha512-cxb0sEmZjlwhYWO28sPsV64VDx31ekskhC1IsDXU1p9ntjHSJRmW4KEIqJ2O3QwJap/kLKfMS6TckvY10gjc6w==", "dev": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" + "engines": { + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-evm": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.1.tgz", - "integrity": "sha512-oL8vJcnk0Bx/onl+TgQOQ1t/534GKFaEG17fZmwtPFeH8S5soiBYPCLUrvANOl4sCp9elYxIMzIiTtMtNNN8EQ==", + "node_modules/@nomicfoundation/edr-win32-x64-msvc": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.3.8.tgz", + "integrity": "sha512-yVuVPqRRNLZk7TbBMkKw7lzCvI8XO8fNTPTYxymGadjr9rEGRuNTU1yBXjfJ59I1jJU/X2TSkRk1OFX0P5tpZQ==", "dev": true, - "dependencies": { - "@ethersproject/providers": "^5.7.1", - "@nomicfoundation/ethereumjs-common": "4.0.1", - "@nomicfoundation/ethereumjs-tx": "5.0.1", - "@nomicfoundation/ethereumjs-util": "9.0.1", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "mcl-wasm": "^0.7.1", - "rustbn.js": "~0.2.0" - }, "engines": { - "node": ">=14" + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-evm/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "node_modules/@nomicfoundation/ethereumjs-common": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz", + "integrity": "sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==", "dev": true, "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" + "@nomicfoundation/ethereumjs-util": "9.0.4" } }, "node_modules/@nomicfoundation/ethereumjs-rlp": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.1.tgz", - "integrity": "sha512-xtxrMGa8kP4zF5ApBQBtjlSbN5E2HI8m8FYgVSYAnO6ssUoY5pVPGy2H8+xdf/bmMa22Ce8nWMH3aEW8CcqMeQ==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz", + "integrity": "sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==", "dev": true, "bin": { - "rlp": "bin/rlp" + "rlp": "bin/rlp.cjs" }, "engines": { - "node": ">=14" + "node": ">=18" } }, - "node_modules/@nomicfoundation/ethereumjs-statemanager": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.1.tgz", - "integrity": "sha512-B5ApMOnlruVOR7gisBaYwFX+L/AP7i/2oAahatssjPIBVDF6wTX1K7Qpa39E/nzsH8iYuL3krkYeUFIdO3EMUQ==", + "node_modules/@nomicfoundation/ethereumjs-tx": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz", + "integrity": "sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==", "dev": true, "dependencies": { - "@nomicfoundation/ethereumjs-common": "4.0.1", - "@nomicfoundation/ethereumjs-rlp": "5.0.1", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "ethers": "^5.7.1", - "js-sdsl": "^4.1.4" + "@nomicfoundation/ethereumjs-common": "4.0.4", + "@nomicfoundation/ethereumjs-rlp": "5.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "c-kzg": "^2.1.2" + }, + "peerDependenciesMeta": { + "c-kzg": { + "optional": true + } } }, - "node_modules/@nomicfoundation/ethereumjs-statemanager/node_modules/ethereum-cryptography": { + "node_modules/@nomicfoundation/ethereumjs-tx/node_modules/ethereum-cryptography": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", @@ -1890,23 +1839,28 @@ "setimmediate": "^1.0.5" } }, - "node_modules/@nomicfoundation/ethereumjs-trie": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.1.tgz", - "integrity": "sha512-A64It/IMpDVODzCgxDgAAla8jNjNtsoQZIzZUfIV5AY6Coi4nvn7+VReBn5itlxMiL2yaTlQr9TRWp3CSI6VoA==", + "node_modules/@nomicfoundation/ethereumjs-util": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz", + "integrity": "sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==", "dev": true, "dependencies": { - "@nomicfoundation/ethereumjs-rlp": "5.0.1", - "@nomicfoundation/ethereumjs-util": "9.0.1", - "@types/readable-stream": "^2.3.13", - "ethereum-cryptography": "0.1.3", - "readable-stream": "^3.6.0" + "@nomicfoundation/ethereumjs-rlp": "5.0.4", + "ethereum-cryptography": "0.1.3" }, "engines": { - "node": ">=14" + "node": ">=18" + }, + "peerDependencies": { + "c-kzg": "^2.1.2" + }, + "peerDependenciesMeta": { + "c-kzg": { + "optional": true + } } }, - "node_modules/@nomicfoundation/ethereumjs-trie/node_modules/ethereum-cryptography": { + "node_modules/@nomicfoundation/ethereumjs-util/node_modules/ethereum-cryptography": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", @@ -1929,187 +1883,158 @@ "setimmediate": "^1.0.5" } }, - "node_modules/@nomicfoundation/ethereumjs-trie/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/@nomicfoundation/hardhat-chai-matchers": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.6.tgz", + "integrity": "sha512-Te1Uyo9oJcTCF0Jy9dztaLpshmlpjLf2yPtWXlXuLjMt3RRSmJLm/+rKVTW6gfadAEs12U/it6D0ZRnnRGiICQ==", "dev": true, + "peer": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "@types/chai-as-promised": "^7.1.3", + "chai-as-promised": "^7.1.1", + "deep-eql": "^4.0.1", + "ordinal": "^1.0.3" }, - "engines": { - "node": ">= 6" + "peerDependencies": { + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "chai": "^4.2.0", + "ethers": "^6.1.0", + "hardhat": "^2.9.4" } }, - "node_modules/@nomicfoundation/ethereumjs-tx": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.1.tgz", - "integrity": "sha512-0HwxUF2u2hrsIM1fsasjXvlbDOq1ZHFV2dd1yGq8CA+MEYhaxZr8OTScpVkkxqMwBcc5y83FyPl0J9MZn3kY0w==", + "node_modules/@nomicfoundation/hardhat-ethers": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.6.tgz", + "integrity": "sha512-/xzkFQAaHQhmIAYOQmvHBPwL+NkwLzT9gRZBsgWUYeV+E6pzXsBQsHfRYbAZ3XEYare+T7S+5Tg/1KDJgepSkA==", "dev": true, + "peer": true, "dependencies": { - "@chainsafe/ssz": "^0.9.2", - "@ethersproject/providers": "^5.7.2", - "@nomicfoundation/ethereumjs-common": "4.0.1", - "@nomicfoundation/ethereumjs-rlp": "5.0.1", - "@nomicfoundation/ethereumjs-util": "9.0.1", - "ethereum-cryptography": "0.1.3" + "debug": "^4.1.1", + "lodash.isequal": "^4.5.0" }, - "engines": { - "node": ">=14" + "peerDependencies": { + "ethers": "^6.1.0", + "hardhat": "^2.0.0" } }, - "node_modules/@nomicfoundation/ethereumjs-tx/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "node_modules/@nomicfoundation/hardhat-ignition": { + "version": "0.15.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ignition/-/hardhat-ignition-0.15.4.tgz", + "integrity": "sha512-x1lhLN9ZRSJ9eiNY9AoinMdeQeU4LDQSQOIw90W9DiZIG/g9YUzcTEIY58QTi2TZOF8YFiF6vJqLSePCpi8R1Q==", "dev": true, + "peer": true, "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" + "@nomicfoundation/ignition-core": "^0.15.4", + "@nomicfoundation/ignition-ui": "^0.15.4", + "chalk": "^4.0.0", + "debug": "^4.3.2", + "fs-extra": "^10.0.0", + "prompts": "^2.4.2" + }, + "peerDependencies": { + "@nomicfoundation/hardhat-verify": "^2.0.1", + "hardhat": "^2.18.0" } }, - "node_modules/@nomicfoundation/ethereumjs-util": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.1.tgz", - "integrity": "sha512-TwbhOWQ8QoSCFhV/DDfSmyfFIHjPjFBj957219+V3jTZYZ2rf9PmDtNOeZWAE3p3vlp8xb02XGpd0v6nTUPbsA==", + "node_modules/@nomicfoundation/hardhat-ignition-ethers": { + "version": "0.15.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ignition-ethers/-/hardhat-ignition-ethers-0.15.4.tgz", + "integrity": "sha512-vY30V4b788GSziW/nOd0L/4IPw6mwpluahLs4+gPUUKWaHHGMA8OIeHaYpRRljM1i0M/Kg1yIozrDM/aeRebkg==", + "dev": true, + "peer": true, + "peerDependencies": { + "@nomicfoundation/hardhat-ethers": "^3.0.4", + "@nomicfoundation/hardhat-ignition": "^0.15.4", + "@nomicfoundation/ignition-core": "^0.15.4", + "ethers": "^6.7.0", + "hardhat": "^2.18.0" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "peer": true, "dependencies": { - "@chainsafe/ssz": "^0.10.0", - "@nomicfoundation/ethereumjs-rlp": "5.0.1", - "ethereum-cryptography": "0.1.3" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=14" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@nomicfoundation/ethereumjs-util/node_modules/@chainsafe/persistent-merkle-tree": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.5.0.tgz", - "integrity": "sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw==", + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "peer": true, "dependencies": { - "@chainsafe/as-sha256": "^0.3.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@nomicfoundation/ethereumjs-util/node_modules/@chainsafe/ssz": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.10.2.tgz", - "integrity": "sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg==", + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "peer": true, "dependencies": { - "@chainsafe/as-sha256": "^0.3.1", - "@chainsafe/persistent-merkle-tree": "^0.5.0" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@nomicfoundation/ethereumjs-util/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, + "peer": true + }, + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "peer": true, "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/@nomicfoundation/ethereumjs-vm": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.1.tgz", - "integrity": "sha512-rArhyn0jPsS/D+ApFsz3yVJMQ29+pVzNZ0VJgkzAZ+7FqXSRtThl1C1prhmlVr3YNUlfpZ69Ak+RUT4g7VoOuQ==", - "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-block": "5.0.1", - "@nomicfoundation/ethereumjs-blockchain": "7.0.1", - "@nomicfoundation/ethereumjs-common": "4.0.1", - "@nomicfoundation/ethereumjs-evm": "2.0.1", - "@nomicfoundation/ethereumjs-rlp": "5.0.1", - "@nomicfoundation/ethereumjs-statemanager": "2.0.1", - "@nomicfoundation/ethereumjs-trie": "6.0.1", - "@nomicfoundation/ethereumjs-tx": "5.0.1", - "@nomicfoundation/ethereumjs-util": "9.0.1", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "mcl-wasm": "^0.7.1", - "rustbn.js": "~0.2.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-vm/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" + "node": ">=12" } }, - "node_modules/@nomicfoundation/hardhat-chai-matchers": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-1.0.6.tgz", - "integrity": "sha512-f5ZMNmabZeZegEfuxn/0kW+mm7+yV7VNDxLpMOMGXWFJ2l/Ct3QShujzDRF9cOkK9Ui/hbDeOWGZqyQALDXVCQ==", + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "peer": true, "dependencies": { - "@ethersproject/abi": "^5.1.2", - "@types/chai-as-promised": "^7.1.3", - "chai-as-promised": "^7.1.1", - "deep-eql": "^4.0.1", - "ordinal": "^1.0.3" + "has-flag": "^4.0.0" }, - "peerDependencies": { - "@nomiclabs/hardhat-ethers": "^2.0.0", - "chai": "^4.2.0", - "ethers": "^5.0.0", - "hardhat": "^2.9.4" + "engines": { + "node": ">=8" } }, "node_modules/@nomicfoundation/hardhat-network-helpers": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.9.tgz", - "integrity": "sha512-OXWCv0cHpwLUO2u7bFxBna6dQtCC2Gg/aN/KtJLO7gmuuA28vgmVKYFRCDUqrbjujzgfwQ2aKyZ9Y3vSmDqS7Q==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.10.tgz", + "integrity": "sha512-R35/BMBlx7tWN5V6d/8/19QCwEmIdbnA4ZrsuXgvs8i2qFx5i7h6mH5pBS4Pwi4WigLH+upl6faYusrNPuzMrQ==", "dev": true, "peer": true, "dependencies": { @@ -2120,32 +2045,200 @@ } }, "node_modules/@nomicfoundation/hardhat-toolbox": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-2.0.2.tgz", - "integrity": "sha512-vnN1AzxbvpSx9pfdRHbUzTRIXpMLPXnUlkW855VaDk6N1pwRaQ2gNzEmFAABk4lWf11E00PKwFd/q27HuwYrYg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-5.0.0.tgz", + "integrity": "sha512-FnUtUC5PsakCbwiVNsqlXVIWG5JIb5CEZoSXbJUsEBun22Bivx2jhF1/q9iQbzuaGpJKFQyOhemPB2+XlEE6pQ==", "dev": true, "peerDependencies": { - "@ethersproject/abi": "^5.4.7", - "@ethersproject/providers": "^5.4.7", - "@nomicfoundation/hardhat-chai-matchers": "^1.0.0", + "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@nomicfoundation/hardhat-ignition-ethers": "^0.15.0", "@nomicfoundation/hardhat-network-helpers": "^1.0.0", - "@nomiclabs/hardhat-ethers": "^2.0.0", - "@nomiclabs/hardhat-etherscan": "^3.0.0", - "@typechain/ethers-v5": "^10.1.0", - "@typechain/hardhat": "^6.1.2", + "@nomicfoundation/hardhat-verify": "^2.0.0", + "@typechain/ethers-v6": "^0.5.0", + "@typechain/hardhat": "^9.0.0", "@types/chai": "^4.2.0", "@types/mocha": ">=9.1.0", - "@types/node": ">=12.0.0", + "@types/node": ">=18.0.0", "chai": "^4.2.0", - "ethers": "^5.4.7", + "ethers": "^6.4.0", "hardhat": "^2.11.0", "hardhat-gas-reporter": "^1.0.8", "solidity-coverage": "^0.8.1", "ts-node": ">=8.0.0", - "typechain": "^8.1.0", + "typechain": "^8.3.0", "typescript": ">=4.5.0" } }, + "node_modules/@nomicfoundation/hardhat-verify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.7.tgz", + "integrity": "sha512-jiYHBX+K6bBN0YhwFHQ5SWWc3dQZliM3pdgpH33C7tnsVACsX1ubZn6gZ9hfwlzG0tyjFM72XQhpaXQ56cE6Ew==", + "dev": true, + "peer": true, + "dependencies": { + "@ethersproject/abi": "^5.1.2", + "@ethersproject/address": "^5.0.2", + "cbor": "^8.1.0", + "chalk": "^2.4.2", + "debug": "^4.1.1", + "lodash.clonedeep": "^4.5.0", + "semver": "^6.3.0", + "table": "^6.8.0", + "undici": "^5.14.0" + }, + "peerDependencies": { + "hardhat": "^2.0.4" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nomicfoundation/ignition-core": { + "version": "0.15.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ignition-core/-/ignition-core-0.15.4.tgz", + "integrity": "sha512-i379lH+xOLFdaDv0KiNma550ZXCHc5ZkmKYhM44xyLMKBlvX6skUVFkgUjjN1gvprgOIxc17GVQXlR1R5FhGZA==", + "dev": true, + "peer": true, + "dependencies": { + "@ethersproject/address": "5.6.1", + "@nomicfoundation/solidity-analyzer": "^0.1.1", + "cbor": "^9.0.0", + "debug": "^4.3.2", + "ethers": "^6.7.0", + "fs-extra": "^10.0.0", + "immer": "10.0.2", + "lodash": "4.17.21", + "ndjson": "2.0.0" + } + }, + "node_modules/@nomicfoundation/ignition-core/node_modules/@ethersproject/address": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.6.1.tgz", + "integrity": "sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/keccak256": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/rlp": "^5.6.1" + } + }, + "node_modules/@nomicfoundation/ignition-core/node_modules/cbor": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", + "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", + "dev": true, + "peer": true, + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@nomicfoundation/ignition-core/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@nomicfoundation/ignition-ui": { + "version": "0.15.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ignition-ui/-/ignition-ui-0.15.4.tgz", + "integrity": "sha512-cHbmuxmhso5n2zdIaaIW4p8NNzrFj0mrnv8ufhAZfM3s3IFrRoGc1zo8hI/n1CiOTPuqUbdZcB79d+2tCKtCNw==", + "dev": true, + "peer": true + }, "node_modules/@nomicfoundation/solidity-analyzer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz", @@ -2327,186 +2420,307 @@ "node": ">= 10" } }, - "node_modules/@nomiclabs/hardhat-ethers": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.3.tgz", - "integrity": "sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg==", + "node_modules/@nomiclabs/hardhat-solhint": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-solhint/-/hardhat-solhint-3.1.0.tgz", + "integrity": "sha512-5jNiYwLuiHZ2B11Ds4U5jH+DR565PqpsdbXml6iYfqMguyJb+ulU2rt58+hprNhoFKZds8cOlf9FaoWvA9KqkA==", "dev": true, - "peer": true, + "dependencies": { + "solhint": "^3.4.0" + }, "peerDependencies": { - "ethers": "^5.0.0", "hardhat": "^2.0.0" } }, - "node_modules/@nomiclabs/hardhat-etherscan": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.7.tgz", - "integrity": "sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ==", + "node_modules/@nomiclabs/hardhat-solhint/node_modules/@solidity-parser/parser": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.16.2.tgz", + "integrity": "sha512-PI9NfoA3P8XK2VBkK5oIfRgKDsicwDZfkVq9ZTBCQYGOP1N2owgY2dyLGyU5/J/hQs8KRk55kdmvTLjy3Mu3vg==", "dev": true, - "peer": true, "dependencies": { - "@ethersproject/abi": "^5.1.2", - "@ethersproject/address": "^5.0.2", - "cbor": "^8.1.0", - "chalk": "^2.4.2", - "debug": "^4.1.1", - "fs-extra": "^7.0.1", - "lodash": "^4.17.11", - "semver": "^6.3.0", - "table": "^6.8.0", - "undici": "^5.14.0" - }, - "peerDependencies": { - "hardhat": "^2.0.4" + "antlr4ts": "^0.5.0-alpha.4" } }, - "node_modules/@nomiclabs/hardhat-etherscan/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/@nomiclabs/hardhat-solhint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "peer": true, "dependencies": { - "color-convert": "^1.9.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">=4" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@nomiclabs/hardhat-etherscan/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/@nomiclabs/hardhat-solhint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "peer": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@nomiclabs/hardhat-etherscan/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/@nomiclabs/hardhat-solhint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "peer": true, "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@nomiclabs/hardhat-etherscan/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "peer": true + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } }, - "node_modules/@nomiclabs/hardhat-etherscan/node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "node_modules/@nomiclabs/hardhat-solhint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "peer": true, "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=7.0.0" } }, - "node_modules/@nomiclabs/hardhat-etherscan/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/@nomiclabs/hardhat-solhint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@nomiclabs/hardhat-solhint/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "dev": true, - "peer": true, "engines": { - "node": ">=4" + "node": ">=14" } }, - "node_modules/@nomiclabs/hardhat-etherscan/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "node_modules/@nomiclabs/hardhat-solhint/node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", "dev": true, - "peer": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@nomiclabs/hardhat-etherscan/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/@nomiclabs/hardhat-solhint/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@nomiclabs/hardhat-etherscan/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@nomiclabs/hardhat-solhint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@nomiclabs/hardhat-solhint/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, - "peer": true, "dependencies": { - "has-flag": "^3.0.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/@nomiclabs/hardhat-etherscan/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "node_modules/@nomiclabs/hardhat-solhint/node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, - "peer": true, + "optional": true, + "bin": { + "prettier": "bin-prettier.js" + }, "engines": { - "node": ">= 4.0.0" + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/@nomiclabs/hardhat-solhint": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-solhint/-/hardhat-solhint-3.0.1.tgz", - "integrity": "sha512-GqDoStxL1aA9hZul9HRdk+3eEZ/XLBwvIlz3/EJUusUsoadNYEnio9aYOsBeNeZWo+B/Fd3EgMXgbf9wWQLyRA==", + "node_modules/@nomiclabs/hardhat-solhint/node_modules/solhint": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/solhint/-/solhint-3.6.2.tgz", + "integrity": "sha512-85EeLbmkcPwD+3JR7aEMKsVC9YrRSxd4qkXuMzrlf7+z2Eqdfm1wHWq1ffTuo5aDhoZxp2I9yF3QkxZOxOL7aQ==", "dev": true, "dependencies": { - "solhint": "^3.4.0" + "@solidity-parser/parser": "^0.16.0", + "ajv": "^6.12.6", + "antlr4": "^4.11.0", + "ast-parents": "^0.0.1", + "chalk": "^4.1.2", + "commander": "^10.0.0", + "cosmiconfig": "^8.0.0", + "fast-diff": "^1.2.0", + "glob": "^8.0.3", + "ignore": "^5.2.4", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "pluralize": "^8.0.0", + "semver": "^7.5.2", + "strip-ansi": "^6.0.1", + "table": "^6.8.1", + "text-table": "^0.2.0" }, - "peerDependencies": { - "hardhat": "^2.0.0" + "bin": { + "solhint": "solhint.js" + }, + "optionalDependencies": { + "prettier": "^2.8.3" + } + }, + "node_modules/@nomiclabs/hardhat-solhint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/@onchain-id/solidity": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@onchain-id/solidity/-/solidity-2.1.0.tgz", - "integrity": "sha512-BBpBmUs8gg99N5NIKzANbs3R6DUhd90z2GEFvScVBhpHvpQhI5IzPNFRP6cXua1Lo0dWdNffxsteB3eUY1XMZw==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@onchain-id/solidity/-/solidity-2.2.1.tgz", + "integrity": "sha512-B54InT8yi89qlh9UVCARcfdQLVDP7Lef87B/Ww2Wn19oyEbPmlWho2EK1sgnrt/8Q0fGX/7y5rDnx3HPy28NTA==", "dev": true }, "node_modules/@openzeppelin/contracts": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.9.3.tgz", - "integrity": "sha512-He3LieZ1pP2TNt5JbkPA4PNT9WC3gOTOlDcFGJW4Le4QKqwmiNJCRt44APfxMxvq7OugU/cqYuPcSBzOw38DAg==", + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.9.6.tgz", + "integrity": "sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA==", "dev": true }, "node_modules/@openzeppelin/contracts-upgradeable": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.9.3.tgz", - "integrity": "sha512-jjaHAVRMrE4UuZNfDwjlLGDxTHWIOwTJS2ldnc278a0gevfXfPr8hxKEVBGFBE96kl2G3VHDZhUimw/+G3TG2A==", + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.9.6.tgz", + "integrity": "sha512-m4iHazOsOCv1DgM7eD7GupTJ+NFVujRZt1wzddDPSVGpWdKq1SKkla5htKG7+IS4d2XOCtzkUNwRZ7Vq5aEUMA==", "dev": true }, + "node_modules/@openzeppelin/defender-admin-client": { + "version": "1.54.6", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-admin-client/-/defender-admin-client-1.54.6.tgz", + "integrity": "sha512-P4lxJDySrekWNuPa7FeyW/UmuxnuIXIAGYr5gZnmnMHRsYNaw+XfgkiCDfoGtjEyJbXYxXttYF6iAZhWQPdf1g==", + "dev": true, + "dependencies": { + "@openzeppelin/defender-base-client": "1.54.6", + "axios": "^1.4.0", + "ethers": "^5.7.2", + "lodash": "^4.17.19", + "node-fetch": "^2.6.0" + } + }, + "node_modules/@openzeppelin/defender-admin-client/node_modules/ethers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", + "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.1", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.2", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.1", + "@ethersproject/wordlists": "5.7.0" + } + }, "node_modules/@openzeppelin/defender-base-client": { - "version": "1.54.1", - "resolved": "https://registry.npmjs.org/@openzeppelin/defender-base-client/-/defender-base-client-1.54.1.tgz", - "integrity": "sha512-DRGz/7KN3ZQwu28YWMOaojrC7jjPkz/uCwkC8/C8B11qwZhA5qIVvyhYHhhFOCl0J84+E3TNdvkPD2q3p2WaJw==", + "version": "1.54.6", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-base-client/-/defender-base-client-1.54.6.tgz", + "integrity": "sha512-PTef+rMxkM5VQ7sLwLKSjp2DBakYQd661ZJiSRywx+q/nIpm3B/HYGcz5wPZCA5O/QcEP6TatXXDoeMwimbcnw==", "dev": true, "dependencies": { "amazon-cognito-identity-js": "^6.0.1", @@ -2516,61 +2730,145 @@ "node-fetch": "^2.6.0" } }, + "node_modules/@openzeppelin/defender-sdk-base-client": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-base-client/-/defender-sdk-base-client-1.13.1.tgz", + "integrity": "sha512-FI7YdfgDf0px+cXbXyDkS0mpqzyySHeLkKj90ymzAy1/sGYKHNC03vyzMnMfIRuxa4bF15wdL4MCpA60PSWGpQ==", + "dev": true, + "dependencies": { + "amazon-cognito-identity-js": "^6.3.6", + "async-retry": "^1.3.3" + } + }, + "node_modules/@openzeppelin/defender-sdk-deploy-client": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-deploy-client/-/defender-sdk-deploy-client-1.13.1.tgz", + "integrity": "sha512-zQEoURBRMknrOXLDNzK3gXiHfQbDImLKtEVPBOybya/MYqququBdNkRmPpSkJ45LHVbuxWyqRkkGFQp8+l/UQg==", + "dev": true, + "dependencies": { + "@openzeppelin/defender-sdk-base-client": "^1.13.1", + "axios": "^1.6.7", + "lodash": "^4.17.21" + } + }, + "node_modules/@openzeppelin/defender-sdk-network-client": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-network-client/-/defender-sdk-network-client-1.13.1.tgz", + "integrity": "sha512-QR9dTZ6MuJ5o+GwAKH4Hxy+xuElI0iCwpVqN/ntHG0Ar7neHoq/f7jPtk04/DgEmrwTUMLzTKpZWmUO1fxiEMA==", + "dev": true, + "dependencies": { + "@openzeppelin/defender-sdk-base-client": "^1.13.1", + "axios": "^1.6.7", + "lodash": "^4.17.21" + } + }, "node_modules/@openzeppelin/hardhat-upgrades": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-1.28.0.tgz", - "integrity": "sha512-7sb/Jf+X+uIufOBnmHR0FJVWuxEs2lpxjJnLNN6eCJCP8nD0v+Ot5lTOW2Qb/GFnh+fLvJtEkhkowz4ZQ57+zQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-3.1.0.tgz", + "integrity": "sha512-CQ5Cg2kE8WeW6qajUTacBsmkntiAwJd7f6p+BUtd1fEvEv7si4H2lmAqvjOjkFc9ihIEQxMBy50IsBXSZGktmg==", "dev": true, "dependencies": { - "@openzeppelin/defender-base-client": "^1.46.0", - "@openzeppelin/platform-deploy-client": "^0.8.0", - "@openzeppelin/upgrades-core": "^1.27.0", + "@openzeppelin/defender-admin-client": "^1.52.0", + "@openzeppelin/defender-base-client": "^1.52.0", + "@openzeppelin/defender-sdk-base-client": "^1.10.0", + "@openzeppelin/defender-sdk-deploy-client": "^1.10.0", + "@openzeppelin/defender-sdk-network-client": "^1.10.0", + "@openzeppelin/upgrades-core": "^1.32.0", "chalk": "^4.1.0", "debug": "^4.1.1", - "proper-lockfile": "^4.1.1" + "ethereumjs-util": "^7.1.5", + "proper-lockfile": "^4.1.1", + "undici": "^6.11.1" }, "bin": { "migrate-oz-cli-project": "dist/scripts/migrate-oz-cli-project.js" }, "peerDependencies": { - "@nomiclabs/hardhat-ethers": "^2.0.0", - "@nomiclabs/hardhat-etherscan": "^3.1.0", - "ethers": "^5.0.5", + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@nomicfoundation/hardhat-verify": "^2.0.0", + "ethers": "^6.6.0", "hardhat": "^2.0.2" }, "peerDependenciesMeta": { - "@nomiclabs/harhdat-etherscan": { + "@nomicfoundation/hardhat-verify": { "optional": true } } }, - "node_modules/@openzeppelin/platform-deploy-client": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/platform-deploy-client/-/platform-deploy-client-0.8.0.tgz", - "integrity": "sha512-POx3AsnKwKSV/ZLOU/gheksj0Lq7Is1q2F3pKmcFjGZiibf+4kjGxr4eSMrT+2qgKYZQH1ZLQZ+SkbguD8fTvA==", - "deprecated": "@openzeppelin/platform-deploy-client is deprecated. Please use @openzeppelin/defender-sdk-deploy-client", + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "@ethersproject/abi": "^5.6.3", - "@openzeppelin/defender-base-client": "^1.46.0", - "axios": "^0.21.2", - "lodash": "^4.17.19", - "node-fetch": "^2.6.0" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@openzeppelin/platform-deploy-client/node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "follow-redirects": "^1.14.0" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/undici": { + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.18.1.tgz", + "integrity": "sha512-/0BWqR8rJNRysS5lqVmfc7eeOErcOP4tZpATVjJOojjHZ71gSYVAtFhEmadcIjwMIUehh5NFyKGsXCnXIajtbA==", + "dev": true, + "engines": { + "node": ">=18.17" } }, "node_modules/@openzeppelin/upgrades-core": { - "version": "1.32.5", - "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.32.5.tgz", - "integrity": "sha512-R0wprsyJ4xWiRW05kaTfZZkRVpG2g0af3/hpjE7t2mX0Eb2n40MQLokTwqIk4LDzpp910JfLSpB0vBuZ6WNPog==", + "version": "1.33.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.33.1.tgz", + "integrity": "sha512-YRxIRhTY1b+j7+NUUu8Uuem5ugxKexEMVd8dBRWNgWeoN1gS1OCrhgUg0ytL+54vzQ+SGWZDfNnzjVuI1Cj1Zw==", "dev": true, "dependencies": { "cbor": "^9.0.0", @@ -2586,6 +2884,21 @@ "openzeppelin-upgrades-core": "dist/cli/cli.js" } }, + "node_modules/@openzeppelin/upgrades-core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/@openzeppelin/upgrades-core/node_modules/cbor": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", @@ -2598,6 +2911,52 @@ "node": ">=16" } }, + "node_modules/@openzeppelin/upgrades-core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -2608,6 +2967,71 @@ "node": ">=14" } }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "dev": true, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "dev": true, + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/@pnpm/npm-conf": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", + "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", + "dev": true, + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@prettier/sync": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@prettier/sync/-/sync-0.3.0.tgz", + "integrity": "sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw==", + "dev": true, + "funding": { + "url": "https://github.com/prettier/prettier-synchronized?sponsor=1" + }, + "peerDependencies": { + "prettier": "^3.0.0" + } + }, "node_modules/@primitivefi/hardhat-dodoc": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@primitivefi/hardhat-dodoc/-/hardhat-dodoc-0.2.3.tgz", @@ -2622,16 +3046,13 @@ } }, "node_modules/@scure/base": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", - "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", + "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] + "funding": { + "url": "https://paulmillr.com/funding/" + } }, "node_modules/@scure/bip32": { "version": "1.1.5", @@ -2730,15 +3151,6 @@ "node": ">=6" } }, - "node_modules/@sentry/node/node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/@sentry/tracing": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", @@ -2777,16 +3189,28 @@ "node": ">=6" } }, + "node_modules/@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, "node_modules/@smithy/types": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.11.0.tgz", - "integrity": "sha512-AR0SXO7FuAskfNhyGfSTThpLRntDI5bOrU0xrpVYU0rZyjl3LBXInZFMTP/NNSd7IS6Ksdtar0QvnrPRIhVrLQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.0.0.tgz", + "integrity": "sha512-VvWuQk2RKFuOr98gFhjca7fkBS+xLLURT8bUjk5XQoV0ZLm7WPwWPPY3/AwzTLuUBDeoKDCthfe1AsTUWaSEhw==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/types/node_modules/tslib": { @@ -2796,42 +3220,58 @@ "dev": true }, "node_modules/@solidity-parser/parser": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.1.tgz", - "integrity": "sha512-eLjj2L6AuQjBB6s/ibwCAc0DwrR5Ge+ys+wgWo+bviU7fV2nTMQhU63CGaDKXg9iTmMxwhkyoggdIR7ZGRfMgw==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.5.tgz", + "integrity": "sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==", "dev": true, "dependencies": { "antlr4ts": "^0.5.0-alpha.4" } }, + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "dev": true, + "dependencies": { + "defer-to-connect": "^2.0.1" + }, + "engines": { + "node": ">=14.16" + } + }, "node_modules/@tsconfig/node10": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", - "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", - "dev": true + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "peer": true }, "node_modules/@tsconfig/node12": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", - "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", - "dev": true + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "peer": true }, "node_modules/@tsconfig/node14": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", - "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", - "dev": true + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "peer": true }, "node_modules/@tsconfig/node16": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", - "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", - "dev": true + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "peer": true }, - "node_modules/@typechain/ethers-v5": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-10.2.1.tgz", - "integrity": "sha512-n3tQmCZjRE6IU4h6lqUGiQ1j866n5MTCBJreNEHHVWXa2u9GJTaeYyU1/k+1qLutkyw+sS6VAN+AbeiTqsxd/A==", + "node_modules/@typechain/ethers-v6": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@typechain/ethers-v6/-/ethers-v6-0.5.1.tgz", + "integrity": "sha512-F+GklO8jBWlsaVV+9oHaPh5NJdd6rAKN4tklGfInX1Q7h0xPgVLP39Jl3eCulPB5qexI71ZFHwbljx4ZXNfouA==", "dev": true, "peer": true, "dependencies": { @@ -2839,29 +3279,25 @@ "ts-essentials": "^7.0.1" }, "peerDependencies": { - "@ethersproject/abi": "^5.0.0", - "@ethersproject/providers": "^5.0.0", - "ethers": "^5.1.3", - "typechain": "^8.1.1", - "typescript": ">=4.3.0" + "ethers": "6.x", + "typechain": "^8.3.2", + "typescript": ">=4.7.0" } }, "node_modules/@typechain/hardhat": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@typechain/hardhat/-/hardhat-6.1.6.tgz", - "integrity": "sha512-BiVnegSs+ZHVymyidtK472syodx1sXYlYJJixZfRstHVGYTi8V1O7QG4nsjyb0PC/LORcq7sfBUcHto1y6UgJA==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@typechain/hardhat/-/hardhat-9.1.0.tgz", + "integrity": "sha512-mtaUlzLlkqTlfPwB3FORdejqBskSnh+Jl8AIJGjXNAQfRQ4ofHADPl1+oU7Z3pAJzmZbUXII8MhOLQltcHgKnA==", "dev": true, "peer": true, "dependencies": { "fs-extra": "^9.1.0" }, "peerDependencies": { - "@ethersproject/abi": "^5.4.7", - "@ethersproject/providers": "^5.4.7", - "@typechain/ethers-v5": "^10.2.1", - "ethers": "^5.4.7", + "@typechain/ethers-v6": "^0.5.1", + "ethers": "^6.1.0", "hardhat": "^2.9.9", - "typechain": "^8.1.1" + "typechain": "^8.3.2" } }, "node_modules/@typechain/hardhat/node_modules/fs-extra": { @@ -2881,25 +3317,25 @@ } }, "node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", + "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-VOVRLM1mBxIRxydiViqPcKn6MIxZytrbMpd6RJLIWKxUNr3zux8no0Oc7kJx0WAPIitgZ0gkrDS+btlqQpubpw==", + "version": "4.3.16", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.16.tgz", + "integrity": "sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==", "dev": true, "peer": true }, "node_modules/@types/chai-as-promised": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.6.tgz", - "integrity": "sha512-cQLhk8fFarRVZAXUQV1xEnZgMoPxqKojBvRkqPCKPQCzEhpbbSKl1Uu75kDng7k5Ln6LQLUmNBjLlFthCgm1NA==", + "version": "7.1.8", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz", + "integrity": "sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==", "dev": true, "peer": true, "dependencies": { @@ -2915,6 +3351,15 @@ "@types/node": "*" } }, + "node_modules/@types/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/form-data": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz", @@ -2925,9 +3370,9 @@ } }, "node_modules/@types/glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", "dev": true, "peer": true, "dependencies": { @@ -2935,10 +3380,10 @@ "@types/node": "*" } }, - "node_modules/@types/json-schema": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", - "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", "dev": true }, "node_modules/@types/json5": { @@ -2954,41 +3399,32 @@ "dev": true }, "node_modules/@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", "dev": true, "peer": true }, - "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, "node_modules/@types/mocha": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", - "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", + "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", "dev": true, "peer": true }, "node_modules/@types/node": { - "version": "18.15.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", - "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", - "dev": true - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true + "version": "20.12.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", + "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/pbkdf2": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", - "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", "dev": true, "dependencies": { "@types/node": "*" @@ -3002,64 +3438,46 @@ "peer": true }, "node_modules/@types/qs": { - "version": "6.9.5", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz", - "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==", + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", "dev": true }, - "node_modules/@types/readable-stream": { - "version": "2.3.15", - "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.15.tgz", - "integrity": "sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "safe-buffer": "~5.1.1" - } - }, "node_modules/@types/secp256k1": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.3.tgz", - "integrity": "sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", + "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", "dev": true, "dependencies": { "@types/node": "*" } }, - "node_modules/@types/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==", - "dev": true - }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.4.tgz", - "integrity": "sha512-DAbgDXwtX+pDkAHwiGhqP3zWUGpW49B7eqmgpPtg+BKJXwdct79ut9+ifqOFPJGClGKSHXn2PTBatCnldJRUoA==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.10.0.tgz", + "integrity": "sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw==", "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.7.4", - "@typescript-eslint/type-utils": "6.7.4", - "@typescript-eslint/utils": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4", - "debug": "^4.3.4", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.10.0", + "@typescript-eslint/type-utils": "7.10.0", + "@typescript-eslint/utils": "7.10.0", + "@typescript-eslint/visitor-keys": "7.10.0", "graphemer": "^1.4.0", - "ignore": "^5.2.4", + "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -3068,26 +3486,26 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.4.tgz", - "integrity": "sha512-I5zVZFY+cw4IMZUeNCU7Sh2PO5O57F7Lr0uyhgCJmhN/BuTlnc55KxPonR4+EM3GBdfiCyGZye6DgMjtubQkmA==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.10.0.tgz", + "integrity": "sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.7.4", - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/typescript-estree": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4", + "@typescript-eslint/scope-manager": "7.10.0", + "@typescript-eslint/types": "7.10.0", + "@typescript-eslint/typescript-estree": "7.10.0", + "@typescript-eslint/visitor-keys": "7.10.0", "debug": "^4.3.4" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -3096,16 +3514,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.4.tgz", - "integrity": "sha512-SdGqSLUPTXAXi7c3Ob7peAGVnmMoGzZ361VswK2Mqf8UOYcODiYvs8rs5ILqEdfvX1lE7wEZbLyELCW+Yrql1A==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.10.0.tgz", + "integrity": "sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4" + "@typescript-eslint/types": "7.10.0", + "@typescript-eslint/visitor-keys": "7.10.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -3113,25 +3531,25 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.4.tgz", - "integrity": "sha512-n+g3zi1QzpcAdHFP9KQF+rEFxMb2KxtnJGID3teA/nxKHOVi3ylKovaqEzGBbVY2pBttU6z85gp0D00ufLzViQ==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.10.0.tgz", + "integrity": "sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.7.4", - "@typescript-eslint/utils": "6.7.4", + "@typescript-eslint/typescript-estree": "7.10.0", + "@typescript-eslint/utils": "7.10.0", "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -3140,12 +3558,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.4.tgz", - "integrity": "sha512-o9XWK2FLW6eSS/0r/tgjAGsYasLAnOWg7hvZ/dGYSSNjCh+49k5ocPN8OmG5aZcSJ8pclSOyVKP2x03Sj+RrCA==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.10.0.tgz", + "integrity": "sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg==", "dev": true, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -3153,21 +3571,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.4.tgz", - "integrity": "sha512-ty8b5qHKatlNYd9vmpHooQz3Vki3gG+3PchmtsA4TgrZBKWHNjWfkQid7K7xQogBqqc7/BhGazxMD5vr6Ha+iQ==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.10.0.tgz", + "integrity": "sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4", + "@typescript-eslint/types": "7.10.0", + "@typescript-eslint/visitor-keys": "7.10.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -3179,68 +3598,51 @@ } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@typescript-eslint/utils": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.4.tgz", - "integrity": "sha512-PRQAs+HUn85Qdk+khAxsVV+oULy3VkbH3hQ8hxLRJXWBEd7iI+GbQxH5SEUSH7kbEoTp6oT1bOwyga24ELALTA==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.10.0.tgz", + "integrity": "sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.7.4", - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/typescript-estree": "6.7.4", - "semver": "^7.5.4" + "@typescript-eslint/scope-manager": "7.10.0", + "@typescript-eslint/types": "7.10.0", + "@typescript-eslint/typescript-estree": "7.10.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.4.tgz", - "integrity": "sha512-pOW37DUhlTZbvph50x5zZCkFn3xzwkGtNoJHzIM3svpiSkJzwOYr/kVBaXmf+RAQiUDs1AHEZVNPg6UJCJpwRA==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.10.0.tgz", + "integrity": "sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.4", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "7.10.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/@xyrusworx/hardhat-solidity-json": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@xyrusworx/hardhat-solidity-json/-/hardhat-solidity-json-1.0.2.tgz", @@ -3250,47 +3652,17 @@ "hardhat": "^2.9.0" } }, - "node_modules/abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true, - "peer": true - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/abstract-level": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.3.tgz", - "integrity": "sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA==", + "node_modules/abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==", "dev": true, - "dependencies": { - "buffer": "^6.0.3", - "catering": "^2.1.0", - "is-buffer": "^2.0.5", - "level-supports": "^4.0.0", - "level-transcoder": "^1.0.1", - "module-error": "^1.0.1", - "queue-microtask": "^1.2.3" - }, - "engines": { - "node": ">=12" - } + "peer": true }, "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -3309,22 +3681,13 @@ } }, "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/address": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", - "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", "dev": true, "peer": true, "engines": { - "node": ">= 0.12.0" + "node": ">=0.4.0" } }, "node_modules/adm-zip": { @@ -3337,10 +3700,11 @@ } }, "node_modules/aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", - "dev": true + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", + "dev": true, + "peer": true }, "node_modules/agent-base": { "version": "6.0.2", @@ -3368,15 +3732,15 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.14.0.tgz", + "integrity": "sha512-oYs1UUtO97ZO2lJ4bwnWeQW8/zvOIQLGKcvPTsWmvc2SYgBb+upuNS5NxoLaMU4h8Ju3Nbj6Cq8mD2LQoqVKFA==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" }, "funding": { "type": "github", @@ -3396,21 +3760,10 @@ "js-cookie": "^2.2.1" } }, - "node_modules/amazon-cognito-identity-js/node_modules/buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dev": true, - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, "node_modules/amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", "dev": true, "optional": true, "peer": true, @@ -3418,10 +3771,42 @@ "node": ">=0.4.2" } }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-align/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, "engines": { "node": ">=6" @@ -3464,24 +3849,21 @@ } }, "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/antlr4": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.12.0.tgz", - "integrity": "sha512-23iB5IzXJZRZeK9TigzUyrNc9pSmNqAerJRBcNq1ETrmttMWRgaYZzC561IgEO3ygKsDJTYDTozABXa4b/fTQQ==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.13.1.tgz", + "integrity": "sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==", "dev": true, "engines": { "node": ">=16" @@ -3494,9 +3876,9 @@ "dev": true }, "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "dependencies": { "normalize-path": "^3.0.0", @@ -3510,17 +3892,14 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "dev": true, + "peer": true }, "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "peer": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/array-back": { "version": "3.1.0", @@ -3555,15 +3934,16 @@ "dev": true }, "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" }, "engines": { @@ -3593,15 +3973,16 @@ } }, "node_modules/array.prototype.findlast": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.4.tgz", - "integrity": "sha512-BMtLxpV+8BD+6ZPFIWmnUBpQoy+A+ujcg4rhp2iwCRJYA7PEh2MS4NL3lz8EiDlLrJPp2hg9qWihr5pd//jcGw==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", + "es-abstract": "^1.23.2", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" }, "engines": { @@ -3611,16 +3992,18 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3629,15 +4012,15 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -3647,18 +4030,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.reduce": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz", - "integrity": "sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q==", + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -3689,15 +4070,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -3717,7 +4089,7 @@ "node_modules/ast-parents": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/ast-parents/-/ast-parents-0.0.1.tgz", - "integrity": "sha1-UI/Q8F0MSHddnszaLhdEIyYejdM=", + "integrity": "sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==", "dev": true }, "node_modules/astral-regex": { @@ -3732,7 +4104,7 @@ "node_modules/async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", "dev": true, "peer": true }, @@ -3748,7 +4120,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, "node_modules/at-least-node": { @@ -3777,112 +4149,203 @@ } }, "node_modules/axios": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", - "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", "dev": true, "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, - "node_modules/axios/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", "dev": true, "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "safe-buffer": "^5.0.1" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/blakejs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", + "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", + "dev": true + }, + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "dev": true + }, + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">= 6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "node_modules/boxen/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/boxen/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/boxen/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/boxen/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "node_modules/boxen/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" + "engines": { + "node": ">=8" } }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bigint-crypto-utils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/bigint-crypto-utils/-/bigint-crypto-utils-3.2.2.tgz", - "integrity": "sha512-U1RbE3aX9ayCUVcIPHuPDPKcK3SFOXf93J1UK/iHlJuQB7bhagPIX06/CLpLEsDThJ7KA4Dhrnzynl+d2weTiw==", + "node_modules/boxen/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, "engines": { - "node": ">=14.0.0" + "node": ">=8" } }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "node_modules/boxen/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { "node": ">=8" } }, - "node_modules/blakejs": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", - "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", - "dev": true - }, - "node_modules/bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -3891,21 +4354,9 @@ "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", "dev": true }, - "node_modules/browser-level": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browser-level/-/browser-level-1.0.1.tgz", - "integrity": "sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ==", - "dev": true, - "dependencies": { - "abstract-level": "^1.0.2", - "catering": "^2.1.1", - "module-error": "^1.0.2", - "run-parallel-limit": "^1.1.0" - } - }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", @@ -3947,27 +4398,14 @@ } }, "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" } }, "node_modules/buffer-from": { @@ -3976,44 +4414,58 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/buffer-to-arraybuffer": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", - "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=", - "dev": true, - "peer": true - }, "node_modules/buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", "dev": true }, - "node_modules/bufferutil": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz", - "integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==", + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacheable-lookup": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", "dev": true, - "hasInstallScript": true, - "optional": true, - "peer": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, "engines": { - "node": ">=6.14.2" + "node": ">=14.16" } }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "node_modules/cacheable-request": { + "version": "10.2.14", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", + "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", "dev": true, "dependencies": { - "streamsearch": "^1.1.0" + "@types/http-cache-semantics": "^4.0.2", + "get-stream": "^6.0.1", + "http-cache-semantics": "^4.1.1", + "keyv": "^4.5.3", + "mimic-response": "^4.0.0", + "normalize-url": "^8.0.0", + "responselike": "^3.0.0" }, "engines": { - "node": ">=10.16.0" + "node": ">=14.16" + } + }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/call-bind": { @@ -4045,55 +4497,23 @@ } }, "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/case": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz", - "integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "dev": true }, - "node_modules/catering": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/catering/-/catering-2.1.1.tgz", - "integrity": "sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/cbor": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", @@ -4108,9 +4528,9 @@ } }, "node_modules/chai": { - "version": "4.3.10", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", - "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", "dev": true, "peer": true, "dependencies": { @@ -4127,29 +4547,25 @@ } }, "node_modules/chai-as-promised": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", - "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.2.tgz", + "integrity": "sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw==", "dev": true, "peer": true, "dependencies": { "check-error": "^1.0.2" }, "peerDependencies": { - "chai": ">= 2.1.2 < 5" + "chai": ">= 2.1.2 < 6" } }, "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" @@ -4178,16 +4594,10 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -4200,22 +4610,23 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } }, - "node_modules/chokidar/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "is-glob": "^4.0.1" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">= 6" } }, "node_modules/ci-info": { @@ -4234,23 +4645,6 @@ "safe-buffer": "^5.0.1" } }, - "node_modules/classic-level": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/classic-level/-/classic-level-1.3.0.tgz", - "integrity": "sha512-iwFAJQYtqRTRM0F6L8h4JCt00ZSGdOyqh7yVrhhjrOpFhmBjNlRUey64MCiyo6UmQHMJ+No3c81nujPv+n9yrg==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "abstract-level": "^1.0.2", - "catering": "^2.1.0", - "module-error": "^1.0.1", - "napi-macros": "^2.2.2", - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -4260,16 +4654,31 @@ "node": ">=6" } }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", "dev": true, "dependencies": { - "restore-cursor": "^3.1.0" + "restore-cursor": "^4.0.0" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cli-table3": { @@ -4284,64 +4693,21 @@ "engines": { "node": ">=6" }, - "optionalDependencies": { - "colors": "^1.1.2" - } - }, - "node_modules/cli-table3/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/cli-table3/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/cli-table3/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cli-table3/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" + "optionalDependencies": { + "colors": "^1.1.2" } }, "node_modules/cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, "dependencies": { "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" + "string-width": "^7.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4360,32 +4726,32 @@ } }, "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", "dev": true }, "node_modules/cli-truncate/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", "dev": true, "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cli-truncate/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { "ansi-regex": "^6.0.1" @@ -4398,32 +4764,55 @@ } }, "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=7.0.0" + "node": ">=8" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" } }, "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "node_modules/colorette": { @@ -4529,23 +4918,16 @@ "node": ">=4" } }, - "node_modules/command-line-usage/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/command-line-usage/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "peer": true, - "dependencies": { - "color-name": "1.1.3" + "engines": { + "node": ">=0.8.0" } }, - "node_modules/command-line-usage/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "peer": true - }, "node_modules/command-line-usage/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -4580,12 +4962,12 @@ } }, "node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/compare-func": { @@ -4607,7 +4989,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, "node_modules/concat-stream": { @@ -4625,111 +5007,146 @@ "typedarray": "^0.0.6" } }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/config-chain/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, "node_modules/confusing-browser-globals": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz", - "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", "dev": true }, "node_modules/conventional-changelog-angular": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz", - "integrity": "sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", + "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", "dev": true, "dependencies": { "compare-func": "^2.0.0" }, "engines": { - "node": ">=14" + "node": ">=16" } }, "node_modules/conventional-commits-parser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-4.0.0.tgz", - "integrity": "sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", "dev": true, "dependencies": { - "is-text-path": "^1.0.1", + "is-text-path": "^2.0.0", "JSONStream": "^1.3.5", - "meow": "^8.1.2", - "split2": "^3.2.2" + "meow": "^12.0.1", + "split2": "^4.0.0" }, "bin": { - "conventional-commits-parser": "cli.js" + "conventional-commits-parser": "cli.mjs" }, "engines": { - "node": ">=14" + "node": ">=16" + } + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "engines": { + "node": ">= 0.6" } }, "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, "node_modules/cosmiconfig": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", - "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", "dev": true, "dependencies": { - "import-fresh": "^3.2.1", + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0" + "parse-json": "^5.2.0" }, "engines": { "node": ">=14" }, "funding": { "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/cosmiconfig-typescript-loader": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.4.0.tgz", - "integrity": "sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.0.0.tgz", + "integrity": "sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==", "dev": true, + "dependencies": { + "jiti": "^1.19.1" + }, "engines": { - "node": ">=v14.21.3" + "node": ">=v16" }, "peerDependencies": { "@types/node": "*", - "cosmiconfig": ">=7", - "ts-node": ">=10", + "cosmiconfig": ">=8.2", "typescript": ">=4" } }, - "node_modules/cosmiconfig/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/cosmiconfig/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "dev": true, - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", @@ -4761,7 +5178,8 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "dev": true, + "peer": true }, "node_modules/cross-spawn": { "version": "7.0.3", @@ -4787,18 +5205,72 @@ } }, "node_modules/dargs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", + "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/death": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", - "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=", + "integrity": "sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w==", "dev": true, "peer": true }, @@ -4820,60 +5292,42 @@ } }, "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "dev": true, "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" + "mimic-response": "^3.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "peer": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/deep-eql": { @@ -4894,17 +5348,25 @@ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, - "peer": true, "engines": { "node": ">=4.0.0" } }, "node_modules/deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -4942,47 +5404,21 @@ "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, "engines": { "node": ">=0.4.0" } }, - "node_modules/detect-port": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", - "integrity": "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==", + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, - "peer": true, - "dependencies": { - "address": "^1.0.1", - "debug": "^2.6.0" - }, - "bin": { - "detect": "bin/detect-port", - "detect-port": "bin/detect-port" - }, "engines": { - "node": ">= 4.2.1" - } - }, - "node_modules/detect-port/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "peer": true, - "dependencies": { - "ms": "2.0.0" + "node": ">= 0.8" } }, - "node_modules/detect-port/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true, - "peer": true - }, "node_modules/diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", @@ -5029,13 +5465,6 @@ "node": ">=6.0.0" } }, - "node_modules/dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", - "dev": true, - "peer": true - }, "node_modules/dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -5069,6 +5498,12 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -5076,9 +5511,9 @@ "dev": true }, "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.1.tgz", + "integrity": "sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -5089,12 +5524,13 @@ } }, "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, "dependencies": { - "ansi-colors": "^4.1.1" + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8.6" @@ -5119,17 +5555,21 @@ } }, "node_modules/es-abstract": { - "version": "1.22.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz", - "integrity": "sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", "es-define-property": "^1.0.0", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", @@ -5140,10 +5580,11 @@ "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "hasown": "^2.0.1", + "hasown": "^2.0.2", "internal-slot": "^1.0.7", "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.3", @@ -5154,17 +5595,17 @@ "object-keys": "^1.1.1", "object.assign": "^4.1.5", "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.0", + "safe-array-concat": "^1.1.2", "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.2", "typed-array-byte-length": "^1.0.1", "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.5", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -5173,13 +5614,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true, - "peer": true - }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", @@ -5201,6 +5635,18 @@ "node": ">= 0.4" } }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", @@ -5242,27 +5688,30 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/escodegen": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==", "dev": true, "peer": true, "dependencies": { @@ -5282,24 +5731,10 @@ "source-map": "~0.2.0" } }, - "node_modules/escodegen/node_modules/esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true, - "peer": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/escodegen/node_modules/estraverse": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "integrity": "sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==", "dev": true, "peer": true, "engines": { @@ -5309,7 +5744,7 @@ "node_modules/escodegen/node_modules/levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", "dev": true, "peer": true, "dependencies": { @@ -5341,31 +5776,17 @@ "node_modules/escodegen/node_modules/prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", "dev": true, "peer": true, "engines": { "node": ">= 0.8.0" } }, - "node_modules/escodegen/node_modules/source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "amdefine": ">=0.0.4" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/escodegen/node_modules/type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", "dev": true, "peer": true, "dependencies": { @@ -5376,27 +5797,28 @@ } }, "node_modules/eslint": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.39.0.tgz", - "integrity": "sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.2", - "@eslint/js": "8.39.0", - "@humanwhocodes/config-array": "^0.11.8", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.0", - "espree": "^9.5.1", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -5404,22 +5826,19 @@ "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "bin": { @@ -5452,18 +5871,18 @@ } }, "node_modules/eslint-config-airbnb-base/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/eslint-config-prettier": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", - "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", + "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" @@ -5473,14 +5892,14 @@ } }, "node_modules/eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "dependencies": { "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, "node_modules/eslint-import-resolver-node/node_modules/debug": { @@ -5518,9 +5937,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", "dev": true, "dependencies": { "debug": "^3.2.7" @@ -5544,9 +5963,9 @@ } }, "node_modules/eslint-plugin-chai-friendly": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-chai-friendly/-/eslint-plugin-chai-friendly-0.7.2.tgz", - "integrity": "sha512-LOIfGx5sZZ5FwM1shr2GlYAWV9Omdi+1/3byuVagvQNoGUuU0iHhp7AfjA1uR+4dJ4Isfb4+FwBJgQajIw9iAg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-chai-friendly/-/eslint-plugin-chai-friendly-0.8.0.tgz", + "integrity": "sha512-d9W92QHA606QRhxEvPTzGFeZU+CHL5bsyfk7DvaXcxgpfEOny5Pem1G3X2274J1dxStlX/DotuanrQofULhl4g==", "dev": true, "engines": { "node": ">=0.10.0" @@ -5556,26 +5975,28 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.27.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", - "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.7.4", - "has": "^1.0.3", - "is-core-module": "^2.11.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.values": "^1.1.6", - "resolve": "^1.22.1", - "semver": "^6.3.0", - "tsconfig-paths": "^3.14.1" + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" @@ -5584,6 +6005,16 @@ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" } }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/eslint-plugin-import/node_modules/debug": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", @@ -5611,90 +6042,238 @@ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-security": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-3.0.0.tgz", + "integrity": "sha512-2Ij7PkmXIF2cKwoVkEgemwoXbOnxg5UfdhdcpNxZwJxC/10dbsdhHISrTyJ/n8DUkt3yiN6P1ywEgcMGjIwHIw==", + "dev": true, + "dependencies": { + "safe-regex": "^2.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, - "node_modules/eslint-plugin-prettier": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", - "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { - "prettier-linter-helpers": "^1.0.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "eslint": ">=7.28.0", - "prettier": ">=2.0.0" + "node": ">=10" }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-security": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.7.1.tgz", - "integrity": "sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ==", + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "safe-regex": "^2.1.1" + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=10" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "dependencies": { + "p-limit": "^3.0.2" }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "engines": { "node": ">=10" }, @@ -5702,51 +6281,48 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/eslint/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, "engines": { - "node": ">=10.13.0" + "node": ">=8" } }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "argparse": "^2.0.1" + "has-flag": "^4.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=8" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/eslint/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/espree": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", - "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "dependencies": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.0" + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -5756,9 +6332,9 @@ } }, "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", "dev": true, "peer": true, "bin": { @@ -5766,7 +6342,7 @@ "esvalidate": "bin/esvalidate.js" }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, "node_modules/esquery": { @@ -5840,22 +6416,76 @@ } } }, + "node_modules/eth-gas-reporter/node_modules/ethers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", + "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.1", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.2", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.1", + "@ethersproject/wordlists": "5.7.0" + } + }, "node_modules/ethereum-bloom-filters": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz", - "integrity": "sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.1.0.tgz", + "integrity": "sha512-J1gDRkLpuGNvWYzWslBQR9cDV4nd4kfvVTE/Wy4Kkm4yb3EYRSlyi0eB/inTsSTTVyA0+HyzHgbr95Fn/Z1fSw==", "dev": true, "peer": true, "dependencies": { - "js-sha3": "^0.8.0" + "@noble/hashes": "^1.4.0" } }, - "node_modules/ethereum-bloom-filters/node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "node_modules/ethereum-bloom-filters/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", "dev": true, - "peer": true + "peer": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } }, "node_modules/ethereum-cryptography": { "version": "1.2.0", @@ -5879,6 +6509,21 @@ "ethereumjs-util": "^6.0.0" } }, + "node_modules/ethereumjs-abi/node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ethereumjs-abi/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, "node_modules/ethereumjs-abi/node_modules/ethereum-cryptography": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", @@ -5918,9 +6563,9 @@ } }, "node_modules/ethereumjs-util": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz", - "integrity": "sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A==", + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", + "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", "dev": true, "dependencies": { "@types/bn.js": "^5.1.0", @@ -5933,21 +6578,6 @@ "node": ">=10.0.0" } }, - "node_modules/ethereumjs-util/node_modules/@types/bn.js": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", - "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ethereumjs-util/node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "dev": true - }, "node_modules/ethereumjs-util/node_modules/ethereum-cryptography": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", @@ -5972,57 +6602,65 @@ } }, "node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "version": "6.12.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.12.1.tgz", + "integrity": "sha512-j6wcVoZf06nqEcBbDWkKg8Fp895SS96dSnTCjiXT+8vt2o02raTn4Lo9ERUuIVU5bAjoPYeA+7ytQFexFmLuVw==", "dev": true, "funding": [ { "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + "url": "https://github.com/sponsors/ethers-io/" }, { "type": "individual", "url": "https://www.buymeacoffee.com/ricmoo" } ], + "peer": true, "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "18.15.13", + "aes-js": "4.0.0-beta.5", + "tslib": "2.4.0", + "ws": "8.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ethers/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, + "node_modules/ethers/node_modules/@types/node": { + "version": "18.15.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", + "dev": true, + "peer": true + }, + "node_modules/ethers/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true, + "peer": true + }, "node_modules/ethjs-unit": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", - "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", + "integrity": "sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==", "dev": true, "peer": true, "dependencies": { @@ -6037,7 +6675,7 @@ "node_modules/ethjs-unit/node_modules/bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", "dev": true, "peer": true }, @@ -6055,14 +6693,11 @@ "npm": ">=3" } }, - "node_modules/event-target-shim": { + "node_modules/eventemitter3": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, - "engines": { - "node": ">=6" - } + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true }, "node_modules/evp_bytestokey": { "version": "1.0.3", @@ -6075,23 +6710,23 @@ } }, "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, "dependencies": { "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" }, "engines": { - "node": ">=10" + "node": ">=16.17" }, "funding": { "url": "https://github.com/sindresorhus/execa?sponsor=1" @@ -6110,15 +6745,15 @@ "dev": true }, "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", "dev": true }, "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -6131,6 +6766,18 @@ "node": ">=8.6.0" } }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -6140,13 +6787,13 @@ "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, "node_modules/fastq": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.0.tgz", - "integrity": "sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -6165,9 +6812,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -6190,41 +6837,39 @@ } }, "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz", + "integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==", "dev": true, "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "locate-path": "^7.2.0", + "path-exists": "^5.0.0", + "unicorn-magic": "^0.1.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, - "peer": true, - "dependencies": { - "is-buffer": "~2.0.3" - }, "bin": { "flat": "cli.js" } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { @@ -6232,15 +6877,15 @@ } }, "node_modules/flatted": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.0.tgz", - "integrity": "sha512-XprP7lDrVT+kE2c2YlfiV+IfS9zxukiIOvNamPNsImNhXadSsQEbosItdL9bUQlCZXR13SvPk20BjWSWLA7m4A==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true, "funding": [ { @@ -6282,30 +6927,27 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", - "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, "dependencies": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", "mime-types": "^2.1.12" }, "engines": { - "node": ">= 0.12" + "node": ">= 6" + } + }, + "node_modules/form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "dev": true, + "engines": { + "node": ">= 14.17" } }, "node_modules/fp-ts": { @@ -6315,9 +6957,9 @@ "dev": true }, "node_modules/fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -6337,21 +6979,19 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, "node_modules/fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "deprecated": "\"Please update to latest v2.3 or v2.2\"", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, "os": [ "darwin" ], - "peer": true, "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } @@ -6383,12 +7023,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", @@ -6407,6 +7041,18 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-func-name": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", @@ -6446,12 +7092,12 @@ } }, "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, "engines": { - "node": ">=10" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6475,9 +7121,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", - "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", + "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", "dev": true, "dependencies": { "resolve-pkg-maps": "^1.0.0" @@ -6528,27 +7174,20 @@ "node": ">=4" } }, - "node_modules/ghost-testrpc/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/ghost-testrpc/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "peer": true, - "dependencies": { - "color-name": "1.1.3" + "engines": { + "node": ">=0.8.0" } }, - "node_modules/ghost-testrpc/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true, - "peer": true - }, "node_modules/ghost-testrpc/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "peer": true, "engines": { @@ -6569,103 +7208,69 @@ } }, "node_modules/git-raw-commits": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", - "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", + "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==", "dev": true, "dependencies": { - "dargs": "^7.0.0", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" + "dargs": "^8.0.0", + "meow": "^12.0.1", + "split2": "^4.0.0" }, "bin": { - "git-raw-commits": "cli.js" + "git-raw-commits": "cli.mjs" }, "engines": { - "node": ">=10" + "node": ">=16" } }, "node_modules/glob": { - "version": "10.2.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.6.tgz", - "integrity": "sha512-U/rnDpXJGF414QQQZv5uVsabTVxMSwzS5CH0p3DRCIV6ownl4f7PzGnkGmvlum2wB+9RlJWJZ6ACU1INnBqiPA==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2", - "path-scurry": "^1.7.0" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" }, "bin": { - "glob": "dist/cjs/src/bin.js" + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" + "node": ">=10.13.0" } }, - "node_modules/glob/node_modules/minimatch": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "node_modules/global-directory": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "ini": "4.1.1" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/global": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", - "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", - "dev": true, - "peer": true, - "dependencies": { - "min-document": "^2.19.0", - "process": "^0.11.10" - } - }, - "node_modules/global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", - "dev": true, - "dependencies": { - "ini": "^1.3.4" - }, - "engines": { - "node": ">=4" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/global-modules": { @@ -6696,6 +7301,13 @@ "node": ">=6" } }, + "node_modules/global-prefix/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "peer": true + }, "node_modules/global-prefix/node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -6710,9 +7322,9 @@ } }, "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -6725,12 +7337,13 @@ } }, "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, "dependencies": { - "define-properties": "^1.1.3" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -6740,69 +7353,72 @@ } }, "node_modules/globby": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", - "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, - "peer": true, "dependencies": { - "@types/glob": "^7.1.1", "array-union": "^2.1.0", "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", "slash": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dev": true, - "peer": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" + "get-intrinsic": "^1.1.3" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/globby/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/got": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", "dev": true, - "peer": true, "dependencies": { - "brace-expansion": "^1.1.7" + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" }, "engines": { - "node": "*" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/got/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/graceful-fs": { @@ -6811,37 +7427,21 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=4.x" - } - }, "node_modules/handlebars": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", - "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, "peer": true, "dependencies": { "minimist": "^1.2.5", - "neo-async": "^2.6.0", + "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, @@ -6855,41 +7455,36 @@ "uglify-js": "^3.1.4" } }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "peer": true, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, "node_modules/hardhat": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.14.0.tgz", - "integrity": "sha512-73jsInY4zZahMSVFurSK+5TNCJTXMv+vemvGia0Ac34Mm19fYp6vEPVGF3sucbumszsYxiTT2TbS8Ii2dsDSoQ==", + "version": "2.22.4", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.4.tgz", + "integrity": "sha512-09qcXJFBHQUaraJkYNr7XlmwjOj27xBB0SL2rYS024hTj9tPMbp26AFjlf5quBMO9SR4AJFg+4qWahcYcvXBuQ==", "dev": true, "dependencies": { "@ethersproject/abi": "^5.1.2", "@metamask/eth-sig-util": "^4.0.0", - "@nomicfoundation/ethereumjs-block": "5.0.1", - "@nomicfoundation/ethereumjs-blockchain": "7.0.1", - "@nomicfoundation/ethereumjs-common": "4.0.1", - "@nomicfoundation/ethereumjs-evm": "2.0.1", - "@nomicfoundation/ethereumjs-rlp": "5.0.1", - "@nomicfoundation/ethereumjs-statemanager": "2.0.1", - "@nomicfoundation/ethereumjs-trie": "6.0.1", - "@nomicfoundation/ethereumjs-tx": "5.0.1", - "@nomicfoundation/ethereumjs-util": "9.0.1", - "@nomicfoundation/ethereumjs-vm": "7.0.1", + "@nomicfoundation/edr": "^0.3.7", + "@nomicfoundation/ethereumjs-common": "4.0.4", + "@nomicfoundation/ethereumjs-tx": "5.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", "@nomicfoundation/solidity-analyzer": "^0.1.0", "@sentry/node": "^5.18.1", "@types/bn.js": "^5.1.0", "@types/lru-cache": "^5.1.0", - "abort-controller": "^3.0.0", "adm-zip": "^0.4.16", "aggregate-error": "^3.0.0", "ansi-escapes": "^4.3.0", + "boxen": "^5.1.2", "chalk": "^2.4.2", "chokidar": "^3.4.0", "ci-info": "^2.0.0", @@ -6909,7 +7504,6 @@ "mnemonist": "^0.38.0", "mocha": "^10.0.0", "p-map": "^4.0.0", - "qs": "^6.7.0", "raw-body": "^2.4.1", "resolve": "1.17.0", "semver": "^6.3.0", @@ -6924,9 +7518,6 @@ "bin": { "hardhat": "internal/cli/bootstrap.js" }, - "engines": { - "node": ">=14.0.0" - }, "peerDependencies": { "ts-node": "*", "typescript": "*" @@ -6941,9 +7532,9 @@ } }, "node_modules/hardhat-gas-reporter": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.9.tgz", - "integrity": "sha512-INN26G3EW43adGKBNzYWOlI3+rlLnasXTwW79YNnUhXPDa+yHESgt639dJEs37gCjhkbNKcRRJnomXEuMFBXJg==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.10.tgz", + "integrity": "sha512-02N4+So/fZrzJ88ci54GqwVA3Zrf0C9duuTyGt0CFRIh/CdNwbnTgkXkRfojOMLBQ+6t+lBIkgbsOtqMvNwikA==", "dev": true, "peer": true, "dependencies": { @@ -6955,15 +7546,6 @@ "hardhat": "^2.0.2" } }, - "node_modules/hardhat/node_modules/@types/bn.js": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.1.tgz", - "integrity": "sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/hardhat/node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -6974,15 +7556,16 @@ }, "engines": { "node": ">=4" - } - }, - "node_modules/hardhat/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + } + }, + "node_modules/hardhat/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "engines": { - "node": ">= 0.8" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/hardhat/node_modules/chalk": { @@ -6999,34 +7582,13 @@ "node": ">=4" } }, - "node_modules/hardhat/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/hardhat/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/hardhat/node_modules/commander": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", - "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", - "dev": true - }, - "node_modules/hardhat/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "node_modules/hardhat/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "engines": { - "node": ">= 0.8" + "node": ">=0.8.0" } }, "node_modules/hardhat/node_modules/find-up": { @@ -7059,6 +7621,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -7084,28 +7647,6 @@ "node": ">=4" } }, - "node_modules/hardhat/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/hardhat/node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "dev": true - }, "node_modules/hardhat/node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -7128,6 +7669,18 @@ "node": ">=4" } }, + "node_modules/hardhat/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/hardhat/node_modules/p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -7152,15 +7705,6 @@ "node": ">=4" } }, - "node_modules/hardhat/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/hardhat/node_modules/path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -7170,36 +7714,6 @@ "node": ">=4" } }, - "node_modules/hardhat/node_modules/qs": { - "version": "6.11.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz", - "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hardhat/node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/hardhat/node_modules/resolve": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", @@ -7212,96 +7726,15 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hardhat/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/hardhat/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" } }, - "node_modules/hardhat/node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/hardhat/node_modules/solc": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz", - "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==", - "dev": true, - "dependencies": { - "command-exists": "^1.2.8", - "commander": "3.0.2", - "follow-redirects": "^1.12.1", - "fs-extra": "^0.30.0", - "js-sha3": "0.8.0", - "memorystream": "^0.3.1", - "require-from-string": "^2.0.0", - "semver": "^5.5.0", - "tmp": "0.0.33" - }, - "bin": { - "solcjs": "solcjs" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/hardhat/node_modules/solc/node_modules/fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, - "node_modules/hardhat/node_modules/solc/node_modules/jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/hardhat/node_modules/solc/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/hardhat/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/hardhat/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -7314,15 +7747,6 @@ "node": ">=4" } }, - "node_modules/hardhat/node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, "node_modules/hardhat/node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -7332,16 +7756,25 @@ "node": ">= 4.0.0" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/hardhat/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, "engines": { - "node": ">= 0.4.0" + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/has-bigints": { @@ -7427,40 +7860,6 @@ "node": ">=4" } }, - "node_modules/hash-base/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/hash-base/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", @@ -7472,9 +7871,9 @@ } }, "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "dependencies": { "function-bind": "^1.1.2" @@ -7502,7 +7901,7 @@ "node_modules/hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", "dev": true, "dependencies": { "hash.js": "^1.0.3", @@ -7510,18 +7909,6 @@ "minimalistic-crypto-utils": "^1.0.1" } }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/http-basic": { "version": "8.1.3", "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz", @@ -7534,7 +7921,29 @@ "parse-cache-control": "^1.0.1" }, "engines": { - "node": ">=6.0.0" + "node": ">=6.0.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" } }, "node_modules/http-response-object": { @@ -7552,6 +7961,19 @@ "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", "dev": true }, + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "dev": true, + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -7566,24 +7988,24 @@ } }, "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, "engines": { - "node": ">=10.17.0" + "node": ">=16.17.0" } }, "node_modules/husky": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", - "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", + "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", "dev": true, "bin": { - "husky": "lib/bin.js" + "husky": "bin.mjs" }, "engines": { - "node": ">=14" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/typicode" @@ -7622,18 +8044,29 @@ ] }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" } }, + "node_modules/immer": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.2.tgz", + "integrity": "sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==", + "dev": true, + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/immutable": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", - "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz", + "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==", "dev": true }, "node_modules/import-fresh": { @@ -7661,10 +8094,20 @@ "node": ">=4" } }, + "node_modules/import-meta-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "engines": { "node": ">=0.8.19" @@ -7682,7 +8125,8 @@ "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, "dependencies": { "once": "^1.3.0", @@ -7696,10 +8140,13 @@ "dev": true }, "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } }, "node_modules/internal-slot": { "version": "1.0.7", @@ -7753,7 +8200,7 @@ "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, "node_modules/is-bigint": { @@ -7796,29 +8243,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=4" - } - }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -7832,22 +8256,40 @@ } }, "node_modules/is-core-module": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", - "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", "dev": true, "dependencies": { - "has": "^1.0.3" + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -7858,28 +8300,24 @@ "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", - "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", - "dev": true, - "peer": true - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -7895,7 +8333,7 @@ "node_modules/is-hex-prefixed": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", + "integrity": "sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==", "dev": true, "engines": { "node": ">=6.5.0", @@ -7957,12 +8395,12 @@ } }, "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/is-regex": { @@ -7997,12 +8435,12 @@ } }, "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -8024,12 +8462,12 @@ } }, "node_modules/is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, "dependencies": { - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -8039,15 +8477,15 @@ } }, "node_modules/is-text-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", + "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", "dev": true, "dependencies": { - "text-extensions": "^1.0.0" + "text-extensions": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/is-typed-array": { @@ -8092,13 +8530,13 @@ "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "node_modules/isomorphic-unfetch": { @@ -8112,9 +8550,9 @@ } }, "node_modules/jackspeak": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", - "integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.1.2.tgz", + "integrity": "sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ==", "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" @@ -8129,21 +8567,26 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/jiti": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, "node_modules/js-cookie": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==", "dev": true }, - "node_modules/js-sdsl": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", - "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "dev": true }, "node_modules/js-tokens": { "version": "4.0.0", @@ -8152,19 +8595,23 @@ "dev": true }, "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "peer": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -8172,21 +8619,28 @@ "dev": true }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "peer": true + }, "node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "dependencies": { "minimist": "^1.2.0" @@ -8217,9 +8671,9 @@ ] }, "node_modules/jsonschema": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.0.tgz", - "integrity": "sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", + "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", "dev": true, "peer": true, "engines": { @@ -8243,9 +8697,9 @@ } }, "node_modules/keccak": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.2.tgz", - "integrity": "sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", + "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -8257,18 +8711,13 @@ "node": ">=10.0.0" } }, - "node_modules/keccak/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "json-buffer": "3.0.1" } }, "node_modules/kind-of": { @@ -8276,6 +8725,7 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -8283,49 +8733,35 @@ "node_modules/klaw": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==", "dev": true, "optionalDependencies": { "graceful-fs": "^4.1.9" } }, - "node_modules/level": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/level/-/level-8.0.0.tgz", - "integrity": "sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ==", - "dev": true, - "dependencies": { - "browser-level": "^1.0.1", - "classic-level": "^1.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/level" - } - }, - "node_modules/level-supports": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-4.0.1.tgz", - "integrity": "sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA==", + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true, + "peer": true, "engines": { - "node": ">=12" + "node": ">=6" } }, - "node_modules/level-transcoder": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/level-transcoder/-/level-transcoder-1.0.1.tgz", - "integrity": "sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w==", + "node_modules/latest-version": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", + "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", "dev": true, "dependencies": { - "buffer": "^6.0.3", - "module-error": "^1.0.1" + "package-json": "^8.1.0" }, "engines": { - "node": ">=12" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/levn": { @@ -8342,12 +8778,15 @@ } }, "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", + "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", "dev": true, "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, "node_modules/lines-and-columns": { @@ -8357,233 +8796,126 @@ "dev": true }, "node_modules/lint-staged": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.2.2.tgz", - "integrity": "sha512-71gSwXKy649VrSU09s10uAT0rWCcY3aewhMaHyl2N84oBk4Xs9HgxvUp3AYu+bNsK4NrOYYxvSgg7FyGJ+jGcA==", - "dev": true, - "dependencies": { - "chalk": "5.2.0", - "cli-truncate": "^3.1.0", - "commander": "^10.0.0", - "debug": "^4.3.4", - "execa": "^7.0.0", - "lilconfig": "2.1.0", - "listr2": "^5.0.7", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-inspect": "^1.12.3", - "pidtree": "^0.6.0", - "string-argv": "^0.3.1", - "yaml": "^2.2.2" + "version": "15.2.5", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.5.tgz", + "integrity": "sha512-j+DfX7W9YUvdzEZl3Rk47FhDF6xwDBV5wwsCPw6BwWZVPYJemusQmvb9bRsW23Sqsaa+vRloAWogbK4BUuU2zA==", + "dev": true, + "dependencies": { + "chalk": "~5.3.0", + "commander": "~12.1.0", + "debug": "~4.3.4", + "execa": "~8.0.1", + "lilconfig": "~3.1.1", + "listr2": "~8.2.1", + "micromatch": "~4.0.7", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.4.2" }, "bin": { "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": "^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/lint-staged" - } - }, - "node_modules/lint-staged/node_modules/chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/lint-staged/node_modules/execa": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", - "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/lint-staged/node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/lint-staged/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18.12.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/lint-staged" } }, - "node_modules/lint-staged/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "node_modules/listr2": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.1.tgz", + "integrity": "sha512-irTfvpib/rNiD637xeevjO2l3Z5loZmuaRi0L0YE5LfijwVY96oyVn0DFD3o/teAok7nfobMG1THvvcHh/BP6g==", "dev": true, "dependencies": { - "mimic-fn": "^4.0.0" + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.0.0", + "rfdc": "^1.3.1", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18.0.0" } }, - "node_modules/lint-staged/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/lint-staged/node_modules/yaml": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz", - "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==", - "dev": true, - "engines": { - "node": ">= 14" - } + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true }, - "node_modules/listr2": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.8.tgz", - "integrity": "sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==", + "node_modules/listr2/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", "dev": true, "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.19", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.8.0", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": "^14.13.1 || >=16.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" + "node": ">=18" }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/listr2/node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/listr2/node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", "dev": true, "dependencies": { - "p-locate": "^5.0.0" + "p-locate": "^6.0.0" }, "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -8601,11 +8933,19 @@ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "dev": true }, - "node_modules/lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", - "dev": true + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "dev": true, + "peer": true + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "dev": true, + "peer": true }, "node_modules/lodash.isplainobject": { "version": "4.0.6", @@ -8677,63 +9017,216 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "dev": true, + "dependencies": { + "ansi-escapes": "^6.2.0", + "cli-cursor": "^4.0.0", + "slice-ansi": "^7.0.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/loupe": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", - "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "dev": true, "peer": true, "dependencies": { - "get-func-name": "^2.0.0" + "get-func-name": "^2.0.1" + } + }, + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lru_map": { @@ -8743,34 +9236,20 @@ "dev": true }, "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=10" + "node": "14 || >=16.14" } }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "peer": true }, "node_modules/markdown-table": { "version": "1.1.3", @@ -8778,15 +9257,6 @@ "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", "dev": true }, - "node_modules/mcl-wasm": { - "version": "0.7.9", - "resolved": "https://registry.npmjs.org/mcl-wasm/-/mcl-wasm-0.7.9.tgz", - "integrity": "sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ==", - "dev": true, - "engines": { - "node": ">=8.9.0" - } - }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -8798,61 +9268,22 @@ "safe-buffer": "^5.1.2" } }, - "node_modules/memory-level": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/memory-level/-/memory-level-1.0.0.tgz", - "integrity": "sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og==", - "dev": true, - "dependencies": { - "abstract-level": "^1.0.0", - "functional-red-black-tree": "^1.0.1", - "module-error": "^1.0.1" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", - "dev": true, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", "dev": true, - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.10.0" } }, - "node_modules/meow/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "node_modules/meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", "dev": true, "engines": { - "node": ">=10" + "node": ">=16.10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -8873,13 +9304,20 @@ "node": ">= 8" } }, + "node_modules/micro-ftch": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/micro-ftch/-/micro-ftch-0.3.1.tgz", + "integrity": "sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==", + "dev": true, + "peer": true + }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -8887,62 +9325,48 @@ } }, "node_modules/mime-db": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", - "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.28", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", - "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "dependencies": { - "mime-db": "1.45.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" } }, "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dev": true, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "dev": true, - "peer": true, - "dependencies": { - "dom-walk": "^0.1.0" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", "dev": true, "engines": { - "node": ">=4" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/minimalistic-assert": { @@ -8954,19 +9378,22 @@ "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", "dev": true }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { @@ -8978,37 +9405,23 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/minipass": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-6.0.2.tgz", - "integrity": "sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "peer": true, "dependencies": { - "minimist": "^1.2.5" + "minimist": "^1.2.6" }, "bin": { "mkdirp": "bin/cmd.js" @@ -9024,9 +9437,9 @@ } }, "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", + "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", "dev": true, "dependencies": { "ansi-colors": "4.1.1", @@ -9036,13 +9449,12 @@ "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.2.0", + "glob": "8.1.0", "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", "minimatch": "5.0.1", "ms": "2.1.3", - "nanoid": "3.3.3", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", @@ -9057,32 +9469,64 @@ }, "engines": { "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" } }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "node_modules/mocha/node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/mocha/node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], "dependencies": { - "balanced-match": "^1.0.0" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/mocha/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, "engines": { "node": ">=10" }, @@ -9091,57 +9535,59 @@ } }, "node_modules/mocha/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": "*" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/mocha/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/mocha/node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/mocha/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/mocha/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { - "argparse": "^2.0.1" + "p-locate": "^5.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/mocha/node_modules/minimatch": { @@ -9162,55 +9608,57 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "node_modules/mocha/node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "node_modules/mocha/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" + "dependencies": { + "yocto-queue": "^0.1.0" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/mocha/node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/mocha/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "p-limit": "^3.0.2" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true + "node_modules/mocha/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "node_modules/mocha/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "node_modules/mocha/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" } }, "node_modules/mocha/node_modules/yargs": { @@ -9231,41 +9679,59 @@ "node": ">=10" } }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "node_modules/mocha/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/module-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/module-error/-/module-error-1.0.2.tgz", - "integrity": "sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA==", + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/ndjson": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-2.0.0.tgz", + "integrity": "sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==", "dev": true, + "peer": true, + "dependencies": { + "json-stringify-safe": "^5.0.1", + "minimist": "^1.2.5", + "readable-stream": "^3.6.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "ndjson": "cli.js" + }, "engines": { "node": ">=10" } }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/napi-macros": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.2.2.tgz", - "integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==", - "dev": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true + "node_modules/ndjson/node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "peer": true, + "dependencies": { + "readable-stream": "^3.0.0" + } }, "node_modules/neo-async": { "version": "2.6.2", @@ -9290,27 +9756,6 @@ "lodash": "^4.17.21" } }, - "node_modules/node-environment-flags": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", - "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", - "dev": true, - "peer": true, - "dependencies": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } - }, - "node_modules/node-environment-flags/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "peer": true, - "bin": { - "semver": "bin/semver" - } - }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -9332,9 +9777,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", - "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", + "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", "dev": true, "bin": { "node-gyp-build": "bin.js", @@ -9354,7 +9799,7 @@ "node_modules/nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", "dev": true, "peer": true, "dependencies": { @@ -9364,21 +9809,6 @@ "nopt": "bin/nopt.js" } }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -9388,22 +9818,49 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-url": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", + "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, "dependencies": { - "path-key": "^3.0.0" + "path-key": "^4.0.0" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/number-to-bn": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", - "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", + "integrity": "sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==", "dev": true, "peer": true, "dependencies": { @@ -9418,14 +9875,14 @@ "node_modules/number-to-bn/node_modules/bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", "dev": true, "peer": true }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, "engines": { "node": ">=0.10.0" @@ -9468,47 +9925,60 @@ } }, "node_modules/object.entries": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", - "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" } }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.5.tgz", - "integrity": "sha512-yDNzckpM6ntyQiGTik1fKV1DcVDRS+w8bvpWNCBanvH5LfRX9O8WTHqQzG4RZwRAM4I0oU7TV11Lj5v0g20ibw==", + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, - "peer": true, "dependencies": { - "array.prototype.reduce": "^1.0.5", - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -9526,31 +9996,31 @@ "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "dependencies": { "wrappy": "1" } }, "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "mimic-fn": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "dependencies": { "deep-is": "^0.1.3", @@ -9558,7 +10028,7 @@ "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -9574,52 +10044,46 @@ "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12.20" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", "dev": true, "dependencies": { - "p-limit": "^3.0.2" + "yocto-queue": "^1.0.0" }, "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", "dev": true, "dependencies": { - "yocto-queue": "^0.1.0" + "p-limit": "^4.0.0" }, "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -9641,12 +10105,30 @@ } }, "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", "dev": true, "engines": { - "node": ">=6" + "node": ">=4" + } + }, + "node_modules/package-json": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", + "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==", + "dev": true, + "dependencies": { + "got": "^12.1.0", + "registry-auth-token": "^5.0.1", + "registry-url": "^6.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/parent-module": { @@ -9667,13 +10149,6 @@ "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==", "dev": true }, - "node_modules/parse-headers": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.4.tgz", - "integrity": "sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw==", - "dev": true, - "peer": true - }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -9693,18 +10168,18 @@ } }, "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", "dev": true, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "engines": { "node": ">=0.10.0" @@ -9726,30 +10201,21 @@ "dev": true }, "node_modules/path-scurry": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.9.2.tgz", - "integrity": "sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { - "lru-cache": "^9.1.1", - "minipass": "^5.0.0 || ^6.0.2" + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.2.tgz", - "integrity": "sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } - }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -9785,6 +10251,12 @@ "node": ">=0.12" } }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -9809,6 +10281,16 @@ "node": ">=0.10" } }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -9837,15 +10319,15 @@ } }, "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true, "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" @@ -9864,40 +10346,27 @@ } }, "node_modules/prettier-plugin-solidity": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.1.3.tgz", - "integrity": "sha512-fQ9yucPi2sBbA2U2Xjh6m4isUTJ7S7QLc/XDDsktqqxYfTwdYKJ0EnnywXHwCGAaYbQNK+HIYPL1OemxuMsgeg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.3.1.tgz", + "integrity": "sha512-MN4OP5I2gHAzHZG1wcuJl0FsLS3c4Cc5494bbg+6oQWBPuEamjwDvmGfFMZ6NFzsh3Efd9UUxeT7ImgjNH4ozA==", "dev": true, "dependencies": { - "@solidity-parser/parser": "^0.16.0", - "semver": "^7.3.8", - "solidity-comments-extractor": "^0.0.7" + "@solidity-parser/parser": "^0.17.0", + "semver": "^7.5.4", + "solidity-comments-extractor": "^0.0.8" }, "engines": { - "node": ">=12" + "node": ">=16" }, "peerDependencies": { - "prettier": ">=2.3.0 || >=3.0.0-alpha.0" + "prettier": ">=2.3.0" } }, "node_modules/prettier-plugin-solidity/node_modules/@solidity-parser/parser": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.16.0.tgz", - "integrity": "sha512-ESipEcHyRHg4Np4SqBCfcXwyxxna1DgFVz69bgpLV8vzl/NP1DtcKsJ4dJZXWQhY/Z4J2LeKBiOkOVZn9ct33Q==", - "dev": true, - "dependencies": { - "antlr4ts": "^0.5.0-alpha.4" - } - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true, - "peer": true, - "engines": { - "node": ">= 0.6.0" - } + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.17.0.tgz", + "integrity": "sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw==", + "dev": true }, "node_modules/process-nextick-args": { "version": "2.0.1", @@ -9914,6 +10383,20 @@ "asap": "~2.0.6" } }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "peer": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/proper-lockfile": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", @@ -9934,6 +10417,18 @@ "node": ">= 4" } }, + "node_modules/proper-lockfile/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -9941,36 +10436,27 @@ "dev": true }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/query-string": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", - "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "version": "6.12.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz", + "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==", "dev": true, - "peer": true, "dependencies": { - "decode-uri-component": "^0.2.0", - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" + "side-channel": "^1.0.6" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/queue-microtask": { @@ -9991,153 +10477,86 @@ "type": "consulting", "url": "https://feross.org/support" } - ] - }, - "node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } + ] }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" + "safe-buffer": "^5.1.0" } }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, "dependencies": { - "p-locate": "^4.1.0" + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "dependencies": { - "p-limit": "^2.2.0" + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" + "bin": { + "rc": "cli.js" } }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, "node_modules/readdirp": { @@ -10155,7 +10574,7 @@ "node_modules/rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", "dev": true, "peer": true, "dependencies": { @@ -10166,29 +10585,40 @@ } }, "node_modules/recursive-readdir": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", - "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", "dev": true, "peer": true, "dependencies": { - "minimatch": "3.0.4" + "minimatch": "^3.0.5" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0.0" } }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "node_modules/recursive-readdir/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/recursive-readdir/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "peer": true, "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" + "node": "*" } }, "node_modules/reduce-flatten": { @@ -10202,9 +10632,9 @@ } }, "node_modules/regexp-tree": { - "version": "0.1.24", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz", - "integrity": "sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==", + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", "dev": true, "bin": { "regexp-tree": "bin/regexp-tree" @@ -10228,6 +10658,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/registry-auth-token": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", + "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", + "dev": true, + "dependencies": { + "@pnpm/npm-conf": "^2.1.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/registry-url": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", + "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", + "dev": true, + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/req-cwd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-2.0.0.tgz", @@ -10264,7 +10721,7 @@ "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, "engines": { "node": ">=0.10.0" @@ -10279,20 +10736,13 @@ "node": ">=0.10.0" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true, - "peer": true - }, "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -10303,6 +10753,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, "node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", @@ -10312,18 +10768,6 @@ "node": ">=8" } }, - "node_modules/resolve-global": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", - "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", - "dev": true, - "dependencies": { - "global-dirs": "^0.1.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -10333,19 +10777,67 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/responselike": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "dev": true, + "dependencies": { + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", "dev": true, "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -10366,15 +10858,16 @@ } }, "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", "dev": true }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { "glob": "^7.1.3" @@ -10386,10 +10879,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/rimraf/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -10440,12 +10944,6 @@ "rlp": "bin/rlp" } }, - "node_modules/rlp/node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "dev": true - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -10469,58 +10967,14 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/run-parallel-limit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz", - "integrity": "sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rustbn.js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", - "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==", - "dev": true - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/rxjs/node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true - }, "node_modules/safe-array-concat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", - "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -10538,10 +10992,24 @@ "dev": true }, "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/safe-regex": { "version": "2.1.1", @@ -10601,24 +11069,32 @@ "istanbul": "lib/cli.js" } }, - "node_modules/sc-istanbul/node_modules/esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "node_modules/sc-istanbul/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "peer": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/sc-istanbul/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "peer": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/sc-istanbul/node_modules/glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "peer": true, "dependencies": { @@ -10635,24 +11111,65 @@ "node_modules/sc-istanbul/node_modules/has-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", "dev": true, "peer": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/sc-istanbul/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "peer": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/sc-istanbul/node_modules/js-yaml/node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sc-istanbul/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/sc-istanbul/node_modules/resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==", "dev": true, "peer": true }, "node_modules/sc-istanbul/node_modules/supports-color": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", "dev": true, "peer": true, "dependencies": { @@ -10697,13 +11214,10 @@ } }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -10711,25 +11225,27 @@ "node": ">=10" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, - "peer": true + "dependencies": { + "randombytes": "^2.1.0" + } }, "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "dependencies": { - "define-data-property": "^1.1.2", + "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10756,6 +11272,12 @@ "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", "dev": true }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, "node_modules/sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", @@ -10804,9 +11326,9 @@ } }, "node_modules/shelljs": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", - "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", "dev": true, "peer": true, "dependencies": { @@ -10821,10 +11343,22 @@ "node": ">=4" } }, + "node_modules/shelljs/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/shelljs/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "peer": true, "dependencies": { @@ -10856,57 +11390,41 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "peer": true + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "node_modules/simple-get": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", - "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true, - "peer": true, - "dependencies": { - "decompress-response": "^3.3.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } + "peer": true }, "node_modules/slash": { "version": "3.0.0", @@ -10933,39 +11451,131 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.0.tgz", - "integrity": "sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==", + "node_modules/solc": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz", + "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==", "dev": true, + "dependencies": { + "command-exists": "^1.2.8", + "commander": "3.0.2", + "follow-redirects": "^1.12.1", + "fs-extra": "^0.30.0", + "js-sha3": "0.8.0", + "memorystream": "^0.3.1", + "require-from-string": "^2.0.0", + "semver": "^5.5.0", + "tmp": "0.0.33" + }, + "bin": { + "solcjs": "solcjs" + }, "engines": { - "node": ">=12" + "node": ">=8.0.0" + } + }, + "node_modules/solc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/solc/node_modules/commander": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", + "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", + "dev": true + }, + "node_modules/solc/node_modules/fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "node_modules/solc/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "node_modules/solc/node_modules/jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/solc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=12" + "node": "*" + } + }, + "node_modules/solc/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/solc/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" } }, "node_modules/solhint": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/solhint/-/solhint-3.4.1.tgz", - "integrity": "sha512-pzZn2RlZhws1XwvLPVSsxfHrwsteFf5eySOhpAytzXwKQYbTCJV6z8EevYDiSVKMpWrvbKpEtJ055CuEmzp4Xg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/solhint/-/solhint-5.0.1.tgz", + "integrity": "sha512-QeQLS9HGCnIiibt+xiOa/+MuP7BWz9N7C5+Mj9pLHshdkNhuo3AzCpWmjfWVZBUuwIUO3YyCRVIcYLR3YOKGfg==", "dev": true, "dependencies": { - "@solidity-parser/parser": "^0.16.0", + "@solidity-parser/parser": "^0.18.0", "ajv": "^6.12.6", - "antlr4": "^4.11.0", + "antlr4": "^4.13.1-patch-1", "ast-parents": "^0.0.1", "chalk": "^4.1.2", "commander": "^10.0.0", @@ -10974,9 +11584,10 @@ "glob": "^8.0.3", "ignore": "^5.2.4", "js-yaml": "^4.1.0", + "latest-version": "^7.0.0", "lodash": "^4.17.21", "pluralize": "^8.0.0", - "semver": "^6.3.0", + "semver": "^7.5.2", "strip-ansi": "^6.0.1", "table": "^6.8.1", "text-table": "^0.2.0" @@ -10984,51 +11595,135 @@ "bin": { "solhint": "solhint.js" }, - "optionalDependencies": { - "prettier": "^2.8.3" + "optionalDependencies": { + "prettier": "^2.8.3" + } + }, + "node_modules/solhint-plugin-prettier": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/solhint-plugin-prettier/-/solhint-plugin-prettier-0.1.0.tgz", + "integrity": "sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw==", + "dev": true, + "dependencies": { + "@prettier/sync": "^0.3.0", + "prettier-linter-helpers": "^1.0.0" + }, + "peerDependencies": { + "prettier": "^3.0.0", + "prettier-plugin-solidity": "^1.0.0" + } + }, + "node_modules/solhint/node_modules/@solidity-parser/parser": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.18.0.tgz", + "integrity": "sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==", + "dev": true + }, + "node_modules/solhint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/solhint-plugin-prettier": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/solhint-plugin-prettier/-/solhint-plugin-prettier-0.0.5.tgz", - "integrity": "sha512-7jmWcnVshIrO2FFinIvDQmhQpfpS2rRRn3RejiYgnjIE68xO2bvrYvjqVNfrio4xH9ghOqn83tKuTzLjEbmGIA==", + "node_modules/solhint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "prettier-linter-helpers": "^1.0.0" + "color-convert": "^2.0.1" }, - "peerDependencies": { - "prettier": "^1.15.0 || ^2.0.0", - "prettier-plugin-solidity": "^1.0.0-alpha.14" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/solhint/node_modules/@solidity-parser/parser": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.16.0.tgz", - "integrity": "sha512-ESipEcHyRHg4Np4SqBCfcXwyxxna1DgFVz69bgpLV8vzl/NP1DtcKsJ4dJZXWQhY/Z4J2LeKBiOkOVZn9ct33Q==", + "node_modules/solhint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "antlr4ts": "^0.5.0-alpha.4" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/solhint/node_modules/argparse": { + "node_modules/solhint/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/solhint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/solhint/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/solhint/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/solhint/node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/solhint/node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -11044,17 +11739,11 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/solhint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } + "node_modules/solhint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/solhint/node_modules/minimatch": { "version": "5.1.6", @@ -11068,50 +11757,68 @@ "node": ">=10" } }, - "node_modules/solhint/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/solhint/node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, + "optional": true, "bin": { - "semver": "bin/semver.js" + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/solhint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/solidity-ast": { - "version": "0.4.55", - "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.55.tgz", - "integrity": "sha512-qeEU/r/K+V5lrAw8iswf2/yfWAnSGs3WKPHI+zAFKFjX0dIBVXEU/swQ8eJQYHf6PJWUZFO2uWV4V1wEOkeQbA==", + "version": "0.4.56", + "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.56.tgz", + "integrity": "sha512-HgmsA/Gfklm/M8GFbCX/J1qkVH0spXHgALCNZ8fA8x5X+MFdn/8CP2gr5OVyXjXw6RZTPC/Sxl2RUDQOXyNMeA==", "dev": true, "dependencies": { "array.prototype.findlast": "^1.2.2" } }, "node_modules/solidity-comments-extractor": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz", - "integrity": "sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==", + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.8.tgz", + "integrity": "sha512-htM7Vn6LhHreR+EglVMd2s+sZhcXAirB1Zlyrv5zBuTxieCvjfnRpd7iZk75m/u6NOlEyQ94C6TWbBn2cY7w8g==", "dev": true }, "node_modules/solidity-coverage": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.2.tgz", - "integrity": "sha512-cv2bWb7lOXPE9/SSleDO6czkFiMHgP4NXPj+iW9W7iEKLBk7Cj0AGBiNmGX3V1totl9wjPrT0gHmABZKZt65rQ==", + "version": "0.8.12", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.12.tgz", + "integrity": "sha512-8cOB1PtjnjFRqOgwFiD8DaUsYJtVJ6+YdXQtSZDrLGf8cdhhh8xzTtGzVTGeBf15kTv0v7lYPJlV/az7zLEPJw==", "dev": true, "peer": true, "dependencies": { "@ethersproject/abi": "^5.0.9", - "@solidity-parser/parser": "^0.14.1", + "@solidity-parser/parser": "^0.18.0", "chalk": "^2.4.2", "death": "^1.1.0", - "detect-port": "^1.3.0", "difflib": "^0.2.4", "fs-extra": "^8.1.0", "ghost-testrpc": "^0.0.2", "global-modules": "^2.0.0", "globby": "^10.0.1", "jsonschema": "^1.2.4", - "lodash": "^4.17.15", - "mocha": "7.1.2", + "lodash": "^4.17.21", + "mocha": "^10.2.0", "node-emoji": "^1.10.0", "pify": "^4.0.1", "recursive-readdir": "^2.2.2", @@ -11127,345 +11834,150 @@ "hardhat": "^2.11.0" } }, - "node_modules/solidity-coverage/node_modules/ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "node_modules/solidity-coverage/node_modules/@solidity-parser/parser": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.18.0.tgz", + "integrity": "sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==", "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } + "peer": true }, "node_modules/solidity-coverage/node_modules/ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "peer": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/solidity-coverage/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "peer": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/solidity-coverage/node_modules/chokidar": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", - "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", - "dev": true, - "peer": true, - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.2.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.1.1" - } - }, - "node_modules/solidity-coverage/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "peer": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/solidity-coverage/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true, - "peer": true - }, - "node_modules/solidity-coverage/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", - "dev": true, - "peer": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/solidity-coverage/node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/solidity-coverage/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "peer": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/solidity-coverage/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "peer": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/solidity-coverage/node_modules/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/solidity-coverage/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/solidity-coverage/node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "peer": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/solidity-coverage/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "peer": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/solidity-coverage/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "peer": true, "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/solidity-coverage/node_modules/log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "node_modules/solidity-coverage/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "peer": true, "dependencies": { - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=8" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/solidity-coverage/node_modules/mocha": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.1.2.tgz", - "integrity": "sha512-o96kdRKMKI3E8U0bjnfqW4QMk12MwZ4mhdBTf+B5a1q9+aq2HRnj+3ZdJu0B/ZhJeK78MgYuv6L8d/rA5AeBJA==", + "node_modules/solidity-coverage/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "peer": true, "dependencies": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "chokidar": "3.3.0", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "3.0.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.5", - "ms": "2.1.1", - "node-environment-flags": "1.0.6", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" + "node": ">=4" } }, - "node_modules/solidity-coverage/node_modules/mocha/node_modules/supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "node_modules/solidity-coverage/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "peer": true, - "dependencies": { - "has-flag": "^3.0.0" - }, "engines": { - "node": ">=6" + "node": ">=0.8.0" } }, - "node_modules/solidity-coverage/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "node_modules/solidity-coverage/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, - "peer": true + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } }, - "node_modules/solidity-coverage/node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "node_modules/solidity-coverage/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "peer": true, "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">= 0.4" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/solidity-coverage/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "node_modules/solidity-coverage/node_modules/globby": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", + "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", "dev": true, "peer": true, "dependencies": { - "p-limit": "^2.0.0" + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/solidity-coverage/node_modules/path-exists": { + "node_modules/solidity-coverage/node_modules/has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "peer": true, "engines": { "node": ">=4" } }, - "node_modules/solidity-coverage/node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "node_modules/solidity-coverage/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, "peer": true, - "engines": { - "node": ">=6" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/solidity-coverage/node_modules/readdirp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", - "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "node_modules/solidity-coverage/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "peer": true, "dependencies": { - "picomatch": "^2.0.4" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 8" - } - }, - "node_modules/solidity-coverage/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" + "node": "*" } }, "node_modules/solidity-coverage/node_modules/supports-color": { @@ -11491,52 +12003,18 @@ "node": ">= 4.0.0" } }, - "node_modules/solidity-coverage/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "peer": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/solidity-coverage/node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "peer": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/solidity-coverage/node_modules/yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "node_modules/source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==", "dev": true, + "optional": true, "peer": true, "dependencies": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" + "amdefine": ">=0.0.4" }, "engines": { - "node": ">=6" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": ">=0.8.0" } }, "node_modules/source-map-support": { @@ -11549,65 +12027,28 @@ "source-map": "^0.6.0" } }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", - "dev": true - }, "node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "dependencies": { - "readable-stream": "^3.0.0" - } - }, - "node_modules/split2/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, "engines": { - "node": ">= 6" + "node": ">= 10.x" } }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true, "peer": true }, @@ -11644,38 +12085,28 @@ "node": ">=8" } }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, - "peer": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "dependencies": { - "safe-buffer": "~5.1.0" + "safe-buffer": "~5.2.0" } }, "node_modules/string-argv": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", - "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", "dev": true, "engines": { "node": ">=0.6.19" @@ -11689,17 +12120,16 @@ "peer": true }, "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/string-width-cjs": { @@ -11717,15 +12147,55 @@ "node": ">=8" } }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/string-width/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -11735,28 +12205,31 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11790,25 +12263,28 @@ "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/strip-hex-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", - "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "integrity": "sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==", "dev": true, "dependencies": { "is-hex-prefixed": "1.0.0" @@ -11818,18 +12294,6 @@ "npm": ">=3" } }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -11843,15 +12307,18 @@ } }, "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -11889,10 +12356,32 @@ "get-port": "^3.1.0" } }, + "node_modules/synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/synckit/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, "node_modules/table": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", - "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", + "integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", "dev": true, "dependencies": { "ajv": "^8.0.1", @@ -11941,28 +12430,48 @@ "node": ">=8" } }, - "node_modules/table/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "node_modules/table/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "node_modules/table/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/table/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/table/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/table/node_modules/slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", @@ -11980,6 +12489,20 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/table/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -11990,18 +12513,21 @@ } }, "node_modules/text-extensions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", + "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", "dev": true, "engines": { - "node": ">=0.10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, "node_modules/then-request": { @@ -12032,10 +12558,24 @@ "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==", "dev": true }, + "node_modules/then-request/node_modules/form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, "node_modules/through2": { @@ -12043,34 +12583,11 @@ "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, + "peer": true, "dependencies": { "readable-stream": "3" } }, - "node_modules/through2/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -12095,28 +12612,28 @@ "node": ">=8.0" } }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "dev": true }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/ts-api-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", - "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "engines": { - "node": ">=16.13.0" + "node": ">=16" }, "peerDependencies": { "typescript": ">=4.2.0" @@ -12138,6 +12655,72 @@ "write-markdown": "dist/write-markdown.js" } }, + "node_modules/ts-command-line-args/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ts-command-line-args/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ts-command-line-args/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ts-command-line-args/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "peer": true + }, + "node_modules/ts-command-line-args/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ts-essentials": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", @@ -12149,10 +12732,11 @@ } }, "node_modules/ts-node": { - "version": "10.8.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.8.1.tgz", - "integrity": "sha512-Wwsnao4DQoJsN034wePSg5nZiw4YKXf56mPIAeD6wVmiv+RytNSWqc2f3fKvcUoV+Yn2+yocD71VOfQHbmVX4g==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, + "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -12196,18 +12780,19 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, + "peer": true, "engines": { "node": ">=0.3.1" } }, "node_modules/tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "dependencies": { "@types/json5": "^0.0.29", - "json5": "^1.0.1", + "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } @@ -12221,7 +12806,13 @@ "node_modules/tsort": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", - "integrity": "sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y=", + "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==", + "dev": true + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", "dev": true }, "node_modules/tweetnacl-util": { @@ -12265,9 +12856,9 @@ } }, "node_modules/typechain": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.3.1.tgz", - "integrity": "sha512-fA7clol2IP/56yq6vkMTR+4URF1nGjV82Wx6Rf09EsqD4tkzMAvEaqYxVFCavJm/1xaRga/oD55K+4FtuXwQOQ==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.3.2.tgz", + "integrity": "sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==", "dev": true, "peer": true, "dependencies": { @@ -12289,6 +12880,17 @@ "typescript": ">=4.3.0" } }, + "node_modules/typechain/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/typechain/node_modules/fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", @@ -12308,6 +12910,7 @@ "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "peer": true, "dependencies": { @@ -12325,13 +12928,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/typechain/node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "dev": true, - "peer": true - }, "node_modules/typechain/node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -12342,6 +12938,19 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/typechain/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/typechain/node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -12355,6 +12964,22 @@ "node": ">=10" } }, + "node_modules/typechain/node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "peer": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/typechain/node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -12419,9 +13044,9 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", - "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, "dependencies": { "call-bind": "^1.0.7", @@ -12445,16 +13070,17 @@ "dev": true }, "node_modules/typescript": { - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz", - "integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/typical": { @@ -12468,9 +13094,9 @@ } }, "node_modules/uglify-js": { - "version": "3.12.5", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.5.tgz", - "integrity": "sha512-SgpgScL4T7Hj/w/GexjnBHi3Ien9WS1Rpfg5y91WXMj9SY997ZCQU76mH4TpLwwfmMvoOU8wiaRkIf6NaH3mtg==", + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", "dev": true, "optional": true, "peer": true, @@ -12497,27 +13123,45 @@ } }, "node_modules/undici": { - "version": "5.21.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.21.0.tgz", - "integrity": "sha512-HOjK8l6a57b2ZGXOcUsI5NLfoTrfmbOl90ixJDl0AEFG4wgHNDQxtZy15/ZQp7HhjkpaGlp/eneMgtsu1dIlUA==", + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", "dev": true, "dependencies": { - "busboy": "^1.6.0" + "@fastify/busboy": "^2.0.0" }, "engines": { - "node": ">=12.18" + "node": ">=14.0" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/unfetch": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==", "dev": true }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "engines": { "node": ">= 10.0.0" @@ -12526,7 +13170,7 @@ "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, "engines": { "node": ">= 0.8" @@ -12541,28 +13185,6 @@ "punycode": "^2.1.0" } }, - "node_modules/url-set-query": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", - "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=", - "dev": true, - "peer": true - }, - "node_modules/utf-8-validate": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz", - "integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "peer": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/utf8": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", @@ -12573,7 +13195,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, "node_modules/uuid": { @@ -12589,28 +13211,20 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } + "peer": true }, "node_modules/web3-utils": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.5.3.tgz", - "integrity": "sha512-56nRgA+Ad9SEyCv39g36rTcr5fpsd4L9LgV3FK0aB66nAMazLAA6Qz4lH5XrUKPDyBIPGJIR+kJsyRtwcu2q1Q==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.10.4.tgz", + "integrity": "sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==", "dev": true, "peer": true, "dependencies": { - "bn.js": "^4.11.9", - "eth-lib": "0.2.8", + "@ethereumjs/util": "^8.1.0", + "bn.js": "^5.2.1", "ethereum-bloom-filters": "^1.0.6", + "ethereum-cryptography": "^2.1.2", "ethjs-unit": "0.1.6", "number-to-bn": "1.7.0", "randombytes": "^2.1.0", @@ -12620,16 +13234,72 @@ "node": ">=8.0.0" } }, - "node_modules/web3-utils/node_modules/eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", + "node_modules/web3-utils/node_modules/@noble/curves": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", + "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", + "dev": true, + "peer": true, + "dependencies": { + "@noble/hashes": "1.3.3" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/web3-utils/node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/web3-utils/node_modules/@scure/bip32": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.3.tgz", + "integrity": "sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==", + "dev": true, + "peer": true, + "dependencies": { + "@noble/curves": "~1.3.0", + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/web3-utils/node_modules/@scure/bip39": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.2.tgz", + "integrity": "sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==", + "dev": true, + "peer": true, + "dependencies": { + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/web3-utils/node_modules/ethereum-cryptography": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz", + "integrity": "sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==", "dev": true, "peer": true, "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" + "@noble/curves": "1.3.0", + "@noble/hashes": "1.3.3", + "@scure/bip32": "1.3.3", + "@scure/bip39": "1.2.2" } }, "node_modules/webidl-conversions": { @@ -12679,24 +13349,17 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true, - "peer": true - }, "node_modules/which-typed-array": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", - "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.6", - "call-bind": "^1.0.5", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.1" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -12705,67 +13368,45 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", "dev": true, - "peer": true, "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, - "node_modules/wide-align/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "peer": true, + "string-width": "^4.0.0" + }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/wide-align/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "node_modules/widest-line/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, - "peer": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "node_modules/widest-line/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "peer": true, "dependencies": { - "ansi-regex": "^3.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -12774,7 +13415,7 @@ "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", "dev": true, "peer": true }, @@ -12793,395 +13434,289 @@ } }, "node_modules/wordwrapjs/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/ws": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.8.tgz", - "integrity": "sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xhr": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", - "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", - "dev": true, - "peer": true, - "dependencies": { - "global": "~4.4.0", - "is-function": "^1.0.1", - "parse-headers": "^2.0.0", - "xtend": "^4.0.0" - } - }, - "node_modules/xhr-request": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", - "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", - "dev": true, - "peer": true, - "dependencies": { - "buffer-to-arraybuffer": "^0.0.5", - "object-assign": "^4.1.1", - "query-string": "^5.0.1", - "simple-get": "^2.7.0", - "timed-out": "^4.0.1", - "url-set-query": "^1.0.0", - "xhr": "^2.0.4" - } - }, - "node_modules/xhr-request-promise": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz", - "integrity": "sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg==", - "dev": true, - "peer": true, - "dependencies": { - "xhr-request": "^1.1.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", - "dev": true, - "peer": true - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "peer": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", "dev": true, + "peer": true, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "node_modules/workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/yargs-unparser/node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "bin": { - "flat": "cli.js" + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/yargs-unparser/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "engines": { "node": ">=8" } }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/yargs/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "peer": true, "dependencies": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/yargs/node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "peer": true, "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/yargs/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, - "peer": true, - "dependencies": { - "color-name": "1.1.3" + "engines": { + "node": ">=8" } }, - "node_modules/yargs/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "peer": true + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true, - "peer": true + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, - "node_modules/yargs/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "node_modules/ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", "dev": true, "peer": true, - "dependencies": { - "locate-path": "^3.0.0" - }, "engines": { - "node": ">=6" + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, - "peer": true, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/yargs/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "node_modules/yaml": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz", + "integrity": "sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==", "dev": true, - "peer": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "bin": { + "yaml": "bin.mjs" }, "engines": { - "node": ">=6" + "node": ">= 14" } }, - "node_modules/yargs/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, - "peer": true, "dependencies": { - "p-limit": "^2.0.0" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=6" + "node": ">=12" } }, - "node_modules/yargs/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true, - "peer": true, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, - "peer": true, "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, - "peer": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/yargs/node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "peer": true, "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=6" + "node": ">=8" } }, "node_modules/yargs/node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, - "peer": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "engines": { + "node": ">=12" } }, "node_modules/yn": { @@ -13189,17 +13724,18 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, + "peer": true, "engines": { "node": ">=6" } }, "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" diff --git a/package.json b/package.json index 0ef2ea2a..7aca3b9b 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "lint": "npm run lint:sol", "lint:sol": "solhint \"contracts/**/*.sol\"", "docs": "hardhat dodoc", - "prepare": "husky install" + "prepare": "husky" }, "repository": { "type": "git", @@ -41,35 +41,45 @@ }, "homepage": "https://github.com/TokenySolutions/T-REX#README", "devDependencies": { - "@commitlint/cli": "^17.6.1", - "@nomicfoundation/hardhat-toolbox": "^2.0.2", - "@nomiclabs/hardhat-solhint": "^3.0.1", - "@onchain-id/solidity": "^2.0.0", + "@commitlint/cli": "^19.3.0", + "@nomicfoundation/hardhat-toolbox": "^5.0.0", + "@nomiclabs/hardhat-solhint": "^3.1.0", + "@onchain-id/solidity": "^2.2.1", "@openzeppelin/contracts": "^4.8.3", "@openzeppelin/contracts-upgradeable": "^4.8.3", - "@openzeppelin/hardhat-upgrades": "^1.28.0", + "@openzeppelin/hardhat-upgrades": "^3.1.0", "@primitivefi/hardhat-dodoc": "^0.2.3", + "@typescript-eslint/eslint-plugin": "^7.10.0", + "@typescript-eslint/parser": "^7.10.0", "@xyrusworx/hardhat-solidity-json": "^1.0.2", - "eslint": "^8.39.0", + "eslint": "^8.0.0", "eslint-config-airbnb-base": "^15.0.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-chai-friendly": "^0.7.2", - "eslint-plugin-import": "^2.27.5", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-security": "^1.7.1", - "hardhat": "^2.14.0", - "husky": "^8.0.3", - "lint-staged": "^13.2.2", - "prettier": "^2.8.8", - "prettier-plugin-solidity": "^1.1.3", - "solhint": "^3.4.1", - "solhint-plugin-prettier": "^0.0.5", - "glob": "^10.2.6", - "fs-extra": "^11.1.1", - "@typescript-eslint/parser": "^6.7.4", - "@typescript-eslint/eslint-plugin": "^6.7.4", + "eslint-config-prettier": "^8.0.0", "eslint-import-resolver-typescript": "^3.6.1", - "eth-gas-reporter": "^0.2.27" + "eslint-plugin-chai-friendly": "^0.8.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-security": "^3.0.0", + "eth-gas-reporter": "^0.2.27", + "fs-extra": "^11.2.0", + "glob": "^10.4.1", + "hardhat": "^2.22.4", + "husky": "^9.0.11", + "lint-staged": "^15.2.5", + "prettier": "^3.2.5", + "prettier-plugin-solidity": "^1.3.1", + "solhint": "^5.0.1", + "solhint-plugin-prettier": "^0.1.0" + }, + "overrides": { + "@openzeppelin/defender-sdk-deploy-client": { + "@openzeppelin/defender-sdk-base-client": "1.13.1" + }, + "@openzeppelin/hardhat-upgrades": { + "@openzeppelin/defender-sdk-deploy-client": "1.13.1", + "@openzeppelin/defender-sdk-base-client": "1.13.1", + "@openzeppelin/defender-sdk-network-client": "1.13.1" + } }, "lint-staged": { "*.js": [ diff --git a/scripts/commit-msg.js b/scripts/commit-msg.js new file mode 100644 index 00000000..aabccf74 --- /dev/null +++ b/scripts/commit-msg.js @@ -0,0 +1,31 @@ +const fs = require('fs'); + +const TYPEMOJIS = Object.seal({ + '✨': ['sparkles', 'feat', 'feature'], + '🐛': ['bug', 'fix', 'bugfix'], + '♻': ['recycle', 'refactor'], + '📝': ['pencil', 'docs', 'note'], + '✅': ['white_check_mark', 'tests'], + '🔀': ['twisted_rightwards_arrows', 'merge'], + '✏': ['pencil2', 'typo'], + '🔧': ['wrench', 'config'], + '➕': ['heavy_plus_sign', 'add', 'plus'], + '➖': ['heavy_minus_sign', 'remove', 'minus'], + '🔖': ['bookmark', 'version', 'release'], + '👷': ['construction_worker', 'ci'], + '🚨': ['rotating_light', 'lint'], + '🚑': ['ambulance', 'hotfix'], + '🎉': ['tada'], +}); + +const commitMessage = fs.readFileSync(process.argv[2]).toString(); + +let editedCommitMessage = commitMessage; + +Object.entries(TYPEMOJIS).forEach(([typemoji, translations]) => { + translations.forEach(translation => { + editedCommitMessage = editedCommitMessage.replace(`:${translation}:`, typemoji); + }); +}); + +fs.writeFileSync(process.argv[2], editedCommitMessage); diff --git a/test/agentManager.test.ts b/test/agentManager.test.ts index bed52164..6c9839c4 100644 --- a/test/agentManager.test.ts +++ b/test/agentManager.test.ts @@ -14,7 +14,7 @@ describe('AgentManager', () => { } = await loadFixture(deployFullSuiteFixture); await expect( - agentManager.connect(aliceWallet).callForcedTransfer(aliceWallet.address, bobWallet.address, 200, aliceIdentity.address), + agentManager.connect(aliceWallet).callForcedTransfer(aliceWallet.address, bobWallet.address, 200, aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT Transfer Manager'); }); }); @@ -27,10 +27,10 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addTransferManager(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addTransferManager(aliceIdentity.target); await expect( - agentManager.connect(anotherWallet).callForcedTransfer(aliceWallet.address, bobWallet.address, 200, aliceIdentity.address), + agentManager.connect(anotherWallet).callForcedTransfer(aliceWallet.address, bobWallet.address, 200, aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT Transfer Manager'); }); }); @@ -43,11 +43,11 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addTransferManager(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addTransferManager(aliceIdentity.target); const transferTx = await agentManager .connect(aliceWallet) - .callForcedTransfer(aliceWallet.address, bobWallet.address, 200, aliceIdentity.address); + .callForcedTransfer(aliceWallet.address, bobWallet.address, 200, aliceIdentity.target); await expect(transferTx).to.emit(token, 'Transfer').withArgs(aliceWallet.address, bobWallet.address, 200); }); @@ -70,7 +70,7 @@ describe('AgentManager', () => { [aliceWallet.address, bobWallet.address], [bobWallet.address, aliceWallet.address], [200, 200], - aliceIdentity.address, + aliceIdentity.target, ), ).to.be.revertedWith('Role: Sender is NOT Transfer Manager'); }); @@ -84,7 +84,7 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addTransferManager(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addTransferManager(aliceIdentity.target); await expect( agentManager @@ -93,7 +93,7 @@ describe('AgentManager', () => { [aliceWallet.address, bobWallet.address], [bobWallet.address, aliceWallet.address], [200, 200], - aliceIdentity.address, + aliceIdentity.target, ), ).to.be.revertedWith('Role: Sender is NOT Transfer Manager'); }); @@ -107,7 +107,7 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addTransferManager(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addTransferManager(aliceIdentity.target); const transferTx = await agentManager .connect(aliceWallet) @@ -115,7 +115,7 @@ describe('AgentManager', () => { [aliceWallet.address, bobWallet.address], [bobWallet.address, aliceWallet.address], [200, 200], - aliceIdentity.address, + aliceIdentity.target, ); await expect(transferTx).to.emit(token, 'Transfer').withArgs(aliceWallet.address, bobWallet.address, 200); @@ -133,7 +133,7 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callPause(aliceIdentity.address)).to.be.revertedWith('Role: Sender is NOT Freezer'); + await expect(agentManager.connect(aliceWallet).callPause(aliceIdentity.target)).to.be.revertedWith('Role: Sender is NOT Freezer'); }); }); @@ -145,9 +145,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - await expect(agentManager.connect(anotherWallet).callPause(aliceIdentity.address)).to.be.revertedWith('Role: Sender is NOT Freezer'); + await expect(agentManager.connect(anotherWallet).callPause(aliceIdentity.target)).to.be.revertedWith('Role: Sender is NOT Freezer'); }); }); @@ -159,11 +159,11 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - const pauseTx = await agentManager.connect(aliceWallet).callPause(aliceIdentity.address); + const pauseTx = await agentManager.connect(aliceWallet).callPause(aliceIdentity.target); - await expect(pauseTx).to.emit(token, 'Paused').withArgs(agentManager.address); + await expect(pauseTx).to.emit(token, 'Paused').withArgs(agentManager.target); await expect(token.paused()).to.be.eventually.true; }); }); @@ -178,7 +178,7 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callUnpause(aliceIdentity.address)).to.be.revertedWith('Role: Sender is NOT Freezer'); + await expect(agentManager.connect(aliceWallet).callUnpause(aliceIdentity.target)).to.be.revertedWith('Role: Sender is NOT Freezer'); }); }); @@ -190,9 +190,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - await expect(agentManager.connect(anotherWallet).callUnpause(aliceIdentity.address)).to.be.revertedWith('Role: Sender is NOT Freezer'); + await expect(agentManager.connect(anotherWallet).callUnpause(aliceIdentity.target)).to.be.revertedWith('Role: Sender is NOT Freezer'); }); }); @@ -204,13 +204,13 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - await agentManager.connect(aliceWallet).callPause(aliceIdentity.address); + await agentManager.connect(aliceWallet).callPause(aliceIdentity.target); - const pauseTx = await agentManager.connect(aliceWallet).callUnpause(aliceIdentity.address); + const pauseTx = await agentManager.connect(aliceWallet).callUnpause(aliceIdentity.target); - await expect(pauseTx).to.emit(token, 'Unpaused').withArgs(agentManager.address); + await expect(pauseTx).to.emit(token, 'Unpaused').withArgs(agentManager.target); }); }); }); @@ -224,7 +224,7 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callMint(bobWallet.address, 1000, aliceIdentity.address)).to.be.revertedWith( + await expect(agentManager.connect(aliceWallet).callMint(bobWallet.address, 1000, aliceIdentity.target)).to.be.revertedWith( 'Role: Sender is NOT Supply Modifier', ); }); @@ -238,9 +238,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addSupplyModifier(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addSupplyModifier(aliceIdentity.target); - await expect(agentManager.connect(anotherWallet).callMint(bobWallet.address, 1000, aliceIdentity.address)).to.be.revertedWith( + await expect(agentManager.connect(anotherWallet).callMint(bobWallet.address, 1000, aliceIdentity.target)).to.be.revertedWith( 'Role: Sender is NOT Supply Modifier', ); }); @@ -254,11 +254,11 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addSupplyModifier(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addSupplyModifier(aliceIdentity.target); - const mintTx = await agentManager.connect(aliceWallet).callMint(bobWallet.address, 1000, aliceIdentity.address); + const mintTx = await agentManager.connect(aliceWallet).callMint(bobWallet.address, 1000, aliceIdentity.target); - await expect(mintTx).to.emit(token, 'Transfer').withArgs(ethers.constants.AddressZero, bobWallet.address, 1000); + await expect(mintTx).to.emit(token, 'Transfer').withArgs(ethers.ZeroAddress, bobWallet.address, 1000); }); }); }); @@ -273,7 +273,7 @@ describe('AgentManager', () => { } = await loadFixture(deployFullSuiteFixture); await expect( - agentManager.connect(aliceWallet).callBatchMint([bobWallet.address, aliceWallet.address], [1000, 500], aliceIdentity.address), + agentManager.connect(aliceWallet).callBatchMint([bobWallet.address, aliceWallet.address], [1000, 500], aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT Supply Modifier'); }); }); @@ -286,10 +286,10 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addSupplyModifier(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addSupplyModifier(aliceIdentity.target); await expect( - agentManager.connect(anotherWallet).callBatchMint([bobWallet.address, aliceWallet.address], [1000, 500], aliceIdentity.address), + agentManager.connect(anotherWallet).callBatchMint([bobWallet.address, aliceWallet.address], [1000, 500], aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT Supply Modifier'); }); }); @@ -302,14 +302,14 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addSupplyModifier(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addSupplyModifier(aliceIdentity.target); const mintTx = await agentManager .connect(aliceWallet) - .callBatchMint([bobWallet.address, aliceWallet.address], [1000, 500], aliceIdentity.address); + .callBatchMint([bobWallet.address, aliceWallet.address], [1000, 500], aliceIdentity.target); - await expect(mintTx).to.emit(token, 'Transfer').withArgs(ethers.constants.AddressZero, bobWallet.address, 1000); - await expect(mintTx).to.emit(token, 'Transfer').withArgs(ethers.constants.AddressZero, aliceWallet.address, 500); + await expect(mintTx).to.emit(token, 'Transfer').withArgs(ethers.ZeroAddress, bobWallet.address, 1000); + await expect(mintTx).to.emit(token, 'Transfer').withArgs(ethers.ZeroAddress, aliceWallet.address, 500); }); }); }); @@ -323,7 +323,7 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callBurn(bobWallet.address, 1000, aliceIdentity.address)).to.be.revertedWith( + await expect(agentManager.connect(aliceWallet).callBurn(bobWallet.address, 1000, aliceIdentity.target)).to.be.revertedWith( 'Role: Sender is NOT Supply Modifier', ); }); @@ -337,9 +337,9 @@ describe('AgentManager', () => { identities: { bobIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addSupplyModifier(bobIdentity.address); + await agentManager.connect(tokenAdmin).addSupplyModifier(bobIdentity.target); - await expect(agentManager.connect(anotherWallet).callBurn(bobWallet.address, 200, bobIdentity.address)).to.be.revertedWith( + await expect(agentManager.connect(anotherWallet).callBurn(bobWallet.address, 200, bobIdentity.target)).to.be.revertedWith( 'Role: Sender is NOT Supply Modifier', ); }); @@ -353,11 +353,11 @@ describe('AgentManager', () => { identities: { bobIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addSupplyModifier(bobIdentity.address); + await agentManager.connect(tokenAdmin).addSupplyModifier(bobIdentity.target); - const burnTx = await agentManager.connect(bobWallet).callBurn(bobWallet.address, 200, bobIdentity.address); + const burnTx = await agentManager.connect(bobWallet).callBurn(bobWallet.address, 200, bobIdentity.target); - await expect(burnTx).to.emit(token, 'Transfer').withArgs(bobWallet.address, ethers.constants.AddressZero, 200); + await expect(burnTx).to.emit(token, 'Transfer').withArgs(bobWallet.address, ethers.ZeroAddress, 200); }); }); }); @@ -372,7 +372,7 @@ describe('AgentManager', () => { } = await loadFixture(deployFullSuiteFixture); await expect( - agentManager.connect(aliceWallet).callBatchBurn([bobWallet.address, aliceWallet.address], [500, 1000], aliceIdentity.address), + agentManager.connect(aliceWallet).callBatchBurn([bobWallet.address, aliceWallet.address], [500, 1000], aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT Supply Modifier'); }); }); @@ -385,10 +385,10 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addSupplyModifier(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addSupplyModifier(aliceIdentity.target); await expect( - agentManager.connect(anotherWallet).callBatchBurn([bobWallet.address, aliceWallet.address], [500, 100], aliceIdentity.address), + agentManager.connect(anotherWallet).callBatchBurn([bobWallet.address, aliceWallet.address], [500, 100], aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT Supply Modifier'); }); }); @@ -401,14 +401,14 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addSupplyModifier(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addSupplyModifier(aliceIdentity.target); const burnTx = await agentManager .connect(aliceWallet) - .callBatchBurn([bobWallet.address, aliceWallet.address], [500, 100], aliceIdentity.address); + .callBatchBurn([bobWallet.address, aliceWallet.address], [500, 100], aliceIdentity.target); - await expect(burnTx).to.emit(token, 'Transfer').withArgs(bobWallet.address, ethers.constants.AddressZero, 500); - await expect(burnTx).to.emit(token, 'Transfer').withArgs(aliceWallet.address, ethers.constants.AddressZero, 100); + await expect(burnTx).to.emit(token, 'Transfer').withArgs(bobWallet.address, ethers.ZeroAddress, 500); + await expect(burnTx).to.emit(token, 'Transfer').withArgs(aliceWallet.address, ethers.ZeroAddress, 100); }); }); }); @@ -422,7 +422,7 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callSetAddressFrozen(aliceIdentity.address, true, aliceIdentity.address)).to.be.revertedWith( + await expect(agentManager.connect(aliceWallet).callSetAddressFrozen(aliceIdentity.target, true, aliceIdentity.target)).to.be.revertedWith( 'Role: Sender is NOT Freezer', ); }); @@ -436,9 +436,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - await expect(agentManager.connect(anotherWallet).callSetAddressFrozen(aliceIdentity.address, true, aliceIdentity.address)).to.be.revertedWith( + await expect(agentManager.connect(anotherWallet).callSetAddressFrozen(aliceIdentity.target, true, aliceIdentity.target)).to.be.revertedWith( 'Role: Sender is NOT Freezer', ); }); @@ -452,11 +452,11 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - const tx = await agentManager.connect(aliceWallet).callSetAddressFrozen(aliceWallet.address, true, aliceIdentity.address); + const tx = await agentManager.connect(aliceWallet).callSetAddressFrozen(aliceWallet.address, true, aliceIdentity.target); - await expect(tx).to.emit(token, 'AddressFrozen').withArgs(aliceWallet.address, true, agentManager.address); + await expect(tx).to.emit(token, 'AddressFrozen').withArgs(aliceWallet.address, true, agentManager.target); await expect(token.isFrozen(aliceWallet.address)).to.eventually.be.true; }); }); @@ -472,9 +472,7 @@ describe('AgentManager', () => { } = await loadFixture(deployFullSuiteFixture); await expect( - agentManager - .connect(aliceWallet) - .callBatchSetAddressFrozen([aliceIdentity.address, bobWallet.address], [true, false], aliceIdentity.address), + agentManager.connect(aliceWallet).callBatchSetAddressFrozen([aliceIdentity.target, bobWallet.address], [true, false], aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT Freezer'); }); }); @@ -487,12 +485,12 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); await expect( agentManager .connect(anotherWallet) - .callBatchSetAddressFrozen([aliceIdentity.address, bobWallet.address], [true, false], aliceIdentity.address), + .callBatchSetAddressFrozen([aliceIdentity.target, bobWallet.address], [true, false], aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT Freezer'); }); }); @@ -505,14 +503,14 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); const pauseTx = await agentManager .connect(aliceWallet) - .callBatchSetAddressFrozen([aliceWallet.address, bobWallet.address], [true, false], aliceIdentity.address); + .callBatchSetAddressFrozen([aliceWallet.address, bobWallet.address], [true, false], aliceIdentity.target); - await expect(pauseTx).to.emit(token, 'AddressFrozen').withArgs(aliceWallet.address, true, agentManager.address); - await expect(pauseTx).to.emit(token, 'AddressFrozen').withArgs(bobWallet.address, false, agentManager.address); + await expect(pauseTx).to.emit(token, 'AddressFrozen').withArgs(aliceWallet.address, true, agentManager.target); + await expect(pauseTx).to.emit(token, 'AddressFrozen').withArgs(bobWallet.address, false, agentManager.target); }); }); }); @@ -526,7 +524,7 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callFreezePartialTokens(aliceIdentity.address, 100, aliceIdentity.address)).to.be.revertedWith( + await expect(agentManager.connect(aliceWallet).callFreezePartialTokens(aliceIdentity.target, 100, aliceIdentity.target)).to.be.revertedWith( 'Role: Sender is NOT Freezer', ); }); @@ -540,11 +538,11 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - await expect( - agentManager.connect(anotherWallet).callFreezePartialTokens(aliceIdentity.address, 100, aliceIdentity.address), - ).to.be.revertedWith('Role: Sender is NOT Freezer'); + await expect(agentManager.connect(anotherWallet).callFreezePartialTokens(aliceIdentity.target, 100, aliceIdentity.target)).to.be.revertedWith( + 'Role: Sender is NOT Freezer', + ); }); }); @@ -556,9 +554,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - const freezeTx = await agentManager.connect(aliceWallet).callFreezePartialTokens(aliceWallet.address, 100, aliceIdentity.address); + const freezeTx = await agentManager.connect(aliceWallet).callFreezePartialTokens(aliceWallet.address, 100, aliceIdentity.target); await expect(freezeTx).to.emit(token, 'TokensFrozen').withArgs(aliceWallet.address, 100); }); @@ -575,7 +573,7 @@ describe('AgentManager', () => { } = await loadFixture(deployFullSuiteFixture); await expect( - agentManager.connect(aliceWallet).callBatchFreezePartialTokens([aliceWallet.address, bobWallet.address], [100, 200], aliceIdentity.address), + agentManager.connect(aliceWallet).callBatchFreezePartialTokens([aliceWallet.address, bobWallet.address], [100, 200], aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT Freezer'); }); }); @@ -588,12 +586,12 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); await expect( agentManager .connect(anotherWallet) - .callBatchFreezePartialTokens([aliceWallet.address, bobWallet.address], [100, 200], aliceIdentity.address), + .callBatchFreezePartialTokens([aliceWallet.address, bobWallet.address], [100, 200], aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT Freezer'); }); }); @@ -606,11 +604,11 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); const freezeTx = await agentManager .connect(aliceWallet) - .callBatchFreezePartialTokens([aliceWallet.address, bobWallet.address], [100, 200], aliceIdentity.address); + .callBatchFreezePartialTokens([aliceWallet.address, bobWallet.address], [100, 200], aliceIdentity.target); await expect(freezeTx).to.emit(token, 'TokensFrozen').withArgs(aliceWallet.address, 100); await expect(freezeTx).to.emit(token, 'TokensFrozen').withArgs(bobWallet.address, 200); @@ -627,9 +625,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect( - agentManager.connect(aliceWallet).callUnfreezePartialTokens(aliceIdentity.address, 100, aliceIdentity.address), - ).to.be.revertedWith('Role: Sender is NOT Freezer'); + await expect(agentManager.connect(aliceWallet).callUnfreezePartialTokens(aliceIdentity.target, 100, aliceIdentity.target)).to.be.revertedWith( + 'Role: Sender is NOT Freezer', + ); }); }); @@ -641,10 +639,10 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); await expect( - agentManager.connect(anotherWallet).callUnfreezePartialTokens(aliceIdentity.address, 100, aliceIdentity.address), + agentManager.connect(anotherWallet).callUnfreezePartialTokens(aliceIdentity.target, 100, aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT Freezer'); }); }); @@ -657,11 +655,11 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - await agentManager.connect(aliceWallet).callFreezePartialTokens(aliceWallet.address, 100, aliceIdentity.address); + await agentManager.connect(aliceWallet).callFreezePartialTokens(aliceWallet.address, 100, aliceIdentity.target); - const freezeTx = await agentManager.connect(aliceWallet).callUnfreezePartialTokens(aliceWallet.address, 100, aliceIdentity.address); + const freezeTx = await agentManager.connect(aliceWallet).callUnfreezePartialTokens(aliceWallet.address, 100, aliceIdentity.target); await expect(freezeTx).to.emit(token, 'TokensUnfrozen').withArgs(aliceWallet.address, 100); }); @@ -680,7 +678,7 @@ describe('AgentManager', () => { await expect( agentManager .connect(aliceWallet) - .callBatchUnfreezePartialTokens([aliceWallet.address, bobWallet.address], [100, 200], aliceIdentity.address), + .callBatchUnfreezePartialTokens([aliceWallet.address, bobWallet.address], [100, 200], aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT Freezer'); }); }); @@ -693,12 +691,12 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); await expect( agentManager .connect(anotherWallet) - .callBatchUnfreezePartialTokens([aliceWallet.address, bobWallet.address], [100, 200], aliceIdentity.address), + .callBatchUnfreezePartialTokens([aliceWallet.address, bobWallet.address], [100, 200], aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT Freezer'); }); }); @@ -711,14 +709,14 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - await agentManager.connect(aliceWallet).callFreezePartialTokens(aliceWallet.address, 100, aliceIdentity.address); - await agentManager.connect(aliceWallet).callFreezePartialTokens(bobWallet.address, 200, aliceIdentity.address); + await agentManager.connect(aliceWallet).callFreezePartialTokens(aliceWallet.address, 100, aliceIdentity.target); + await agentManager.connect(aliceWallet).callFreezePartialTokens(bobWallet.address, 200, aliceIdentity.target); const freezeTx = await agentManager .connect(aliceWallet) - .callBatchUnfreezePartialTokens([aliceWallet.address, bobWallet.address], [100, 200], aliceIdentity.address); + .callBatchUnfreezePartialTokens([aliceWallet.address, bobWallet.address], [100, 200], aliceIdentity.target); await expect(freezeTx).to.emit(token, 'TokensUnfrozen').withArgs(aliceWallet.address, 100); }); @@ -735,7 +733,7 @@ describe('AgentManager', () => { } = await loadFixture(deployFullSuiteFixture); await expect( - agentManager.connect(aliceWallet).callRecoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.address, aliceIdentity.address), + agentManager.connect(aliceWallet).callRecoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target, aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT Recovery Agent'); }); }); @@ -748,35 +746,32 @@ describe('AgentManager', () => { identities: { aliceIdentity, bobIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addRecoveryAgent(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addRecoveryAgent(aliceIdentity.target); await expect( - agentManager - .connect(anotherWallet) - .callRecoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.address, aliceIdentity.address), + agentManager.connect(anotherWallet).callRecoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target, aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT Recovery Agent'); }); }); describe('when identity has the RecoveryAgent role and the sender is authorized for it', () => { it('Should perform the recovery of the address', async () => { + const abiCoder = new ethers.AbiCoder(); const { suite: { agentManager, token }, accounts: { tokenAdmin, aliceWallet, bobWallet, anotherWallet }, identities: { aliceIdentity, bobIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addRecoveryAgent(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addRecoveryAgent(aliceIdentity.target); - await bobIdentity - .connect(bobWallet) - .addKey(ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['address'], [anotherWallet.address])), 1, 1); + await bobIdentity.connect(bobWallet).addKey(ethers.keccak256(abiCoder.encode(['address'], [anotherWallet.address])), 1, 1); const recoveryTx = await agentManager .connect(aliceWallet) - .callRecoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.address, aliceIdentity.address); + .callRecoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target, aliceIdentity.target); - await expect(recoveryTx).to.emit(token, 'RecoverySuccess').withArgs(bobWallet.address, anotherWallet.address, bobIdentity.address); + await expect(recoveryTx).to.emit(token, 'RecoverySuccess').withArgs(bobWallet.address, anotherWallet.address, bobIdentity.target); }); }); }); @@ -791,7 +786,7 @@ describe('AgentManager', () => { } = await loadFixture(deployFullSuiteFixture); await expect( - agentManager.connect(aliceWallet).callRegisterIdentity(bobWallet.address, bobIdentity.address, 42, aliceIdentity.address), + agentManager.connect(aliceWallet).callRegisterIdentity(bobWallet.address, bobIdentity.target, 42, aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT WhiteList Manager'); }); }); @@ -804,10 +799,10 @@ describe('AgentManager', () => { identities: { aliceIdentity, bobIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.target); await expect( - agentManager.connect(bobWallet).callRegisterIdentity(bobWallet.address, bobIdentity.address, 42, aliceIdentity.address), + agentManager.connect(bobWallet).callRegisterIdentity(bobWallet.address, bobIdentity.target, 42, aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT WhiteList Manager'); }); }); @@ -820,13 +815,13 @@ describe('AgentManager', () => { identities: { aliceIdentity, charlieIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.target); const registerTx = await agentManager .connect(aliceWallet) - .callRegisterIdentity(charlieWallet.address, charlieIdentity.address, 42, aliceIdentity.address); + .callRegisterIdentity(charlieWallet.address, charlieIdentity.target, 42, aliceIdentity.target); - await expect(registerTx).to.emit(identityRegistry, 'IdentityRegistered').withArgs(charlieWallet.address, charlieIdentity.address); + await expect(registerTx).to.emit(identityRegistry, 'IdentityRegistered').withArgs(charlieWallet.address, charlieIdentity.target); await expect(identityRegistry.contains(charlieWallet.address)).to.eventually.be.true; }); @@ -843,7 +838,7 @@ describe('AgentManager', () => { } = await loadFixture(deployFullSuiteFixture); await expect( - agentManager.connect(aliceWallet).callUpdateIdentity(bobWallet.address, bobIdentity.address, aliceIdentity.address), + agentManager.connect(aliceWallet).callUpdateIdentity(bobWallet.address, bobIdentity.target, aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT WhiteList Manager'); }); }); @@ -856,10 +851,10 @@ describe('AgentManager', () => { identities: { aliceIdentity, bobIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.target); await expect( - agentManager.connect(bobWallet).callUpdateIdentity(bobWallet.address, bobIdentity.address, aliceIdentity.address), + agentManager.connect(bobWallet).callUpdateIdentity(bobWallet.address, bobIdentity.target, aliceIdentity.target), ).to.be.revertedWith('Role: Sender is NOT WhiteList Manager'); }); }); @@ -872,13 +867,11 @@ describe('AgentManager', () => { identities: { aliceIdentity, bobIdentity, charlieIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.target); - const updateTx = await agentManager - .connect(aliceWallet) - .callUpdateIdentity(bobWallet.address, charlieIdentity.address, aliceIdentity.address); + const updateTx = await agentManager.connect(aliceWallet).callUpdateIdentity(bobWallet.address, charlieIdentity.target, aliceIdentity.target); - await expect(updateTx).to.emit(identityRegistry, 'IdentityUpdated').withArgs(bobIdentity.address, charlieIdentity.address); + await expect(updateTx).to.emit(identityRegistry, 'IdentityUpdated').withArgs(bobIdentity.target, charlieIdentity.target); }); }); }); @@ -892,7 +885,7 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callUpdateCountry(bobWallet.address, 100, aliceIdentity.address)).to.be.revertedWith( + await expect(agentManager.connect(aliceWallet).callUpdateCountry(bobWallet.address, 100, aliceIdentity.target)).to.be.revertedWith( 'Role: Sender is NOT WhiteList Manager', ); }); @@ -906,9 +899,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.target); - await expect(agentManager.connect(bobWallet).callUpdateCountry(bobWallet.address, 100, aliceIdentity.address)).to.be.revertedWith( + await expect(agentManager.connect(bobWallet).callUpdateCountry(bobWallet.address, 100, aliceIdentity.target)).to.be.revertedWith( 'Role: Sender is NOT WhiteList Manager', ); }); @@ -922,9 +915,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.target); - const updateTx = await agentManager.connect(aliceWallet).callUpdateCountry(bobWallet.address, 100, aliceIdentity.address); + const updateTx = await agentManager.connect(aliceWallet).callUpdateCountry(bobWallet.address, 100, aliceIdentity.target); await expect(updateTx).to.emit(identityRegistry, 'CountryUpdated').withArgs(bobWallet.address, 100); }); @@ -940,7 +933,7 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callDeleteIdentity(bobWallet.address, aliceIdentity.address)).to.be.revertedWith( + await expect(agentManager.connect(aliceWallet).callDeleteIdentity(bobWallet.address, aliceIdentity.target)).to.be.revertedWith( 'Role: Sender is NOT WhiteList Manager', ); }); @@ -954,9 +947,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.target); - await expect(agentManager.connect(bobWallet).callDeleteIdentity(bobWallet.address, aliceIdentity.address)).to.be.revertedWith( + await expect(agentManager.connect(bobWallet).callDeleteIdentity(bobWallet.address, aliceIdentity.target)).to.be.revertedWith( 'Role: Sender is NOT WhiteList Manager', ); }); @@ -970,11 +963,11 @@ describe('AgentManager', () => { identities: { aliceIdentity, bobIdentity }, } = await loadFixture(deployFullSuiteFixture); - await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.address); + await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.target); - const deleteTx = await agentManager.connect(aliceWallet).callDeleteIdentity(bobWallet.address, aliceIdentity.address); + const deleteTx = await agentManager.connect(aliceWallet).callDeleteIdentity(bobWallet.address, aliceIdentity.target); - await expect(deleteTx).to.emit(identityRegistry, 'IdentityRemoved').withArgs(bobWallet.address, bobIdentity.address); + await expect(deleteTx).to.emit(identityRegistry, 'IdentityRemoved').withArgs(bobWallet.address, bobIdentity.target); await expect(identityRegistry.contains(bobWallet.address)).to.eventually.be.false; }); diff --git a/test/agentRole.test.ts b/test/agentRole.test.ts index 00d15e72..b1dc465d 100644 --- a/test/agentRole.test.ts +++ b/test/agentRole.test.ts @@ -40,7 +40,7 @@ describe('AgentRole', () => { contracts: { agentRole }, } = await loadFixture(deployAgentFixture); - await expect(agentRole.connect(ownerWallet).addAgent(ethers.constants.AddressZero)).to.be.revertedWith('invalid argument - zero address'); + await expect(agentRole.connect(ownerWallet).addAgent(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); }); }); @@ -93,9 +93,7 @@ describe('AgentRole', () => { contracts: { agentRole }, } = await loadFixture(deployAgentFixture); - await expect(agentRole.connect(ownerWallet).removeAgent(ethers.constants.AddressZero)).to.be.revertedWith( - 'invalid argument - zero address', - ); + await expect(agentRole.connect(ownerWallet).removeAgent(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); }); }); diff --git a/test/authorities/trex-implementation-authority.test.ts b/test/authorities/trex-implementation-authority.test.ts index fbf4c973..cb5dc35b 100644 --- a/test/authorities/trex-implementation-authority.test.ts +++ b/test/authorities/trex-implementation-authority.test.ts @@ -13,7 +13,7 @@ describe('TrexImplementationAuthority', () => { accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(trexImplementationAuthority.connect(anotherWallet).setTREXFactory(ethers.constants.AddressZero)).to.be.revertedWith( + await expect(trexImplementationAuthority.connect(anotherWallet).setTREXFactory(ethers.ZeroAddress)).to.be.revertedWith( 'Ownable: caller is not the owner', ); }); @@ -32,7 +32,7 @@ describe('TrexImplementationAuthority', () => { const otherTrexImplementationAuthority = await ethers.deployContract( 'TREXImplementationAuthority', - [true, ethers.constants.AddressZero, ethers.constants.AddressZero], + [true, ethers.ZeroAddress, ethers.ZeroAddress], deployer, ); const versionStruct = { @@ -41,22 +41,22 @@ describe('TrexImplementationAuthority', () => { patch: 0, }; const contractsStruct = { - tokenImplementation: implementations.tokenImplementation.address, - ctrImplementation: implementations.claimTopicsRegistryImplementation.address, - irImplementation: implementations.identityRegistryImplementation.address, - irsImplementation: implementations.identityRegistryStorageImplementation.address, - tirImplementation: implementations.trustedIssuersRegistryImplementation.address, - mcImplementation: implementations.modularComplianceImplementation.address, + tokenImplementation: implementations.tokenImplementation.target, + ctrImplementation: implementations.claimTopicsRegistryImplementation.target, + irImplementation: implementations.identityRegistryImplementation.target, + irsImplementation: implementations.identityRegistryStorageImplementation.target, + tirImplementation: implementations.trustedIssuersRegistryImplementation.target, + mcImplementation: implementations.modularComplianceImplementation.target, }; await otherTrexImplementationAuthority.connect(deployer).addAndUseTREXVersion(versionStruct, contractsStruct); const trexFactory = await ethers.deployContract( 'TREXFactory', - [otherTrexImplementationAuthority.address, identityFactory.address], + [otherTrexImplementationAuthority.target, identityFactory.target], deployer, ); - await expect(trexImplementationAuthority.setTREXFactory(trexFactory.address)).to.be.revertedWith('only reference contract can call'); + await expect(trexImplementationAuthority.setTREXFactory(trexFactory.target)).to.be.revertedWith('only reference contract can call'); }); }); @@ -68,11 +68,11 @@ describe('TrexImplementationAuthority', () => { factories: { identityFactory }, } = await loadFixture(deployFullSuiteFixture); - const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.address, identityFactory.address], deployer); + const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.target, identityFactory.target], deployer); - const tx = await trexImplementationAuthority.setTREXFactory(trexFactory.address); - await expect(tx).to.emit(trexImplementationAuthority, 'TREXFactorySet').withArgs(trexFactory.address); - await expect(trexImplementationAuthority.getTREXFactory()).to.eventually.equal(trexFactory.address); + const tx = await trexImplementationAuthority.setTREXFactory(trexFactory.target); + await expect(tx).to.emit(trexImplementationAuthority, 'TREXFactorySet').withArgs(trexFactory.target); + await expect(trexImplementationAuthority.getTREXFactory()).to.eventually.equal(trexFactory.target); }); }); }); @@ -87,7 +87,7 @@ describe('TrexImplementationAuthority', () => { accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(trexImplementationAuthority.connect(anotherWallet).setIAFactory(ethers.constants.AddressZero)).to.be.revertedWith( + await expect(trexImplementationAuthority.connect(anotherWallet).setIAFactory(ethers.ZeroAddress)).to.be.revertedWith( 'Ownable: caller is not the owner', ); }); @@ -103,17 +103,17 @@ describe('TrexImplementationAuthority', () => { factories: { identityFactory }, } = await loadFixture(deployFullSuiteFixture); - const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.address, identityFactory.address], deployer); - await trexImplementationAuthority.setTREXFactory(trexFactory.address); + const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.target, identityFactory.target], deployer); + await trexImplementationAuthority.setTREXFactory(trexFactory.target); const implementationAuthorityFactory = await ethers.deployContract( 'TREXImplementationAuthority', - [true, ethers.constants.AddressZero, ethers.constants.AddressZero], + [true, ethers.ZeroAddress, ethers.ZeroAddress], deployer, ); - const tx = await trexImplementationAuthority.setIAFactory(implementationAuthorityFactory.address); - await expect(tx).to.emit(trexImplementationAuthority, 'IAFactorySet').withArgs(implementationAuthorityFactory.address); + const tx = await trexImplementationAuthority.setIAFactory(implementationAuthorityFactory.target); + await expect(tx).to.emit(trexImplementationAuthority, 'IAFactorySet').withArgs(implementationAuthorityFactory.target); }); }); }); @@ -145,11 +145,11 @@ describe('TrexImplementationAuthority', () => { factories: { identityFactory }, } = await loadFixture(deployFullSuiteFixture); - const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.address, identityFactory.address], deployer); + const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.target, identityFactory.target], deployer); const otherTrexImplementationAuthority = await ethers.deployContract( 'TREXImplementationAuthority', - [false, trexFactory.address, trexImplementationAuthority.address], + [false, trexFactory.target, trexImplementationAuthority.target], deployer, ); @@ -173,11 +173,11 @@ describe('TrexImplementationAuthority', () => { factories: { identityFactory }, } = await loadFixture(deployFullSuiteFixture); - const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.address, identityFactory.address], deployer); + const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.target, identityFactory.target], deployer); const otherTrexImplementationAuthority = await ethers.deployContract( 'TREXImplementationAuthority', - [false, trexFactory.address, trexImplementationAuthority.address], + [false, trexFactory.target, trexImplementationAuthority.target], deployer, ); @@ -208,12 +208,12 @@ describe('TrexImplementationAuthority', () => { patch: 1, }; const contractsStruct = { - tokenImplementation: implementations.tokenImplementation.address, - ctrImplementation: implementations.claimTopicsRegistryImplementation.address, - irImplementation: implementations.identityRegistryImplementation.address, - irsImplementation: ethers.constants.AddressZero, - tirImplementation: implementations.trustedIssuersRegistryImplementation.address, - mcImplementation: implementations.modularComplianceImplementation.address, + tokenImplementation: implementations.tokenImplementation.target, + ctrImplementation: implementations.claimTopicsRegistryImplementation.target, + irImplementation: implementations.identityRegistryImplementation.target, + irsImplementation: ethers.ZeroAddress, + tirImplementation: implementations.trustedIssuersRegistryImplementation.target, + mcImplementation: implementations.modularComplianceImplementation.target, }; await expect(trexImplementationAuthority.connect(anotherWallet).addTREXVersion(versionStruct, contractsStruct)).to.be.revertedWith( @@ -232,11 +232,11 @@ describe('TrexImplementationAuthority', () => { implementations, } = await loadFixture(deployFullSuiteFixture); - const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.address, identityFactory.address], deployer); + const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.target, identityFactory.target], deployer); const otherTrexImplementationAuthority = await ethers.deployContract( 'TREXImplementationAuthority', - [false, trexFactory.address, trexImplementationAuthority.address], + [false, trexFactory.target, trexImplementationAuthority.target], deployer, ); @@ -246,12 +246,12 @@ describe('TrexImplementationAuthority', () => { patch: 0, }; const contractsStruct = { - tokenImplementation: implementations.tokenImplementation.address, - ctrImplementation: implementations.claimTopicsRegistryImplementation.address, - irImplementation: implementations.identityRegistryImplementation.address, - irsImplementation: implementations.identityRegistryStorageImplementation.address, - tirImplementation: implementations.trustedIssuersRegistryImplementation.address, - mcImplementation: implementations.modularComplianceImplementation.address, + tokenImplementation: implementations.tokenImplementation.target, + ctrImplementation: implementations.claimTopicsRegistryImplementation.target, + irImplementation: implementations.identityRegistryImplementation.target, + irsImplementation: implementations.identityRegistryStorageImplementation.target, + tirImplementation: implementations.trustedIssuersRegistryImplementation.target, + mcImplementation: implementations.modularComplianceImplementation.target, }; await expect(otherTrexImplementationAuthority.addTREXVersion(versionStruct, contractsStruct)).to.be.revertedWith( @@ -274,12 +274,12 @@ describe('TrexImplementationAuthority', () => { patch: 0, }; const contractsStruct = { - tokenImplementation: implementations.tokenImplementation.address, - ctrImplementation: implementations.claimTopicsRegistryImplementation.address, - irImplementation: implementations.identityRegistryImplementation.address, - irsImplementation: implementations.identityRegistryStorageImplementation.address, - tirImplementation: implementations.trustedIssuersRegistryImplementation.address, - mcImplementation: implementations.modularComplianceImplementation.address, + tokenImplementation: implementations.tokenImplementation.target, + ctrImplementation: implementations.claimTopicsRegistryImplementation.target, + irImplementation: implementations.identityRegistryImplementation.target, + irsImplementation: implementations.identityRegistryStorageImplementation.target, + tirImplementation: implementations.trustedIssuersRegistryImplementation.target, + mcImplementation: implementations.modularComplianceImplementation.target, }; await expect(trexImplementationAuthority.addTREXVersion(versionStruct, contractsStruct)).to.be.revertedWith('version already exists'); @@ -299,12 +299,12 @@ describe('TrexImplementationAuthority', () => { patch: 1, }; const contractsStruct = { - tokenImplementation: implementations.tokenImplementation.address, - ctrImplementation: implementations.claimTopicsRegistryImplementation.address, - irImplementation: implementations.identityRegistryImplementation.address, - irsImplementation: ethers.constants.AddressZero, - tirImplementation: implementations.trustedIssuersRegistryImplementation.address, - mcImplementation: implementations.modularComplianceImplementation.address, + tokenImplementation: implementations.tokenImplementation.target, + ctrImplementation: implementations.claimTopicsRegistryImplementation.target, + irImplementation: implementations.identityRegistryImplementation.target, + irsImplementation: ethers.ZeroAddress, + tirImplementation: implementations.trustedIssuersRegistryImplementation.target, + mcImplementation: implementations.modularComplianceImplementation.target, }; await expect(trexImplementationAuthority.addTREXVersion(versionStruct, contractsStruct)).to.be.revertedWith( @@ -379,9 +379,9 @@ describe('TrexImplementationAuthority', () => { authorities: { trexImplementationAuthority }, } = await loadFixture(deployFullSuiteFixture); - await expect( - trexImplementationAuthority.changeImplementationAuthority(ethers.constants.AddressZero, anotherWallet.address), - ).to.be.revertedWith('invalid argument - zero address'); + await expect(trexImplementationAuthority.changeImplementationAuthority(ethers.ZeroAddress, anotherWallet.address)).to.be.revertedWith( + 'invalid argument - zero address', + ); }); }); @@ -395,17 +395,17 @@ describe('TrexImplementationAuthority', () => { suite: { token }, } = await loadFixture(deployFullSuiteFixture); - const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.address, identityFactory.address], deployer); + const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.target, identityFactory.target], deployer); const otherTrexImplementationAuthority = await ethers.deployContract( 'TREXImplementationAuthority', - [false, trexFactory.address, trexImplementationAuthority.address], + [false, trexFactory.target, trexImplementationAuthority.target], deployer, ); - await expect( - otherTrexImplementationAuthority.changeImplementationAuthority(token.address, ethers.constants.AddressZero), - ).to.be.revertedWith('only reference contract can deploy new IAs'); + await expect(otherTrexImplementationAuthority.changeImplementationAuthority(token.target, ethers.ZeroAddress)).to.be.revertedWith( + 'only reference contract can deploy new IAs', + ); }); }); @@ -419,7 +419,7 @@ describe('TrexImplementationAuthority', () => { } = await loadFixture(deployFullSuiteFixture); await expect( - trexImplementationAuthority.connect(anotherWallet).changeImplementationAuthority(token.address, ethers.constants.AddressZero), + trexImplementationAuthority.connect(anotherWallet).changeImplementationAuthority(token.target, ethers.ZeroAddress), ).to.be.revertedWith('caller NOT owner of all contracts impacted'); }); }); @@ -433,16 +433,16 @@ describe('TrexImplementationAuthority', () => { suite: { token }, } = await loadFixture(deployFullSuiteFixture); - const compliance = await ethers.deployContract('ModularComplianceProxy', [trexImplementationAuthority.address], deployer); - await token.setCompliance(compliance.address); + const compliance = await ethers.deployContract('ModularComplianceProxy', [trexImplementationAuthority.target], deployer); + await token.setCompliance(compliance.target); - const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.address, identityFactory.address], deployer); + const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.target, identityFactory.target], deployer); - const implementationAuthorityFactory = await ethers.deployContract('IAFactory', [trexFactory.address], deployer); - await trexImplementationAuthority.setTREXFactory(trexFactory.address); - await trexImplementationAuthority.setIAFactory(implementationAuthorityFactory.address); + const implementationAuthorityFactory = await ethers.deployContract('IAFactory', [trexFactory.target], deployer); + await trexImplementationAuthority.setTREXFactory(trexFactory.target); + await trexImplementationAuthority.setIAFactory(implementationAuthorityFactory.target); - const tx = await trexImplementationAuthority.changeImplementationAuthority(token.address, ethers.constants.AddressZero); + const tx = await trexImplementationAuthority.changeImplementationAuthority(token.target, ethers.ZeroAddress); expect(tx).to.emit(trexImplementationAuthority, 'ImplementationAuthorityChanged'); }); }); @@ -461,34 +461,34 @@ describe('TrexImplementationAuthority', () => { implementations, } = await loadFixture(deployFullSuiteFixture); - const compliance = await ethers.deployContract('ModularComplianceProxy', [trexImplementationAuthority.address], deployer); - await token.setCompliance(compliance.address); + const compliance = await ethers.deployContract('ModularComplianceProxy', [trexImplementationAuthority.target], deployer); + await token.setCompliance(compliance.target); - const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.address, identityFactory.address], deployer); + const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.target, identityFactory.target], deployer); - const implementationAuthorityFactory = await ethers.deployContract('IAFactory', [trexFactory.address], deployer); - await trexImplementationAuthority.setTREXFactory(trexFactory.address); - await trexImplementationAuthority.setIAFactory(implementationAuthorityFactory.address); + const implementationAuthorityFactory = await ethers.deployContract('IAFactory', [trexFactory.target], deployer); + await trexImplementationAuthority.setTREXFactory(trexFactory.target); + await trexImplementationAuthority.setIAFactory(implementationAuthorityFactory.target); const otherTrexImplementationAuthority = await ethers.deployContract( 'TREXImplementationAuthority', - [true, trexFactory.address, trexImplementationAuthority.address], + [true, trexFactory.target, trexImplementationAuthority.target], deployer, ); await otherTrexImplementationAuthority.addAndUseTREXVersion( { major: 4, minor: 0, patch: 1 }, { - tokenImplementation: implementations.tokenImplementation.address, - ctrImplementation: implementations.claimTopicsRegistryImplementation.address, - irImplementation: implementations.identityRegistryImplementation.address, - irsImplementation: implementations.identityRegistryStorageImplementation.address, - tirImplementation: implementations.trustedIssuersRegistryImplementation.address, - mcImplementation: implementations.modularComplianceImplementation.address, + tokenImplementation: implementations.tokenImplementation.target, + ctrImplementation: implementations.claimTopicsRegistryImplementation.target, + irImplementation: implementations.identityRegistryImplementation.target, + irsImplementation: implementations.identityRegistryStorageImplementation.target, + tirImplementation: implementations.trustedIssuersRegistryImplementation.target, + mcImplementation: implementations.modularComplianceImplementation.target, }, ); await expect( - trexImplementationAuthority.changeImplementationAuthority(token.address, otherTrexImplementationAuthority.address), + trexImplementationAuthority.changeImplementationAuthority(token.target, otherTrexImplementationAuthority.target), ).to.be.revertedWith('version of new IA has to be the same as current IA'); }); }); @@ -503,34 +503,34 @@ describe('TrexImplementationAuthority', () => { implementations, } = await loadFixture(deployFullSuiteFixture); - const compliance = await ethers.deployContract('ModularComplianceProxy', [trexImplementationAuthority.address], deployer); - await token.setCompliance(compliance.address); + const compliance = await ethers.deployContract('ModularComplianceProxy', [trexImplementationAuthority.target], deployer); + await token.setCompliance(compliance.target); - const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.address, identityFactory.address], deployer); + const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.target, identityFactory.target], deployer); - const implementationAuthorityFactory = await ethers.deployContract('IAFactory', [trexFactory.address], deployer); - await trexImplementationAuthority.setTREXFactory(trexFactory.address); - await trexImplementationAuthority.setIAFactory(implementationAuthorityFactory.address); + const implementationAuthorityFactory = await ethers.deployContract('IAFactory', [trexFactory.target], deployer); + await trexImplementationAuthority.setTREXFactory(trexFactory.target); + await trexImplementationAuthority.setIAFactory(implementationAuthorityFactory.target); const otherTrexImplementationAuthority = await ethers.deployContract( 'TREXImplementationAuthority', - [true, trexFactory.address, trexImplementationAuthority.address], + [true, trexFactory.target, trexImplementationAuthority.target], deployer, ); await otherTrexImplementationAuthority.addAndUseTREXVersion( { major: 4, minor: 0, patch: 0 }, { - tokenImplementation: implementations.tokenImplementation.address, - ctrImplementation: implementations.claimTopicsRegistryImplementation.address, - irImplementation: implementations.identityRegistryImplementation.address, - irsImplementation: implementations.identityRegistryStorageImplementation.address, - tirImplementation: implementations.trustedIssuersRegistryImplementation.address, - mcImplementation: implementations.modularComplianceImplementation.address, + tokenImplementation: implementations.tokenImplementation.target, + ctrImplementation: implementations.claimTopicsRegistryImplementation.target, + irImplementation: implementations.identityRegistryImplementation.target, + irsImplementation: implementations.identityRegistryStorageImplementation.target, + tirImplementation: implementations.trustedIssuersRegistryImplementation.target, + mcImplementation: implementations.modularComplianceImplementation.target, }, ); await expect( - trexImplementationAuthority.changeImplementationAuthority(token.address, otherTrexImplementationAuthority.address), + trexImplementationAuthority.changeImplementationAuthority(token.target, otherTrexImplementationAuthority.target), ).to.be.revertedWith('new IA is NOT reference contract'); }); }); @@ -544,25 +544,25 @@ describe('TrexImplementationAuthority', () => { suite: { token }, } = await loadFixture(deployFullSuiteFixture); - const compliance = await ethers.deployContract('ModularComplianceProxy', [trexImplementationAuthority.address], deployer); - await token.setCompliance(compliance.address); + const compliance = await ethers.deployContract('ModularComplianceProxy', [trexImplementationAuthority.target], deployer); + await token.setCompliance(compliance.target); - const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.address, identityFactory.address], deployer); + const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.target, identityFactory.target], deployer); - const implementationAuthorityFactory = await ethers.deployContract('IAFactory', [trexFactory.address], deployer); - await trexImplementationAuthority.setTREXFactory(trexFactory.address); - await trexImplementationAuthority.setIAFactory(implementationAuthorityFactory.address); + const implementationAuthorityFactory = await ethers.deployContract('IAFactory', [trexFactory.target], deployer); + await trexImplementationAuthority.setTREXFactory(trexFactory.target); + await trexImplementationAuthority.setIAFactory(implementationAuthorityFactory.target); const otherTrexImplementationAuthority = await ethers.deployContract( 'TREXImplementationAuthority', - [false, trexFactory.address, trexImplementationAuthority.address], + [false, trexFactory.target, trexImplementationAuthority.target], deployer, ); await otherTrexImplementationAuthority.fetchVersion({ major: 4, minor: 0, patch: 0 }); await otherTrexImplementationAuthority.useTREXVersion({ major: 4, minor: 0, patch: 0 }); await expect( - trexImplementationAuthority.changeImplementationAuthority(token.address, otherTrexImplementationAuthority.address), + trexImplementationAuthority.changeImplementationAuthority(token.target, otherTrexImplementationAuthority.target), ).to.be.revertedWith('invalid IA'); }); }); diff --git a/test/compliance.test.ts b/test/compliance.test.ts index 8814aadb..fef5f9a5 100644 --- a/test/compliance.test.ts +++ b/test/compliance.test.ts @@ -26,7 +26,7 @@ describe('ModularCompliance', () => { suite: { token, compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.connect(anotherWallet).bindToken(token.address)).to.be.revertedWith('only owner or token can call'); + await expect(compliance.connect(anotherWallet).bindToken(token.target)).to.be.revertedWith('only owner or token can call'); }); }); @@ -41,9 +41,9 @@ describe('ModularCompliance', () => { const compliance = await ethers.deployContract('ModularCompliance', deployer); await compliance.init(); - await compliance.bindToken(token.address); + await compliance.bindToken(token.target); - await expect(compliance.connect(anotherWallet).bindToken(token.address)).to.be.revertedWith('only owner or token can call'); + await expect(compliance.connect(anotherWallet).bindToken(token.target)).to.be.revertedWith('only owner or token can call'); }); }); @@ -55,13 +55,13 @@ describe('ModularCompliance', () => { const compliance = await ethers.deployContract('ModularCompliance'); await compliance.init(); - await compliance.bindToken(token.address); + await compliance.bindToken(token.target); const newCompliance = await ethers.deployContract('ModularCompliance'); - const tx = await token.setCompliance(newCompliance.address); - await expect(tx).to.emit(token, 'ComplianceAdded').withArgs(newCompliance.address); - await expect(tx).to.emit(newCompliance, 'TokenBound').withArgs(token.address); + const tx = await token.setCompliance(newCompliance.target); + await expect(tx).to.emit(token, 'ComplianceAdded').withArgs(newCompliance.target); + await expect(tx).to.emit(newCompliance, 'TokenBound').withArgs(token.target); }); }); }); @@ -76,7 +76,7 @@ describe('ModularCompliance', () => { const compliance = await ethers.deployContract('ModularCompliance', deployer); await compliance.init(); - await expect(compliance.bindToken(ethers.constants.AddressZero)).to.be.revertedWith('invalid argument - zero address'); + await expect(compliance.bindToken(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); }); }); }); @@ -90,7 +90,7 @@ describe('ModularCompliance', () => { suite: { token, compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.connect(anotherWallet).unbindToken(token.address)).to.be.revertedWith('only owner or token can call'); + await expect(compliance.connect(anotherWallet).unbindToken(token.target)).to.be.revertedWith('only owner or token can call'); }); }); @@ -101,7 +101,7 @@ describe('ModularCompliance', () => { suite: { compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.unbindToken(ethers.constants.AddressZero)).to.be.revertedWith('invalid argument - zero address'); + await expect(compliance.unbindToken(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); }); }); @@ -115,7 +115,7 @@ describe('ModularCompliance', () => { const compliance = await ethers.deployContract('ModularCompliance', deployer); await compliance.init(); - await expect(compliance.unbindToken(token.address)).to.be.revertedWith('This token is not bound'); + await expect(compliance.unbindToken(token.target)).to.be.revertedWith('This token is not bound'); }); }); }); @@ -126,14 +126,14 @@ describe('ModularCompliance', () => { suite: { compliance, complianceBeta, token }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await token.setCompliance(compliance.address); + await token.setCompliance(compliance.target); - const tx = await token.setCompliance(complianceBeta.address); - await expect(tx).to.emit(token, 'ComplianceAdded').withArgs(complianceBeta.address); - await expect(tx).to.emit(complianceBeta, 'TokenBound').withArgs(token.address); - await expect(tx).to.emit(compliance, 'TokenUnbound').withArgs(token.address); + const tx = await token.setCompliance(complianceBeta.target); + await expect(tx).to.emit(token, 'ComplianceAdded').withArgs(complianceBeta.target); + await expect(tx).to.emit(complianceBeta, 'TokenBound').withArgs(token.target); + await expect(tx).to.emit(compliance, 'TokenUnbound').withArgs(token.target); - await expect(complianceBeta.getTokenBound()).to.eventually.eq(token.address); + await expect(complianceBeta.getTokenBound()).to.eventually.eq(token.target); }); }); }); @@ -146,9 +146,7 @@ describe('ModularCompliance', () => { suite: { compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.connect(anotherWallet).addModule(ethers.constants.AddressZero)).to.be.revertedWith( - 'Ownable: caller is not the owner', - ); + await expect(compliance.connect(anotherWallet).addModule(ethers.ZeroAddress)).to.be.revertedWith('Ownable: caller is not the owner'); }); }); @@ -159,7 +157,7 @@ describe('ModularCompliance', () => { suite: { compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.addModule(ethers.constants.AddressZero)).to.be.revertedWith('invalid argument - zero address'); + await expect(compliance.addModule(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); }); }); @@ -170,9 +168,9 @@ describe('ModularCompliance', () => { } = await loadFixture(deploySuiteWithModularCompliancesFixture); const module = await ethers.deployContract('CountryAllowModule'); - await compliance.addModule(module.address); + await compliance.addModule(module.target); - await expect(compliance.addModule(module.address)).to.be.revertedWith('module already bound'); + await expect(compliance.addModule(module.target)).to.be.revertedWith('module already bound'); }); }); @@ -183,10 +181,10 @@ describe('ModularCompliance', () => { accounts, suite: { compliance, token }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await compliance.connect(accounts.deployer).bindToken(token.address); + await compliance.connect(accounts.deployer).bindToken(token.target); const module = await ethers.deployContract('MaxBalanceModule'); - await expect(compliance.addModule(module.address)).to.be.revertedWith('compliance is not suitable for binding to the module'); + await expect(compliance.addModule(module.target)).to.be.revertedWith('compliance is not suitable for binding to the module'); }); }); @@ -197,15 +195,15 @@ describe('ModularCompliance', () => { suite: { compliance, token }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await compliance.connect(accounts.deployer).bindToken(token.address); + await compliance.connect(accounts.deployer).bindToken(token.target); await token.connect(accounts.tokenAgent).burn(accounts.aliceWallet.address, 1000); await token.connect(accounts.tokenAgent).burn(accounts.bobWallet.address, 500); const module = await ethers.deployContract('MaxBalanceModule'); - const tx = await compliance.addModule(module.address); + const tx = await compliance.addModule(module.target); - await expect(tx).to.emit(compliance, 'ModuleAdded').withArgs(module.address); - await expect(compliance.getModules()).to.eventually.deep.eq([module.address]); + await expect(tx).to.emit(compliance, 'ModuleAdded').withArgs(module.target); + await expect(compliance.getModules()).to.eventually.deep.eq([module.target]); }); }); }); @@ -217,10 +215,10 @@ describe('ModularCompliance', () => { } = await loadFixture(deploySuiteWithModularCompliancesFixture); const module = await ethers.deployContract('CountryAllowModule'); - const tx = await compliance.addModule(module.address); + const tx = await compliance.addModule(module.target); - await expect(tx).to.emit(compliance, 'ModuleAdded').withArgs(module.address); - await expect(compliance.getModules()).to.eventually.deep.eq([module.address]); + await expect(tx).to.emit(compliance, 'ModuleAdded').withArgs(module.target); + await expect(compliance.getModules()).to.eventually.deep.eq([module.target]); }); }); @@ -232,11 +230,11 @@ describe('ModularCompliance', () => { const modules = await Promise.all(Array.from({ length: 25 }, () => ethers.deployContract('CountryAllowModule'))); - await Promise.all(modules.map((module) => compliance.addModule(module.address))); + await Promise.all(modules.map((module) => compliance.addModule(module.target))); const module = await ethers.deployContract('CountryAllowModule'); - await expect(compliance.addModule(module.address)).to.be.revertedWith('cannot add more than 25 modules'); + await expect(compliance.addModule(module.target)).to.be.revertedWith('cannot add more than 25 modules'); }); }); }); @@ -250,9 +248,7 @@ describe('ModularCompliance', () => { suite: { compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.connect(anotherWallet).removeModule(ethers.constants.AddressZero)).to.be.revertedWith( - 'Ownable: caller is not the owner', - ); + await expect(compliance.connect(anotherWallet).removeModule(ethers.ZeroAddress)).to.be.revertedWith('Ownable: caller is not the owner'); }); }); @@ -263,7 +259,7 @@ describe('ModularCompliance', () => { suite: { compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.removeModule(ethers.constants.AddressZero)).to.be.revertedWith('invalid argument - zero address'); + await expect(compliance.removeModule(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); }); }); @@ -275,7 +271,7 @@ describe('ModularCompliance', () => { const module = await ethers.deployContract('CountryAllowModule'); - await expect(compliance.removeModule(module.address)).to.be.revertedWith('module not bound'); + await expect(compliance.removeModule(module.target)).to.be.revertedWith('module not bound'); }); }); @@ -286,16 +282,16 @@ describe('ModularCompliance', () => { } = await loadFixture(deploySuiteWithModularCompliancesFixture); const module = await ethers.deployContract('CountryAllowModule'); - await compliance.addModule(module.address); + await compliance.addModule(module.target); const moduleB = await ethers.deployContract('CountryAllowModule'); - await compliance.addModule(moduleB.address); + await compliance.addModule(moduleB.target); - const tx = await compliance.removeModule(moduleB.address); + const tx = await compliance.removeModule(moduleB.target); - await expect(tx).to.emit(compliance, 'ModuleRemoved').withArgs(moduleB.address); + await expect(tx).to.emit(compliance, 'ModuleRemoved').withArgs(moduleB.target); - await expect(compliance.isModuleBound(moduleB.address)).to.be.eventually.false; + await expect(compliance.isModuleBound(moduleB.target)).to.be.eventually.false; }); }); }); @@ -309,7 +305,7 @@ describe('ModularCompliance', () => { suite: { compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.connect(anotherWallet).transferred(ethers.constants.AddressZero, ethers.constants.AddressZero, 0)).to.be.revertedWith( + await expect(compliance.connect(anotherWallet).transferred(ethers.ZeroAddress, ethers.ZeroAddress, 0)).to.be.revertedWith( 'error : this address is not a token bound to the compliance contract', ); }); @@ -323,7 +319,7 @@ describe('ModularCompliance', () => { accounts: { bobWallet, charlieWallet }, } = await loadFixture(deploySuiteWithModuleComplianceBoundToWallet); - await expect(compliance.connect(charlieWallet).transferred(ethers.constants.AddressZero, bobWallet.address, 10)).to.be.revertedWith( + await expect(compliance.connect(charlieWallet).transferred(ethers.ZeroAddress, bobWallet.address, 10)).to.be.revertedWith( 'invalid argument - zero address', ); }); @@ -336,7 +332,7 @@ describe('ModularCompliance', () => { accounts: { charlieWallet, aliceWallet }, } = await loadFixture(deploySuiteWithModuleComplianceBoundToWallet); - await expect(compliance.connect(charlieWallet).transferred(aliceWallet.address, ethers.constants.AddressZero, 10)).to.be.revertedWith( + await expect(compliance.connect(charlieWallet).transferred(aliceWallet.address, ethers.ZeroAddress, 10)).to.be.revertedWith( 'invalid argument - zero address', ); }); @@ -376,7 +372,7 @@ describe('ModularCompliance', () => { suite: { compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.connect(anotherWallet).created(ethers.constants.AddressZero, 0)).to.be.revertedWith( + await expect(compliance.connect(anotherWallet).created(ethers.ZeroAddress, 0)).to.be.revertedWith( 'error : this address is not a token bound to the compliance contract', ); }); @@ -390,9 +386,7 @@ describe('ModularCompliance', () => { accounts: { charlieWallet }, } = await loadFixture(deploySuiteWithModuleComplianceBoundToWallet); - await expect(compliance.connect(charlieWallet).created(ethers.constants.AddressZero, 10)).to.be.revertedWith( - 'invalid argument - zero address', - ); + await expect(compliance.connect(charlieWallet).created(ethers.ZeroAddress, 10)).to.be.revertedWith('invalid argument - zero address'); }); }); @@ -428,7 +422,7 @@ describe('ModularCompliance', () => { suite: { compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.connect(anotherWallet).destroyed(ethers.constants.AddressZero, 0)).to.be.revertedWith( + await expect(compliance.connect(anotherWallet).destroyed(ethers.ZeroAddress, 0)).to.be.revertedWith( 'error : this address is not a token bound to the compliance contract', ); }); @@ -442,9 +436,7 @@ describe('ModularCompliance', () => { accounts: { charlieWallet }, } = await loadFixture(deploySuiteWithModuleComplianceBoundToWallet); - await expect(compliance.connect(charlieWallet).destroyed(ethers.constants.AddressZero, 10)).to.be.revertedWith( - 'invalid argument - zero address', - ); + await expect(compliance.connect(charlieWallet).destroyed(ethers.ZeroAddress, 10)).to.be.revertedWith('invalid argument - zero address'); }); }); @@ -480,9 +472,9 @@ describe('ModularCompliance', () => { suite: { compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect( - compliance.connect(anotherWallet).callModuleFunction(ethers.utils.randomBytes(32), ethers.constants.AddressZero), - ).to.be.revertedWith('Ownable: caller is not the owner'); + await expect(compliance.connect(anotherWallet).callModuleFunction(ethers.randomBytes(32), ethers.ZeroAddress)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); }); }); @@ -493,7 +485,7 @@ describe('ModularCompliance', () => { suite: { compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.connect(deployer).callModuleFunction(ethers.utils.randomBytes(32), ethers.constants.AddressZero)).to.be.revertedWith( + await expect(compliance.connect(deployer).callModuleFunction(ethers.randomBytes(32), ethers.ZeroAddress)).to.be.revertedWith( 'call only on bound module', ); }); diff --git a/test/compliances/module-conditional-transfer.test.ts b/test/compliances/module-conditional-transfer.test.ts index 5134cffd..2a2b0d8f 100644 --- a/test/compliances/module-conditional-transfer.test.ts +++ b/test/compliances/module-conditional-transfer.test.ts @@ -9,14 +9,14 @@ describe('ConditionalTransferModule', () => { const { compliance } = context.suite; const module = await ethers.deployContract('ConditionalTransferModule'); - const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); - const conditionalTransferModule = await ethers.getContractAt('ConditionalTransferModule', proxy.address); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const conditionalTransferModule = await ethers.getContractAt('ConditionalTransferModule', proxy.target); - await compliance.addModule(conditionalTransferModule.address); + await compliance.addModule(conditionalTransferModule.target); const mockContract = await ethers.deployContract('MockContract'); - await compliance.bindToken(mockContract.address); + await compliance.bindToken(mockContract.target); return { ...context, suite: { ...context.suite, conditionalTransferModule, mockContract } }; } @@ -41,7 +41,7 @@ describe('ConditionalTransferModule', () => { describe('.canComplianceBind', () => { it('should return true', async () => { const context = await loadFixture(deployComplianceWithConditionalTransferModule); - expect(await context.suite.conditionalTransferModule.canComplianceBind(context.suite.compliance.address)).to.be.true; + expect(await context.suite.conditionalTransferModule.canComplianceBind(context.suite.compliance.target)).to.be.true; }); }); @@ -96,9 +96,9 @@ describe('ConditionalTransferModule', () => { describe('when calling directly', () => { it('should revert', async () => { const context = await loadFixture(deployComplianceWithConditionalTransferModule); - await expect( - context.suite.conditionalTransferModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero), - ).to.revertedWith('Ownable: caller is not the owner'); + await expect(context.suite.conditionalTransferModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress)).to.revertedWith( + 'Ownable: caller is not the owner', + ); }); }); @@ -109,11 +109,14 @@ describe('ConditionalTransferModule', () => { const newImplementation = await ethers.deployContract('ConditionalTransferModule'); // when - await context.suite.conditionalTransferModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + await context.suite.conditionalTransferModule.connect(context.accounts.deployer).upgradeTo(newImplementation.target); + + const target = context.suite.conditionalTransferModule.target; + const address = typeof target === 'string' ? target : await target.getAddress(); // then - const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.conditionalTransferModule.address); - expect(implementationAddress).to.eq(newImplementation.address); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(address); + expect(implementationAddress).to.eq(newImplementation.target); }); }); }); @@ -142,28 +145,29 @@ describe('ConditionalTransferModule', () => { const tx = await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchApproveTransfers(address[], address[], uint256[])']).encodeFunctionData( - 'batchApproveTransfers', - [[aliceWallet.address], [bobWallet.address], [10]], - ), - conditionalTransferModule.address, + new ethers.Interface(['function batchApproveTransfers(address[], address[], uint256[])']).encodeFunctionData('batchApproveTransfers', [ + [aliceWallet.address], + [bobWallet.address], + [10], + ]), + conditionalTransferModule.target, ); await expect(tx) .to.emit(conditionalTransferModule, 'TransferApproved') - .withArgs(aliceWallet.address, bobWallet.address, 10, mockContract.address); + .withArgs(aliceWallet.address, bobWallet.address, 10, mockContract.target); expect( await conditionalTransferModule.isTransferApproved( - compliance.address, - await conditionalTransferModule.calculateTransferHash(aliceWallet.address, bobWallet.address, 10, mockContract.address), + compliance.target, + await conditionalTransferModule.calculateTransferHash(aliceWallet.address, bobWallet.address, 10, mockContract.target), ), ).to.be.true; await expect( conditionalTransferModule.getTransferApprovals( - compliance.address, - await conditionalTransferModule.calculateTransferHash(aliceWallet.address, bobWallet.address, 10, mockContract.address), + compliance.target, + await conditionalTransferModule.calculateTransferHash(aliceWallet.address, bobWallet.address, 10, mockContract.target), ), ).to.eventually.be.equal(1); }); @@ -196,11 +200,11 @@ describe('ConditionalTransferModule', () => { compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchUnApproveTransfers(address[], address[], uint256[])']).encodeFunctionData( + new ethers.Interface(['function batchUnApproveTransfers(address[], address[], uint256[])']).encodeFunctionData( 'batchUnApproveTransfers', [[aliceWallet.address], [bobWallet.address], [10]], ), - conditionalTransferModule.address, + conditionalTransferModule.target, ), ).to.be.revertedWith('not approved'); }); @@ -215,31 +219,32 @@ describe('ConditionalTransferModule', () => { await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchApproveTransfers(address[], address[], uint256[])']).encodeFunctionData( - 'batchApproveTransfers', - [[aliceWallet.address], [bobWallet.address], [10]], - ), - conditionalTransferModule.address, + new ethers.Interface(['function batchApproveTransfers(address[], address[], uint256[])']).encodeFunctionData('batchApproveTransfers', [ + [aliceWallet.address], + [bobWallet.address], + [10], + ]), + conditionalTransferModule.target, ); const tx = await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchUnApproveTransfers(address[], address[], uint256[])']).encodeFunctionData( + new ethers.Interface(['function batchUnApproveTransfers(address[], address[], uint256[])']).encodeFunctionData( 'batchUnApproveTransfers', [[aliceWallet.address], [bobWallet.address], [10]], ), - conditionalTransferModule.address, + conditionalTransferModule.target, ); await expect(tx) .to.emit(conditionalTransferModule, 'ApprovalRemoved') - .withArgs(aliceWallet.address, bobWallet.address, 10, mockContract.address); + .withArgs(aliceWallet.address, bobWallet.address, 10, mockContract.target); expect( await conditionalTransferModule.isTransferApproved( - compliance.address, - await conditionalTransferModule.calculateTransferHash(aliceWallet.address, bobWallet.address, 10, mockContract.address), + compliance.target, + await conditionalTransferModule.calculateTransferHash(aliceWallet.address, bobWallet.address, 10, mockContract.target), ), ).to.be.false; }); @@ -284,7 +289,7 @@ describe('ConditionalTransferModule', () => { accounts: { aliceWallet, bobWallet }, } = await loadFixture(deployComplianceWithConditionalTransferModule); - await expect(conditionalTransferModule.moduleCheck(aliceWallet.address, bobWallet.address, 10, compliance.address)).to.eventually.be.false; + await expect(conditionalTransferModule.moduleCheck(aliceWallet.address, bobWallet.address, 10, compliance.target)).to.eventually.be.false; }); }); @@ -298,14 +303,15 @@ describe('ConditionalTransferModule', () => { await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchApproveTransfers(address[], address[], uint256[])']).encodeFunctionData( - 'batchApproveTransfers', - [[aliceWallet.address], [bobWallet.address], [10]], - ), - conditionalTransferModule.address, + new ethers.Interface(['function batchApproveTransfers(address[], address[], uint256[])']).encodeFunctionData('batchApproveTransfers', [ + [aliceWallet.address], + [bobWallet.address], + [10], + ]), + conditionalTransferModule.target, ); - await expect(conditionalTransferModule.moduleCheck(aliceWallet.address, bobWallet.address, 10, compliance.address)).to.eventually.be.true; + await expect(conditionalTransferModule.moduleCheck(aliceWallet.address, bobWallet.address, 10, compliance.target)).to.eventually.be.true; }); }); }); @@ -333,11 +339,11 @@ describe('ConditionalTransferModule', () => { compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ + new ethers.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ anotherWallet.address, 10, ]), - conditionalTransferModule.address, + conditionalTransferModule.target, ), ).to.eventually.be.fulfilled; }); @@ -367,11 +373,11 @@ describe('ConditionalTransferModule', () => { compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ + new ethers.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ anotherWallet.address, 10, ]), - conditionalTransferModule.address, + conditionalTransferModule.target, ), ).to.eventually.be.fulfilled; }); @@ -404,12 +410,12 @@ describe('ConditionalTransferModule', () => { compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address, address, uint256)']).encodeFunctionData('moduleTransferAction', [ + new ethers.Interface(['function moduleTransferAction(address, address, uint256)']).encodeFunctionData('moduleTransferAction', [ aliceWallet.address, bobWallet.address, 10, ]), - conditionalTransferModule.address, + conditionalTransferModule.target, ), ).to.eventually.be.fulfilled; }); @@ -425,34 +431,35 @@ describe('ConditionalTransferModule', () => { await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchApproveTransfers(address[], address[], uint256[])']).encodeFunctionData( - 'batchApproveTransfers', - [[aliceWallet.address], [bobWallet.address], [10]], - ), - conditionalTransferModule.address, + new ethers.Interface(['function batchApproveTransfers(address[], address[], uint256[])']).encodeFunctionData('batchApproveTransfers', [ + [aliceWallet.address], + [bobWallet.address], + [10], + ]), + conditionalTransferModule.target, ); const tx = await expect( compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address, address, uint256)']).encodeFunctionData('moduleTransferAction', [ + new ethers.Interface(['function moduleTransferAction(address, address, uint256)']).encodeFunctionData('moduleTransferAction', [ aliceWallet.address, bobWallet.address, 10, ]), - conditionalTransferModule.address, + conditionalTransferModule.target, ), ).to.eventually.be.fulfilled; await expect(tx) .to.emit(conditionalTransferModule, 'ApprovalRemoved') - .withArgs(aliceWallet.address, bobWallet.address, 10, mockContract.address); + .withArgs(aliceWallet.address, bobWallet.address, 10, mockContract.target); expect( await conditionalTransferModule.isTransferApproved( - compliance.address, - await conditionalTransferModule.calculateTransferHash(aliceWallet.address, bobWallet.address, 10, mockContract.address), + compliance.target, + await conditionalTransferModule.calculateTransferHash(aliceWallet.address, bobWallet.address, 10, mockContract.target), ), ).to.be.false; }); diff --git a/test/compliances/module-country-allow.test.ts b/test/compliances/module-country-allow.test.ts index bf446d86..711be048 100644 --- a/test/compliances/module-country-allow.test.ts +++ b/test/compliances/module-country-allow.test.ts @@ -9,9 +9,9 @@ describe('CountryAllowModule', () => { const { compliance } = context.suite; const module = await ethers.deployContract('CountryAllowModule'); - const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); - const countryAllowModule = await ethers.getContractAt('CountryAllowModule', proxy.address); - await compliance.addModule(countryAllowModule.address); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const countryAllowModule = await ethers.getContractAt('CountryAllowModule', proxy.target); + await compliance.addModule(countryAllowModule.target); return { ...context, suite: { ...context.suite, countryAllowModule } }; } @@ -36,7 +36,7 @@ describe('CountryAllowModule', () => { describe('.canComplianceBind()', () => { it('should return true', async () => { const context = await loadFixture(deployComplianceWithCountryAllowModule); - expect(await context.suite.countryAllowModule.canComplianceBind(context.suite.compliance.address)).to.be.true; + expect(await context.suite.countryAllowModule.canComplianceBind(context.suite.compliance.target)).to.be.true; }); }); @@ -91,7 +91,7 @@ describe('CountryAllowModule', () => { describe('when calling directly', () => { it('should revert', async () => { const context = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(context.suite.countryAllowModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero)).to.revertedWith( + await expect(context.suite.countryAllowModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress)).to.revertedWith( 'Ownable: caller is not the owner', ); }); @@ -108,25 +108,27 @@ describe('CountryAllowModule', () => { await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function addAllowedCountry(uint16 country)']).encodeFunctionData('addAllowedCountry', [42]), - countryAllowModule.address, + new ethers.Interface(['function addAllowedCountry(uint16 country)']).encodeFunctionData('addAllowedCountry', [42]), + countryAllowModule.target, ); const newImplementation = await ethers.deployContract('TestUpgradedCountryAllowModule'); // when - await countryAllowModule.connect(deployer).upgradeTo(newImplementation.address); + await countryAllowModule.connect(deployer).upgradeTo(newImplementation.target); + const target = countryAllowModule.target; + const address = typeof target === 'string' ? target : await target.getAddress(); // then - const implementationAddress = await upgrades.erc1967.getImplementationAddress(countryAllowModule.address); - expect(implementationAddress).to.eq(newImplementation.address); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(address); + expect(implementationAddress).to.eq(newImplementation.target); - const upgradedContract = await ethers.getContractAt('TestUpgradedCountryAllowModule', countryAllowModule.address); + const upgradedContract = await ethers.getContractAt('TestUpgradedCountryAllowModule', countryAllowModule.target); expect(await upgradedContract.getNewField()).to.be.eq(0); await upgradedContract.connect(deployer).setNewField(222); expect(await upgradedContract.getNewField()).to.be.eq(222); - expect(await upgradedContract.isCountryAllowed(compliance.address, 42)).to.be.true; + expect(await upgradedContract.isCountryAllowed(compliance.target, 42)).to.be.true; }); }); }); @@ -164,17 +166,15 @@ describe('CountryAllowModule', () => { const tx = await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchAllowCountries(uint16[] calldata countries)']).encodeFunctionData('batchAllowCountries', [ - [42, 66], - ]), - countryAllowModule.address, + new ethers.Interface(['function batchAllowCountries(uint16[] calldata countries)']).encodeFunctionData('batchAllowCountries', [[42, 66]]), + countryAllowModule.target, ); - await expect(tx).to.emit(countryAllowModule, 'CountryAllowed').withArgs(compliance.address, 42); - await expect(tx).to.emit(countryAllowModule, 'CountryAllowed').withArgs(compliance.address, 66); + await expect(tx).to.emit(countryAllowModule, 'CountryAllowed').withArgs(compliance.target, 42); + await expect(tx).to.emit(countryAllowModule, 'CountryAllowed').withArgs(compliance.target, 66); - expect(await countryAllowModule.isCountryAllowed(compliance.address, 42)).to.be.true; - expect(await countryAllowModule.isCountryAllowed(compliance.address, 66)).to.be.true; + expect(await countryAllowModule.isCountryAllowed(compliance.target, 42)).to.be.true; + expect(await countryAllowModule.isCountryAllowed(compliance.target, 66)).to.be.true; }); }); }); @@ -212,18 +212,17 @@ describe('CountryAllowModule', () => { const tx = await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchDisallowCountries(uint16[] calldata countries)']).encodeFunctionData( - 'batchDisallowCountries', - [[42, 66]], - ), - countryAllowModule.address, + new ethers.Interface(['function batchDisallowCountries(uint16[] calldata countries)']).encodeFunctionData('batchDisallowCountries', [ + [42, 66], + ]), + countryAllowModule.target, ); - await expect(tx).to.emit(countryAllowModule, 'CountryUnallowed').withArgs(compliance.address, 42); - await expect(tx).to.emit(countryAllowModule, 'CountryUnallowed').withArgs(compliance.address, 66); + await expect(tx).to.emit(countryAllowModule, 'CountryUnallowed').withArgs(compliance.target, 42); + await expect(tx).to.emit(countryAllowModule, 'CountryUnallowed').withArgs(compliance.target, 66); - expect(await countryAllowModule.isCountryAllowed(compliance.address, 42)).to.be.false; - expect(await countryAllowModule.isCountryAllowed(compliance.address, 66)).to.be.false; + expect(await countryAllowModule.isCountryAllowed(compliance.target, 42)).to.be.false; + expect(await countryAllowModule.isCountryAllowed(compliance.target, 66)).to.be.false; }); }); }); @@ -262,20 +261,20 @@ describe('CountryAllowModule', () => { await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function addAllowedCountry(uint16 country)']).encodeFunctionData('addAllowedCountry', [42]), - countryAllowModule.address, + new ethers.Interface(['function addAllowedCountry(uint16 country)']).encodeFunctionData('addAllowedCountry', [42]), + countryAllowModule.target, ); await expect( compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function addAllowedCountry(uint16 country)']).encodeFunctionData('addAllowedCountry', [42]), - countryAllowModule.address, + new ethers.Interface(['function addAllowedCountry(uint16 country)']).encodeFunctionData('addAllowedCountry', [42]), + countryAllowModule.target, ), ) .to.be.revertedWithCustomError(countryAllowModule, 'CountryAlreadyAllowed') - .withArgs(compliance.address, 42); + .withArgs(compliance.target, 42); }); }); @@ -289,13 +288,13 @@ describe('CountryAllowModule', () => { const tx = await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function addAllowedCountry(uint16 country)']).encodeFunctionData('addAllowedCountry', [42]), - countryAllowModule.address, + new ethers.Interface(['function addAllowedCountry(uint16 country)']).encodeFunctionData('addAllowedCountry', [42]), + countryAllowModule.target, ); - await expect(tx).to.emit(countryAllowModule, 'CountryAllowed').withArgs(compliance.address, 42); + await expect(tx).to.emit(countryAllowModule, 'CountryAllowed').withArgs(compliance.target, 42); - expect(await countryAllowModule.isCountryAllowed(compliance.address, 42)).to.be.true; + expect(await countryAllowModule.isCountryAllowed(compliance.target, 42)).to.be.true; }); }); }); @@ -336,12 +335,12 @@ describe('CountryAllowModule', () => { compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function removeAllowedCountry(uint16 country)']).encodeFunctionData('removeAllowedCountry', [42]), - countryAllowModule.address, + new ethers.Interface(['function removeAllowedCountry(uint16 country)']).encodeFunctionData('removeAllowedCountry', [42]), + countryAllowModule.target, ), ) .to.be.revertedWithCustomError(countryAllowModule, 'CountryNotAllowed') - .withArgs(compliance.address, 42); + .withArgs(compliance.target, 42); }); }); @@ -355,20 +354,20 @@ describe('CountryAllowModule', () => { await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function addAllowedCountry(uint16 country)']).encodeFunctionData('addAllowedCountry', [42]), - countryAllowModule.address, + new ethers.Interface(['function addAllowedCountry(uint16 country)']).encodeFunctionData('addAllowedCountry', [42]), + countryAllowModule.target, ); const tx = await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function removeAllowedCountry(uint16 country)']).encodeFunctionData('removeAllowedCountry', [42]), - countryAllowModule.address, + new ethers.Interface(['function removeAllowedCountry(uint16 country)']).encodeFunctionData('removeAllowedCountry', [42]), + countryAllowModule.target, ); - await expect(tx).to.emit(countryAllowModule, 'CountryUnallowed').withArgs(compliance.address, 42); + await expect(tx).to.emit(countryAllowModule, 'CountryUnallowed').withArgs(compliance.target, 42); - expect(await countryAllowModule.isCountryAllowed(compliance.address, 42)).to.be.false; + expect(await countryAllowModule.isCountryAllowed(compliance.target, 42)).to.be.false; }); }); }); @@ -382,20 +381,18 @@ describe('CountryAllowModule', () => { accounts: { deployer, aliceWallet, bobWallet }, } = await loadFixture(deployComplianceWithCountryAllowModule); const contract = await ethers.deployContract('MockContract'); - await compliance.bindToken(contract.address); + await compliance.bindToken(contract.target); await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchAllowCountries(uint16[] calldata countries)']).encodeFunctionData('batchAllowCountries', [ - [42, 66], - ]), - countryAllowModule.address, + new ethers.Interface(['function batchAllowCountries(uint16[] calldata countries)']).encodeFunctionData('batchAllowCountries', [[42, 66]]), + countryAllowModule.target, ); await contract.setInvestorCountry(42); - await expect(countryAllowModule.moduleCheck(aliceWallet.address, bobWallet.address, 10, compliance.address)).to.be.eventually.true; + await expect(countryAllowModule.moduleCheck(aliceWallet.address, bobWallet.address, 10, compliance.target)).to.be.eventually.true; await expect(compliance.canTransfer(aliceWallet.address, bobWallet.address, 10)).to.be.eventually.true; }); }); @@ -407,20 +404,18 @@ describe('CountryAllowModule', () => { accounts: { deployer, aliceWallet, bobWallet }, } = await loadFixture(deployComplianceWithCountryAllowModule); const contract = await ethers.deployContract('MockContract'); - await compliance.bindToken(contract.address); + await compliance.bindToken(contract.target); await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchAllowCountries(uint16[] calldata countries)']).encodeFunctionData('batchAllowCountries', [ - [42, 66], - ]), - countryAllowModule.address, + new ethers.Interface(['function batchAllowCountries(uint16[] calldata countries)']).encodeFunctionData('batchAllowCountries', [[42, 66]]), + countryAllowModule.target, ); await contract.setInvestorCountry(10); - await expect(countryAllowModule.moduleCheck(aliceWallet.address, bobWallet.address, 16, compliance.address)).to.be.eventually.false; + await expect(countryAllowModule.moduleCheck(aliceWallet.address, bobWallet.address, 16, compliance.target)).to.be.eventually.false; await expect(compliance.canTransfer(aliceWallet.address, bobWallet.address, 16)).to.be.eventually.false; }); }); @@ -433,7 +428,7 @@ describe('CountryAllowModule', () => { suite: { countryAllowModule, compliance }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.isComplianceBound(compliance.address)).to.be.eventually.true; + await expect(countryAllowModule.isComplianceBound(compliance.target)).to.be.eventually.true; }); }); @@ -443,7 +438,7 @@ describe('CountryAllowModule', () => { suite: { countryAllowModule }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.isComplianceBound(countryAllowModule.address)).to.be.eventually.false; + await expect(countryAllowModule.isComplianceBound(countryAllowModule.target)).to.be.eventually.false; }); }); }); @@ -456,7 +451,7 @@ describe('CountryAllowModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(anotherWallet).unbindCompliance(compliance.address)).to.be.revertedWith( + await expect(countryAllowModule.connect(anotherWallet).unbindCompliance(compliance.target)).to.be.revertedWith( 'only bound compliance can call', ); }); diff --git a/test/compliances/module-country-restrict.test.ts b/test/compliances/module-country-restrict.test.ts index b11c5669..c663ad36 100644 --- a/test/compliances/module-country-restrict.test.ts +++ b/test/compliances/module-country-restrict.test.ts @@ -9,9 +9,9 @@ describe('CountryRestrictModule', () => { const { compliance } = context.suite; const module = await ethers.deployContract('CountryRestrictModule'); - const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); - const countryRestrictModule = await ethers.getContractAt('CountryRestrictModule', proxy.address); - await compliance.addModule(countryRestrictModule.address); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const countryRestrictModule = await ethers.getContractAt('CountryRestrictModule', proxy.target); + await compliance.addModule(countryRestrictModule.target); return { ...context, suite: { ...context.suite, countryRestrictModule } }; } @@ -35,7 +35,7 @@ describe('CountryRestrictModule', () => { describe('.canComplianceBind()', () => { it('should return true', async () => { const context = await loadFixture(deployComplianceWithCountryRestrictModule); - expect(await context.suite.countryRestrictModule.canComplianceBind(context.suite.compliance.address)).to.be.true; + expect(await context.suite.countryRestrictModule.canComplianceBind(context.suite.compliance.target)).to.be.true; }); }); @@ -90,9 +90,9 @@ describe('CountryRestrictModule', () => { describe('when calling directly', () => { it('should revert', async () => { const context = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect( - context.suite.countryRestrictModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero), - ).to.revertedWith('Ownable: caller is not the owner'); + await expect(context.suite.countryRestrictModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress)).to.revertedWith( + 'Ownable: caller is not the owner', + ); }); }); @@ -103,11 +103,14 @@ describe('CountryRestrictModule', () => { const newImplementation = await ethers.deployContract('CountryRestrictModule'); // when - await context.suite.countryRestrictModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + await context.suite.countryRestrictModule.connect(context.accounts.deployer).upgradeTo(newImplementation.target); + const target = context.suite.countryRestrictModule.target; + + const address = typeof target === 'string' ? target : await target.getAddress(); // then - const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.countryRestrictModule.address); - expect(implementationAddress).to.eq(newImplementation.address); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(address); + expect(implementationAddress).to.eq(newImplementation.target); }); }); }); @@ -146,16 +149,16 @@ describe('CountryRestrictModule', () => { await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function addCountryRestriction(uint16 country)']).encodeFunctionData('addCountryRestriction', [42]), - countryRestrictModule.address, + new ethers.Interface(['function addCountryRestriction(uint16 country)']).encodeFunctionData('addCountryRestriction', [42]), + countryRestrictModule.target, ); await expect( compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function addCountryRestriction(uint16 country)']).encodeFunctionData('addCountryRestriction', [42]), - countryRestrictModule.address, + new ethers.Interface(['function addCountryRestriction(uint16 country)']).encodeFunctionData('addCountryRestriction', [42]), + countryRestrictModule.target, ), ).to.be.revertedWith('country already restricted'); }); @@ -171,13 +174,13 @@ describe('CountryRestrictModule', () => { const tx = await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function addCountryRestriction(uint16 country)']).encodeFunctionData('addCountryRestriction', [42]), - countryRestrictModule.address, + new ethers.Interface(['function addCountryRestriction(uint16 country)']).encodeFunctionData('addCountryRestriction', [42]), + countryRestrictModule.target, ); - await expect(tx).to.emit(countryRestrictModule, 'AddedRestrictedCountry').withArgs(compliance.address, 42); + await expect(tx).to.emit(countryRestrictModule, 'AddedRestrictedCountry').withArgs(compliance.target, 42); - expect(await countryRestrictModule.isCountryRestricted(compliance.address, 42)).to.be.true; + expect(await countryRestrictModule.isCountryRestricted(compliance.target, 42)).to.be.true; }); }); }); @@ -218,10 +221,8 @@ describe('CountryRestrictModule', () => { compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function removeCountryRestriction(uint16 country)']).encodeFunctionData('removeCountryRestriction', [ - 42, - ]), - countryRestrictModule.address, + new ethers.Interface(['function removeCountryRestriction(uint16 country)']).encodeFunctionData('removeCountryRestriction', [42]), + countryRestrictModule.target, ), ).to.be.revertedWith('country not restricted'); }); @@ -237,20 +238,20 @@ describe('CountryRestrictModule', () => { await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function addCountryRestriction(uint16 country)']).encodeFunctionData('addCountryRestriction', [42]), - countryRestrictModule.address, + new ethers.Interface(['function addCountryRestriction(uint16 country)']).encodeFunctionData('addCountryRestriction', [42]), + countryRestrictModule.target, ); const tx = await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function removeCountryRestriction(uint16 country)']).encodeFunctionData('removeCountryRestriction', [42]), - countryRestrictModule.address, + new ethers.Interface(['function removeCountryRestriction(uint16 country)']).encodeFunctionData('removeCountryRestriction', [42]), + countryRestrictModule.target, ); - await expect(tx).to.emit(countryRestrictModule, 'RemovedRestrictedCountry').withArgs(compliance.address, 42); + await expect(tx).to.emit(countryRestrictModule, 'RemovedRestrictedCountry').withArgs(compliance.target, 42); - expect(await countryRestrictModule.isCountryRestricted(compliance.address, 42)).to.be.false; + expect(await countryRestrictModule.isCountryRestricted(compliance.target, 42)).to.be.false; }); }); }); @@ -291,11 +292,10 @@ describe('CountryRestrictModule', () => { compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchRestrictCountries(uint16[] memory countries)']).encodeFunctionData( - 'batchRestrictCountries', - [Array.from({ length: 195 }, (_, i) => i)], - ), - countryRestrictModule.address, + new ethers.Interface(['function batchRestrictCountries(uint16[] memory countries)']).encodeFunctionData('batchRestrictCountries', [ + Array.from({ length: 195 }, (_, i) => i), + ]), + countryRestrictModule.target, ), ).to.be.revertedWith('maximum 195 can be restricted in one batch'); }); @@ -311,19 +311,18 @@ describe('CountryRestrictModule', () => { await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function addCountryRestriction(uint16 country)']).encodeFunctionData('addCountryRestriction', [42]), - countryRestrictModule.address, + new ethers.Interface(['function addCountryRestriction(uint16 country)']).encodeFunctionData('addCountryRestriction', [42]), + countryRestrictModule.target, ); await expect( compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchRestrictCountries(uint16[] memory countries)']).encodeFunctionData( - 'batchRestrictCountries', - [[12, 42, 67]], - ), - countryRestrictModule.address, + new ethers.Interface(['function batchRestrictCountries(uint16[] memory countries)']).encodeFunctionData('batchRestrictCountries', [ + [12, 42, 67], + ]), + countryRestrictModule.target, ), ).to.be.revertedWith('country already restricted'); }); @@ -338,17 +337,17 @@ describe('CountryRestrictModule', () => { const tx = await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchRestrictCountries(uint16[] memory countries)']).encodeFunctionData('batchRestrictCountries', [ + new ethers.Interface(['function batchRestrictCountries(uint16[] memory countries)']).encodeFunctionData('batchRestrictCountries', [ [42, 66], ]), - countryRestrictModule.address, + countryRestrictModule.target, ); - await expect(tx).to.emit(countryRestrictModule, 'AddedRestrictedCountry').withArgs(compliance.address, 42); - await expect(tx).to.emit(countryRestrictModule, 'AddedRestrictedCountry').withArgs(compliance.address, 66); + await expect(tx).to.emit(countryRestrictModule, 'AddedRestrictedCountry').withArgs(compliance.target, 42); + await expect(tx).to.emit(countryRestrictModule, 'AddedRestrictedCountry').withArgs(compliance.target, 66); - expect(await countryRestrictModule.isCountryRestricted(compliance.address, 42)).to.be.true; - expect(await countryRestrictModule.isCountryRestricted(compliance.address, 66)).to.be.true; + expect(await countryRestrictModule.isCountryRestricted(compliance.target, 42)).to.be.true; + expect(await countryRestrictModule.isCountryRestricted(compliance.target, 66)).to.be.true; }); }); }); @@ -390,11 +389,11 @@ describe('CountryRestrictModule', () => { compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchUnrestrictCountries(uint16[] memory countries)']).encodeFunctionData( + new ethers.Interface(['function batchUnrestrictCountries(uint16[] memory countries)']).encodeFunctionData( 'batchUnrestrictCountries', [Array.from({ length: 195 }, (_, i) => i)], ), - countryRestrictModule.address, + countryRestrictModule.target, ), ).to.be.revertedWith('maximum 195 can be unrestricted in one batch'); }); @@ -411,11 +410,11 @@ describe('CountryRestrictModule', () => { compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchUnrestrictCountries(uint16[] memory countries)']).encodeFunctionData( + new ethers.Interface(['function batchUnrestrictCountries(uint16[] memory countries)']).encodeFunctionData( 'batchUnrestrictCountries', [[12, 42, 67]], ), - countryRestrictModule.address, + countryRestrictModule.target, ), ).to.be.revertedWith('country not restricted'); }); @@ -430,27 +429,26 @@ describe('CountryRestrictModule', () => { await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchRestrictCountries(uint16[] memory countries)']).encodeFunctionData('batchRestrictCountries', [ + new ethers.Interface(['function batchRestrictCountries(uint16[] memory countries)']).encodeFunctionData('batchRestrictCountries', [ [42, 66], ]), - countryRestrictModule.address, + countryRestrictModule.target, ); const tx = await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchUnrestrictCountries(uint16[] memory countries)']).encodeFunctionData( - 'batchUnrestrictCountries', - [[42, 66]], - ), - countryRestrictModule.address, + new ethers.Interface(['function batchUnrestrictCountries(uint16[] memory countries)']).encodeFunctionData('batchUnrestrictCountries', [ + [42, 66], + ]), + countryRestrictModule.target, ); - await expect(tx).to.emit(countryRestrictModule, 'RemovedRestrictedCountry').withArgs(compliance.address, 42); - await expect(tx).to.emit(countryRestrictModule, 'RemovedRestrictedCountry').withArgs(compliance.address, 66); + await expect(tx).to.emit(countryRestrictModule, 'RemovedRestrictedCountry').withArgs(compliance.target, 42); + await expect(tx).to.emit(countryRestrictModule, 'RemovedRestrictedCountry').withArgs(compliance.target, 66); - expect(await countryRestrictModule.isCountryRestricted(compliance.address, 42)).to.be.false; - expect(await countryRestrictModule.isCountryRestricted(compliance.address, 66)).to.be.false; + expect(await countryRestrictModule.isCountryRestricted(compliance.target, 42)).to.be.false; + expect(await countryRestrictModule.isCountryRestricted(compliance.target, 66)).to.be.false; }); }); }); @@ -480,12 +478,12 @@ describe('CountryRestrictModule', () => { compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address, address, uint256)']).encodeFunctionData('moduleTransferAction', [ + new ethers.Interface(['function moduleTransferAction(address, address, uint256)']).encodeFunctionData('moduleTransferAction', [ aliceWallet.address, bobWallet.address, 10, ]), - countryRestrictModule.address, + countryRestrictModule.target, ), ).to.eventually.be.fulfilled; }); @@ -517,11 +515,11 @@ describe('CountryRestrictModule', () => { compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ + new ethers.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ anotherWallet.address, 10, ]), - countryRestrictModule.address, + countryRestrictModule.target, ), ).to.eventually.be.fulfilled; }); @@ -553,11 +551,11 @@ describe('CountryRestrictModule', () => { compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ + new ethers.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ anotherWallet.address, 10, ]), - countryRestrictModule.address, + countryRestrictModule.target, ), ).to.eventually.be.fulfilled; }); @@ -572,21 +570,20 @@ describe('CountryRestrictModule', () => { accounts: { deployer, aliceWallet, bobWallet }, } = await loadFixture(deployComplianceWithCountryRestrictModule); const contract = await ethers.deployContract('MockContract'); - await compliance.bindToken(contract.address); + await compliance.bindToken(contract.target); await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchRestrictCountries(uint16[] calldata countries)']).encodeFunctionData( - 'batchRestrictCountries', - [[42, 66]], - ), - countryRestrictModule.address, + new ethers.Interface(['function batchRestrictCountries(uint16[] calldata countries)']).encodeFunctionData('batchRestrictCountries', [ + [42, 66], + ]), + countryRestrictModule.target, ); await contract.setInvestorCountry(42); - await expect(countryRestrictModule.moduleCheck(aliceWallet.address, bobWallet.address, 16, compliance.address)).to.be.eventually.false; + await expect(countryRestrictModule.moduleCheck(aliceWallet.address, bobWallet.address, 16, compliance.target)).to.be.eventually.false; }); }); @@ -597,21 +594,20 @@ describe('CountryRestrictModule', () => { accounts: { deployer, aliceWallet, bobWallet }, } = await loadFixture(deployComplianceWithCountryRestrictModule); const contract = await ethers.deployContract('MockContract'); - await compliance.bindToken(contract.address); + await compliance.bindToken(contract.target); await compliance .connect(deployer) .callModuleFunction( - new ethers.utils.Interface(['function batchRestrictCountries(uint16[] calldata countries)']).encodeFunctionData( - 'batchRestrictCountries', - [[42, 66]], - ), - countryRestrictModule.address, + new ethers.Interface(['function batchRestrictCountries(uint16[] calldata countries)']).encodeFunctionData('batchRestrictCountries', [ + [42, 66], + ]), + countryRestrictModule.target, ); await contract.setInvestorCountry(10); - await expect(countryRestrictModule.moduleCheck(aliceWallet.address, bobWallet.address, 16, compliance.address)).to.be.eventually.true; + await expect(countryRestrictModule.moduleCheck(aliceWallet.address, bobWallet.address, 16, compliance.target)).to.be.eventually.true; }); }); }); diff --git a/test/compliances/module-exchange-monthly-limits.test.ts b/test/compliances/module-exchange-monthly-limits.test.ts index 8adda7e2..0ba0cc31 100644 --- a/test/compliances/module-exchange-monthly-limits.test.ts +++ b/test/compliances/module-exchange-monthly-limits.test.ts @@ -3,15 +3,16 @@ import { ethers, upgrades } from 'hardhat'; import { expect } from 'chai'; import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; +import { ExchangeMonthlyLimits } from '../../typechain-types'; async function deployExchangeMonthlyLimitsFixture() { const context = await loadFixture(deployComplianceFixture); const module = await ethers.deployContract('ExchangeMonthlyLimitsModule'); - const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); - const complianceModule = await ethers.getContractAt('ExchangeMonthlyLimitsModule', proxy.address); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('ExchangeMonthlyLimitsModule', proxy.target); - await context.suite.compliance.addModule(complianceModule.address); + await context.suite.compliance.addModule(complianceModule.target); return { ...context, @@ -26,8 +27,8 @@ async function deployExchangeMonthlyLimitsFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); const ExchangeMonthlyLimitsModule = await ethers.getContractFactory('ExchangeMonthlyLimitsModule'); const complianceModule = await upgrades.deployProxy(ExchangeMonthlyLimitsModule, []); - await context.suite.compliance.bindToken(context.suite.token.address); - await context.suite.compliance.addModule(complianceModule.address); + await context.suite.compliance.bindToken(context.suite.token.target); + await context.suite.compliance.addModule(complianceModule.target); return { ...context, @@ -42,8 +43,8 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { it('should deploy the ExchangeMonthlyLimits contract and bind it to the compliance', async () => { const context = await loadFixture(deployExchangeMonthlyLimitsFixture); - expect(context.contracts.complianceModule.address).not.to.be.undefined; - expect(await context.contracts.compliance.isModuleBound(context.contracts.complianceModule.address)).to.be.true; + expect(context.contracts.complianceModule.target).not.to.be.undefined; + expect(await context.contracts.compliance.isModuleBound(context.contracts.complianceModule.target)).to.be.true; }); describe('.name()', () => { @@ -64,7 +65,7 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { describe('.canComplianceBind', () => { it('should return true', async () => { const context = await loadFixture(deployExchangeMonthlyLimitsFullSuite); - expect(await context.suite.complianceModule.canComplianceBind(context.suite.compliance.address)).to.be.true; + expect(await context.suite.complianceModule.canComplianceBind(context.suite.compliance.target)).to.be.true; }); }); @@ -119,9 +120,9 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { describe('when calling directly', () => { it('should revert', async () => { const context = await loadFixture(deployExchangeMonthlyLimitsFixture); - await expect( - context.contracts.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero), - ).to.revertedWith('Ownable: caller is not the owner'); + await expect(context.contracts.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress)).to.revertedWith( + 'Ownable: caller is not the owner', + ); }); }); @@ -132,11 +133,14 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { const newImplementation = await ethers.deployContract('ExchangeMonthlyLimitsModule'); // when - await context.contracts.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + await context.contracts.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.target); + + const target = context.contracts.complianceModule.target; + const address = typeof target === 'string' ? target : await target.getAddress(); // then - const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.contracts.complianceModule.address); - expect(implementationAddress).to.eq(newImplementation.address); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(address); + expect(implementationAddress).to.eq(newImplementation.target); }); }); }); @@ -157,16 +161,16 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { const exchangeID = context.accounts.anotherWallet.address; const tx = await context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface(['function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)']).encodeFunctionData( + new ethers.Interface(['function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)']).encodeFunctionData( 'setExchangeMonthlyLimit', [exchangeID, 100], ), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ); await expect(tx) .to.emit(context.contracts.complianceModule, 'ExchangeMonthlyLimitUpdated') - .withArgs(context.contracts.compliance.address, exchangeID, 100); + .withArgs(context.contracts.compliance.target, exchangeID, 100); }); }); }); @@ -177,14 +181,14 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { const exchangeID = context.accounts.anotherWallet.address; await context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface(['function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)']).encodeFunctionData( + new ethers.Interface(['function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)']).encodeFunctionData( 'setExchangeMonthlyLimit', [exchangeID, 100], ), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ); - expect(await context.contracts.complianceModule.getExchangeMonthlyLimit(context.suite.compliance.address, exchangeID)).to.be.eq(100); + expect(await context.contracts.complianceModule.getExchangeMonthlyLimit(context.suite.compliance.target, exchangeID)).to.be.eq(100); }); }); @@ -312,24 +316,25 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { const exchangeID = await context.suite.identityRegistry.identity(to); const investorID = await context.suite.identityRegistry.identity(from); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(exchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as ExchangeMonthlyLimits).addExchangeID(exchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ - 'function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)', - ]).encodeFunctionData('setExchangeMonthlyLimit', [exchangeID, 100]), - context.suite.complianceModule.address, + new ethers.Interface(['function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)']).encodeFunctionData( + 'setExchangeMonthlyLimit', + [exchangeID, 100], + ), + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 10], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - const counter = await context.suite.complianceModule.getMonthlyCounter(context.suite.compliance.address, exchangeID, investorID); + const counter = await context.suite.complianceModule.getMonthlyCounter(context.suite.compliance.target, exchangeID, investorID); expect(counter).to.be.eq(10); }); }); @@ -342,17 +347,17 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { const exchangeID = await context.suite.identityRegistry.identity(to); const investorID = await context.suite.identityRegistry.identity(from); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(exchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as ExchangeMonthlyLimits).addExchangeID(exchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 10], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - const timer = await context.suite.complianceModule.getMonthlyTimer(context.suite.compliance.address, exchangeID, investorID); + const timer = await context.suite.complianceModule.getMonthlyTimer(context.suite.compliance.target, exchangeID, investorID); expect(timer).to.be.gt(0); }); }); @@ -364,26 +369,26 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { const exchangeID = await context.suite.identityRegistry.identity(to); const investorID = await context.suite.identityRegistry.identity(from); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(exchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as ExchangeMonthlyLimits).addExchangeID(exchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 10], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - const previousTimer = await context.suite.complianceModule.getMonthlyTimer(context.suite.compliance.address, exchangeID, investorID); + const previousTimer = await context.suite.complianceModule.getMonthlyTimer(context.suite.compliance.target, exchangeID, investorID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 11], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - const timer = await context.suite.complianceModule.getMonthlyTimer(context.suite.compliance.address, exchangeID, investorID); + const timer = await context.suite.complianceModule.getMonthlyTimer(context.suite.compliance.target, exchangeID, investorID); expect(timer).to.be.eq(previousTimer); }); }); @@ -397,27 +402,28 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { const exchangeID = await context.suite.identityRegistry.identity(to); const investorID = await context.suite.identityRegistry.identity(from); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(exchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as ExchangeMonthlyLimits).addExchangeID(exchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ - 'function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)', - ]).encodeFunctionData('setExchangeMonthlyLimit', [exchangeID, 100]), - context.suite.complianceModule.address, + new ethers.Interface(['function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)']).encodeFunctionData( + 'setExchangeMonthlyLimit', + [exchangeID, 100], + ), + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 10], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - const counter = await context.suite.complianceModule.getMonthlyCounter(context.suite.compliance.address, exchangeID, investorID); + const counter = await context.suite.complianceModule.getMonthlyCounter(context.suite.compliance.target, exchangeID, investorID); expect(counter).to.be.eq(0); - const timer = await context.suite.complianceModule.getMonthlyTimer(context.suite.compliance.address, exchangeID, investorID); + const timer = await context.suite.complianceModule.getMonthlyTimer(context.suite.compliance.target, exchangeID, investorID); expect(timer).to.be.eq(0); }); }); @@ -433,17 +439,17 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { const investorID = await context.suite.identityRegistry.identity(from); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 10], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - const counter = await context.suite.complianceModule.getMonthlyCounter(context.suite.compliance.address, receiverID, investorID); + const counter = await context.suite.complianceModule.getMonthlyCounter(context.suite.compliance.target, receiverID, investorID); expect(counter).to.be.eq(0); - const timer = await context.suite.complianceModule.getMonthlyTimer(context.suite.compliance.address, receiverID, investorID); + const timer = await context.suite.complianceModule.getMonthlyTimer(context.suite.compliance.target, receiverID, investorID); expect(timer).to.be.eq(0); }); }); @@ -457,17 +463,17 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { const investorID = await context.suite.identityRegistry.identity(from); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 10], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - const counter = await context.suite.complianceModule.getMonthlyCounter(context.suite.compliance.address, receiverID, investorID); + const counter = await context.suite.complianceModule.getMonthlyCounter(context.suite.compliance.target, receiverID, investorID); expect(counter).to.be.eq(0); - const timer = await context.suite.complianceModule.getMonthlyTimer(context.suite.compliance.address, receiverID, investorID); + const timer = await context.suite.complianceModule.getMonthlyTimer(context.suite.compliance.target, receiverID, investorID); expect(timer).to.be.eq(0); }); }); @@ -484,7 +490,7 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { '0x0000000000000000000000000000000000000000', context.accounts.bobWallet.address, 100, - context.suite.compliance.address, + context.suite.compliance.target, ), ).to.be.true; }); @@ -498,7 +504,7 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { context.accounts.tokenAgent.address, context.accounts.bobWallet.address, 100, - context.suite.compliance.address, + context.suite.compliance.target, ), ).to.be.true; }); @@ -512,7 +518,7 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { context.accounts.aliceWallet.address, context.accounts.bobWallet.address, 100, - context.suite.compliance.address, + context.suite.compliance.target, ), ).to.be.true; }); @@ -527,18 +533,19 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { const senderExchangeID = await context.suite.identityRegistry.identity(from); const receiverExchangeID = await context.suite.identityRegistry.identity(to); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(senderExchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as ExchangeMonthlyLimits).addExchangeID(senderExchangeID); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(receiverExchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as ExchangeMonthlyLimits).addExchangeID(receiverExchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ - 'function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)', - ]).encodeFunctionData('setExchangeMonthlyLimit', [receiverExchangeID, 90]), - context.suite.complianceModule.address, + new ethers.Interface(['function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)']).encodeFunctionData( + 'setExchangeMonthlyLimit', + [receiverExchangeID, 90], + ), + context.suite.complianceModule.target, ); - expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.address)).to.be.true; + expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.target)).to.be.true; }); }); @@ -549,16 +556,17 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { const to = context.accounts.bobWallet.address; const exchangeID = await context.suite.identityRegistry.identity(to); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(exchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as ExchangeMonthlyLimits).addExchangeID(exchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ - 'function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)', - ]).encodeFunctionData('setExchangeMonthlyLimit', [exchangeID, 90]), - context.suite.complianceModule.address, + new ethers.Interface(['function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)']).encodeFunctionData( + 'setExchangeMonthlyLimit', + [exchangeID, 90], + ), + context.suite.complianceModule.target, ); - expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.address)).to.be.false; + expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.target)).to.be.false; }); }); @@ -569,16 +577,17 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { const to = context.accounts.bobWallet.address; const exchangeID = await context.suite.identityRegistry.identity(to); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(exchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as ExchangeMonthlyLimits).addExchangeID(exchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ - 'function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)', - ]).encodeFunctionData('setExchangeMonthlyLimit', [exchangeID, 150]), - context.suite.complianceModule.address, + new ethers.Interface(['function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)']).encodeFunctionData( + 'setExchangeMonthlyLimit', + [exchangeID, 150], + ), + context.suite.complianceModule.target, ); - expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.address)).to.be.true; + expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.target)).to.be.true; }); }); @@ -589,24 +598,25 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { const to = context.accounts.bobWallet.address; const exchangeID = await context.suite.identityRegistry.identity(to); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(exchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as ExchangeMonthlyLimits).addExchangeID(exchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ - 'function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)', - ]).encodeFunctionData('setExchangeMonthlyLimit', [exchangeID, 150]), - context.suite.complianceModule.address, + new ethers.Interface(['function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)']).encodeFunctionData( + 'setExchangeMonthlyLimit', + [exchangeID, 150], + ), + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 100], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.address)).to.be.false; + expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.target)).to.be.false; }); }); @@ -617,24 +627,25 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { const to = context.accounts.bobWallet.address; const exchangeID = await context.suite.identityRegistry.identity(to); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(exchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as ExchangeMonthlyLimits).addExchangeID(exchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ - 'function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)', - ]).encodeFunctionData('setExchangeMonthlyLimit', [exchangeID, 150]), - context.suite.complianceModule.address, + new ethers.Interface(['function setExchangeMonthlyLimit(address _exchangeID, uint256 _newExchangeMonthlyLimit)']).encodeFunctionData( + 'setExchangeMonthlyLimit', + [exchangeID, 150], + ), + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 100], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - expect(await context.suite.complianceModule.moduleCheck(from, to, 40, context.suite.compliance.address)).to.be.true; + expect(await context.suite.complianceModule.moduleCheck(from, to, 40, context.suite.compliance.target)).to.be.true; }); }); }); @@ -657,11 +668,11 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ + new ethers.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ context.accounts.anotherWallet.address, 10, ]), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ), ).to.eventually.be.fulfilled; }); @@ -685,11 +696,11 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ + new ethers.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ context.accounts.anotherWallet.address, 10, ]), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ), ).to.eventually.be.fulfilled; }); diff --git a/test/compliances/module-max-balance.test.ts b/test/compliances/module-max-balance.test.ts index 73d37199..b76f3f15 100644 --- a/test/compliances/module-max-balance.test.ts +++ b/test/compliances/module-max-balance.test.ts @@ -8,13 +8,13 @@ async function deployMaxBalanceFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); const module = await ethers.deployContract('MaxBalanceModule'); - const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); - const complianceModule = await ethers.getContractAt('MaxBalanceModule', proxy.address); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('MaxBalanceModule', proxy.target); await context.suite.token.connect(context.accounts.tokenAgent).burn(context.accounts.aliceWallet.address, 1000); await context.suite.token.connect(context.accounts.tokenAgent).burn(context.accounts.bobWallet.address, 500); - await context.suite.compliance.bindToken(context.suite.token.address); - await context.suite.compliance.addModule(complianceModule.address); + await context.suite.compliance.bindToken(context.suite.token.target); + await context.suite.compliance.addModule(complianceModule.target); return { ...context, @@ -29,8 +29,8 @@ describe('Compliance Module: MaxBalance', () => { it('should deploy the MaxBalance contract and bind it to the compliance', async () => { const context = await loadFixture(deployMaxBalanceFullSuite); - expect(context.suite.complianceModule.address).not.to.be.undefined; - expect(await context.suite.compliance.isModuleBound(context.suite.complianceModule.address)).to.be.true; + expect(context.suite.complianceModule.target).not.to.be.undefined; + expect(await context.suite.compliance.isModuleBound(context.suite.complianceModule.target)).to.be.true; }); describe('.name', () => { @@ -54,7 +54,7 @@ describe('Compliance Module: MaxBalance', () => { it('should return false', async () => { const context = await loadFixture(deployMaxBalanceFullSuite); await context.suite.token.connect(context.accounts.tokenAgent).mint(context.accounts.aliceWallet.address, 1000); - expect(await context.suite.complianceModule.canComplianceBind(context.suite.compliance.address)).to.be.false; + expect(await context.suite.complianceModule.canComplianceBind(context.suite.compliance.target)).to.be.false; }); }); @@ -65,9 +65,9 @@ describe('Compliance Module: MaxBalance', () => { await complianceModule .connect(context.accounts.deployer) - .preSetModuleState(context.suite.compliance.address, context.accounts.aliceWallet.address, 100); + .preSetModuleState(context.suite.compliance.target, context.accounts.aliceWallet.address, 100); - expect(await complianceModule.canComplianceBind(context.suite.compliance.address)).to.be.true; + expect(await complianceModule.canComplianceBind(context.suite.compliance.target)).to.be.true; }); }); }); @@ -77,7 +77,7 @@ describe('Compliance Module: MaxBalance', () => { const context = await loadFixture(deployMaxBalanceFullSuite); const complianceModule = await ethers.deployContract('MaxBalanceModule'); - expect(await complianceModule.canComplianceBind(context.suite.compliance.address)).to.be.true; + expect(await complianceModule.canComplianceBind(context.suite.compliance.target)).to.be.true; }); }); }); @@ -96,11 +96,11 @@ describe('Compliance Module: MaxBalance', () => { const context = await loadFixture(deployMaxBalanceFullSuite); const tx = await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [100]), - context.suite.complianceModule.address, + new ethers.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [100]), + context.suite.complianceModule.target, ); - await expect(tx).to.emit(context.suite.complianceModule, 'MaxBalanceSet').withArgs(context.suite.compliance.address, 100); + await expect(tx).to.emit(context.suite.complianceModule, 'MaxBalanceSet').withArgs(context.suite.compliance.target, 100); }); }); }); @@ -156,7 +156,7 @@ describe('Compliance Module: MaxBalance', () => { describe('when calling directly', () => { it('should revert', async () => { const context = await loadFixture(deployMaxBalanceFullSuite); - await expect(context.suite.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero)).to.revertedWith( + await expect(context.suite.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress)).to.revertedWith( 'Ownable: caller is not the owner', ); }); @@ -169,11 +169,14 @@ describe('Compliance Module: MaxBalance', () => { const newImplementation = await ethers.deployContract('MaxBalanceModule'); // when - await context.suite.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + await context.suite.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.target); + const target = context.suite.complianceModule.target; + + const address = typeof target === 'string' ? target : await target.getAddress(); // then - const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.complianceModule.address); - expect(implementationAddress).to.eq(newImplementation.address); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(address); + expect(implementationAddress).to.eq(newImplementation.target); }); }); }); @@ -185,7 +188,7 @@ describe('Compliance Module: MaxBalance', () => { await expect( context.suite.complianceModule .connect(context.accounts.aliceWallet) - .preSetModuleState(context.suite.compliance.address, context.accounts.aliceWallet.address, 100), + .preSetModuleState(context.suite.compliance.target, context.accounts.aliceWallet.address, 100), ).to.be.revertedWithCustomError(context.suite.complianceModule, `OnlyComplianceOwnerCanCall`); }); }); @@ -197,7 +200,7 @@ describe('Compliance Module: MaxBalance', () => { await expect( context.suite.complianceModule .connect(context.accounts.deployer) - .preSetModuleState(context.suite.compliance.address, context.accounts.aliceWallet.address, 100), + .preSetModuleState(context.suite.compliance.target, context.accounts.aliceWallet.address, 100), ).to.be.revertedWithCustomError(context.suite.complianceModule, `TokenAlreadyBound`); }); }); @@ -209,11 +212,11 @@ describe('Compliance Module: MaxBalance', () => { const tx = await complianceModule .connect(context.accounts.deployer) - .preSetModuleState(context.suite.compliance.address, context.accounts.aliceWallet.address, 100); + .preSetModuleState(context.suite.compliance.target, context.accounts.aliceWallet.address, 100); await expect(tx) .to.emit(complianceModule, 'IDBalancePreSet') - .withArgs(context.suite.compliance.address, context.accounts.aliceWallet.address, 100); + .withArgs(context.suite.compliance.target, context.accounts.aliceWallet.address, 100); }); }); }); @@ -224,7 +227,7 @@ describe('Compliance Module: MaxBalance', () => { it('should revert', async () => { const context = await loadFixture(deployMaxBalanceFullSuite); await expect( - context.suite.complianceModule.connect(context.accounts.aliceWallet).presetCompleted(context.suite.compliance.address), + context.suite.complianceModule.connect(context.accounts.aliceWallet).presetCompleted(context.suite.compliance.target), ).to.be.revertedWithCustomError(context.suite.complianceModule, `OnlyComplianceOwnerCanCall`); }); }); @@ -234,9 +237,9 @@ describe('Compliance Module: MaxBalance', () => { const context = await loadFixture(deployComplianceFixture); const complianceModule = await ethers.deployContract('MaxBalanceModule'); - await complianceModule.connect(context.accounts.deployer).presetCompleted(context.suite.compliance.address); + await complianceModule.connect(context.accounts.deployer).presetCompleted(context.suite.compliance.target); - expect(await complianceModule.canComplianceBind(context.suite.compliance.address)).to.be.true; + expect(await complianceModule.canComplianceBind(context.suite.compliance.target)).to.be.true; }); }); }); @@ -248,7 +251,7 @@ describe('Compliance Module: MaxBalance', () => { await expect( context.suite.complianceModule .connect(context.accounts.aliceWallet) - .batchPreSetModuleState(context.suite.compliance.address, [context.accounts.aliceWallet.address], [100]), + .batchPreSetModuleState(context.suite.compliance.target, [context.accounts.aliceWallet.address], [100]), ).to.be.revertedWithCustomError(context.suite.complianceModule, `OnlyComplianceOwnerCanCall`); }); }); @@ -258,7 +261,7 @@ describe('Compliance Module: MaxBalance', () => { it('should revert', async () => { const context = await loadFixture(deployMaxBalanceFullSuite); await expect( - context.suite.complianceModule.connect(context.accounts.deployer).batchPreSetModuleState(context.suite.compliance.address, [], []), + context.suite.complianceModule.connect(context.accounts.deployer).batchPreSetModuleState(context.suite.compliance.target, [], []), ).to.be.revertedWithCustomError(context.suite.complianceModule, `InvalidPresetValues`); }); }); @@ -270,7 +273,7 @@ describe('Compliance Module: MaxBalance', () => { context.suite.complianceModule .connect(context.accounts.deployer) .batchPreSetModuleState( - context.suite.compliance.address, + context.suite.compliance.target, [context.accounts.aliceWallet.address, context.accounts.bobWallet.address], [100], ), @@ -284,7 +287,7 @@ describe('Compliance Module: MaxBalance', () => { await expect( context.suite.complianceModule .connect(context.accounts.deployer) - .batchPreSetModuleState(context.suite.compliance.address, [context.accounts.aliceWallet.address], [100]), + .batchPreSetModuleState(context.suite.compliance.target, [context.accounts.aliceWallet.address], [100]), ).to.be.revertedWithCustomError(context.suite.complianceModule, `TokenAlreadyBound`); }); }); @@ -297,16 +300,16 @@ describe('Compliance Module: MaxBalance', () => { const tx = await complianceModule .connect(context.accounts.deployer) .batchPreSetModuleState( - context.suite.compliance.address, + context.suite.compliance.target, [context.accounts.aliceWallet.address, context.accounts.bobWallet.address], [100, 200], ); await expect(tx) .to.emit(complianceModule, 'IDBalancePreSet') - .withArgs(context.suite.compliance.address, context.accounts.aliceWallet.address, 100) + .withArgs(context.suite.compliance.target, context.accounts.aliceWallet.address, 100) .to.emit(complianceModule, 'IDBalancePreSet') - .withArgs(context.suite.compliance.address, context.accounts.bobWallet.address, 200); + .withArgs(context.suite.compliance.target, context.accounts.bobWallet.address, 200); }); }); }); @@ -331,38 +334,35 @@ describe('Compliance Module: MaxBalance', () => { const to = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), - context.suite.complianceModule.address, + new ethers.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleMintAction(address _to, uint256 _value)']).encodeFunctionData('moduleMintAction', [ - from, - 150, - ]), - context.suite.complianceModule.address, + new ethers.Interface(['function moduleMintAction(address _to, uint256 _value)']).encodeFunctionData('moduleMintAction', [from, 150]), + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [100]), - context.suite.complianceModule.address, + new ethers.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [100]), + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 40], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 80], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ), ).to.be.revertedWithCustomError(context.suite.complianceModule, `MaxBalanceExceeded`); }); @@ -377,30 +377,27 @@ describe('Compliance Module: MaxBalance', () => { const receiverIdentity = await context.suite.identityRegistry.identity(context.accounts.bobWallet.address); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), - context.suite.complianceModule.address, + new ethers.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleMintAction(address _to, uint256 _value)']).encodeFunctionData('moduleMintAction', [ - from, - 150, - ]), - context.suite.complianceModule.address, + new ethers.Interface(['function moduleMintAction(address _to, uint256 _value)']).encodeFunctionData('moduleMintAction', [from, 150]), + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 120], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - const senderBalance = await context.suite.complianceModule.getIDBalance(context.suite.compliance.address, senderIdentity); + const senderBalance = await context.suite.complianceModule.getIDBalance(context.suite.compliance.target, senderIdentity); expect(senderBalance).to.be.eq(30); - const receiverBalance = await context.suite.complianceModule.getIDBalance(context.suite.compliance.address, receiverIdentity); + const receiverBalance = await context.suite.complianceModule.getIDBalance(context.suite.compliance.target, receiverIdentity); expect(receiverBalance).to.be.eq(120); }); }); @@ -424,17 +421,14 @@ describe('Compliance Module: MaxBalance', () => { const to = context.accounts.aliceWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), - context.suite.complianceModule.address, + new ethers.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), + context.suite.complianceModule.target, ); await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleMintAction(address _to, uint256 _value)']).encodeFunctionData('moduleMintAction', [ - to, - 160, - ]), - context.suite.complianceModule.address, + new ethers.Interface(['function moduleMintAction(address _to, uint256 _value)']).encodeFunctionData('moduleMintAction', [to, 160]), + context.suite.complianceModule.target, ), ).to.be.revertedWithCustomError(context.suite.complianceModule, `MaxBalanceExceeded`); }); @@ -447,16 +441,16 @@ describe('Compliance Module: MaxBalance', () => { const receiverIdentity = await context.suite.identityRegistry.identity(context.accounts.aliceWallet.address); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), - context.suite.complianceModule.address, + new ethers.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleMintAction(address _to, uint256 _value)']).encodeFunctionData('moduleMintAction', [to, 150]), - context.suite.complianceModule.address, + new ethers.Interface(['function moduleMintAction(address _to, uint256 _value)']).encodeFunctionData('moduleMintAction', [to, 150]), + context.suite.complianceModule.target, ); - const receiverBalance = await context.suite.complianceModule.getIDBalance(context.suite.compliance.address, receiverIdentity); + const receiverBalance = await context.suite.complianceModule.getIDBalance(context.suite.compliance.target, receiverIdentity); expect(receiverBalance).to.be.eq(150); }); }); @@ -480,21 +474,21 @@ describe('Compliance Module: MaxBalance', () => { const senderIdentity = await context.suite.identityRegistry.identity(context.accounts.aliceWallet.address); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), - context.suite.complianceModule.address, + new ethers.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleMintAction(address _to, uint256 _value)']).encodeFunctionData('moduleMintAction', [from, 100]), - context.suite.complianceModule.address, + new ethers.Interface(['function moduleMintAction(address _to, uint256 _value)']).encodeFunctionData('moduleMintAction', [from, 100]), + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleBurnAction(address _from, uint256 _value)']).encodeFunctionData('moduleBurnAction', [from, 90]), - context.suite.complianceModule.address, + new ethers.Interface(['function moduleBurnAction(address _from, uint256 _value)']).encodeFunctionData('moduleBurnAction', [from, 90]), + context.suite.complianceModule.target, ); - const senderBalance = await context.suite.complianceModule.getIDBalance(context.suite.compliance.address, senderIdentity); + const senderBalance = await context.suite.complianceModule.getIDBalance(context.suite.compliance.target, senderIdentity); expect(senderBalance).to.be.eq(10); }); }); @@ -508,13 +502,11 @@ describe('Compliance Module: MaxBalance', () => { const from = context.accounts.aliceWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), - context.suite.complianceModule.address, + new ethers.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), + context.suite.complianceModule.target, ); - await expect(context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address)).to.revertedWith( - 'identity not found', - ); + await expect(context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.target)).to.revertedWith('identity not found'); }); }); @@ -525,11 +517,11 @@ describe('Compliance Module: MaxBalance', () => { const from = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), - context.suite.complianceModule.address, + new ethers.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), + context.suite.complianceModule.target, ); - const result = await context.suite.complianceModule.moduleCheck(from, to, 170, context.suite.compliance.address); + const result = await context.suite.complianceModule.moduleCheck(from, to, 170, context.suite.compliance.target); expect(result).to.be.false; }); }); @@ -541,16 +533,16 @@ describe('Compliance Module: MaxBalance', () => { const from = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), - context.suite.complianceModule.address, + new ethers.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleMintAction(address _to, uint256 _value)']).encodeFunctionData('moduleMintAction', [to, 100]), - context.suite.complianceModule.address, + new ethers.Interface(['function moduleMintAction(address _to, uint256 _value)']).encodeFunctionData('moduleMintAction', [to, 100]), + context.suite.complianceModule.target, ); - const result = await context.suite.complianceModule.moduleCheck(from, to, 70, context.suite.compliance.address); + const result = await context.suite.complianceModule.moduleCheck(from, to, 70, context.suite.compliance.target); expect(result).to.be.false; }); }); @@ -562,11 +554,11 @@ describe('Compliance Module: MaxBalance', () => { const from = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), - context.suite.complianceModule.address, + new ethers.Interface(['function setMaxBalance(uint256 _max)']).encodeFunctionData('setMaxBalance', [150]), + context.suite.complianceModule.target, ); - const result = await context.suite.complianceModule.moduleCheck(from, to, 70, context.suite.compliance.address); + const result = await context.suite.complianceModule.moduleCheck(from, to, 70, context.suite.compliance.target); expect(result).to.be.true; }); }); diff --git a/test/compliances/module-supply-limit.test.ts b/test/compliances/module-supply-limit.test.ts index a3c800f1..85ae061a 100644 --- a/test/compliances/module-supply-limit.test.ts +++ b/test/compliances/module-supply-limit.test.ts @@ -8,10 +8,10 @@ async function deploySupplyLimitFixture() { const context = await loadFixture(deployComplianceFixture); const module = await ethers.deployContract('SupplyLimitModule'); - const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); - const complianceModule = await ethers.getContractAt('SupplyLimitModule', proxy.address); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('SupplyLimitModule', proxy.target); - await context.suite.compliance.addModule(complianceModule.address); + await context.suite.compliance.addModule(complianceModule.target); return { ...context, @@ -26,8 +26,8 @@ async function deploySupplyLimitFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); const SupplyLimitModule = await ethers.getContractFactory('SupplyLimitModule'); const complianceModule = await upgrades.deployProxy(SupplyLimitModule, []); - await context.suite.compliance.bindToken(context.suite.token.address); - await context.suite.compliance.addModule(complianceModule.address); + await context.suite.compliance.bindToken(context.suite.token.target); + await context.suite.compliance.addModule(complianceModule.target); return { ...context, @@ -42,8 +42,8 @@ describe('Compliance Module: SupplyLimit', () => { it('should deploy the SupplyLimit contract and bind it to the compliance', async () => { const context = await loadFixture(deploySupplyLimitFixture); - expect(context.suite.complianceModule.address).not.to.be.undefined; - expect(await context.suite.compliance.isModuleBound(context.suite.complianceModule.address)).to.be.true; + expect(context.suite.complianceModule.target).not.to.be.undefined; + expect(await context.suite.compliance.isModuleBound(context.suite.complianceModule.target)).to.be.true; }); describe('.name()', () => { @@ -64,7 +64,7 @@ describe('Compliance Module: SupplyLimit', () => { describe('.canComplianceBind', () => { it('should return true', async () => { const context = await loadFixture(deploySupplyLimitFullSuite); - expect(await context.suite.complianceModule.canComplianceBind(context.suite.compliance.address)).to.be.true; + expect(await context.suite.complianceModule.canComplianceBind(context.suite.compliance.target)).to.be.true; }); }); @@ -119,7 +119,7 @@ describe('Compliance Module: SupplyLimit', () => { describe('when calling directly', () => { it('should revert', async () => { const context = await loadFixture(deploySupplyLimitFixture); - await expect(context.suite.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero)).to.revertedWith( + await expect(context.suite.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress)).to.revertedWith( 'Ownable: caller is not the owner', ); }); @@ -132,11 +132,14 @@ describe('Compliance Module: SupplyLimit', () => { const newImplementation = await ethers.deployContract('SupplyLimitModule'); // when - await context.suite.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + await context.suite.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.target); + const target = context.suite.complianceModule.target; + + const address = typeof target === 'string' ? target : await target.getAddress(); // then - const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.complianceModule.address); - expect(implementationAddress).to.eq(newImplementation.address); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(address); + expect(implementationAddress).to.eq(newImplementation.target); }); }); }); @@ -155,11 +158,11 @@ describe('Compliance Module: SupplyLimit', () => { const context = await loadFixture(deploySupplyLimitFixture); const tx = await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setSupplyLimit(uint256 _limit)']).encodeFunctionData('setSupplyLimit', [100]), - context.suite.complianceModule.address, + new ethers.Interface(['function setSupplyLimit(uint256 _limit)']).encodeFunctionData('setSupplyLimit', [100]), + context.suite.complianceModule.target, ); - await expect(tx).to.emit(context.suite.complianceModule, 'SupplyLimitSet').withArgs(context.suite.compliance.address, 100); + await expect(tx).to.emit(context.suite.complianceModule, 'SupplyLimitSet').withArgs(context.suite.compliance.target, 100); }); }); }); @@ -169,10 +172,10 @@ describe('Compliance Module: SupplyLimit', () => { it('should return', async () => { const context = await loadFixture(deploySupplyLimitFixture); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setSupplyLimit(uint256 _limit)']).encodeFunctionData('setSupplyLimit', [1600]), - context.suite.complianceModule.address, + new ethers.Interface(['function setSupplyLimit(uint256 _limit)']).encodeFunctionData('setSupplyLimit', [1600]), + context.suite.complianceModule.target, ); - const supplyLimit = await context.suite.complianceModule.getSupplyLimit(context.suite.compliance.address); + const supplyLimit = await context.suite.complianceModule.getSupplyLimit(context.suite.compliance.target); expect(supplyLimit).to.be.eq(1600); }); }); @@ -187,11 +190,11 @@ describe('Compliance Module: SupplyLimit', () => { const from = zeroAddress; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setSupplyLimit(uint256 _limit)']).encodeFunctionData('setSupplyLimit', [1600]), - context.suite.complianceModule.address, + new ethers.Interface(['function setSupplyLimit(uint256 _limit)']).encodeFunctionData('setSupplyLimit', [1600]), + context.suite.complianceModule.target, ); - const result = await context.suite.complianceModule.moduleCheck(from, to, 101, context.suite.compliance.address); + const result = await context.suite.complianceModule.moduleCheck(from, to, 101, context.suite.compliance.target); expect(result).to.be.false; }); }); @@ -203,11 +206,11 @@ describe('Compliance Module: SupplyLimit', () => { const from = zeroAddress; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setSupplyLimit(uint256 _limit)']).encodeFunctionData('setSupplyLimit', [1600]), - context.suite.complianceModule.address, + new ethers.Interface(['function setSupplyLimit(uint256 _limit)']).encodeFunctionData('setSupplyLimit', [1600]), + context.suite.complianceModule.target, ); - const result = await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.address); + const result = await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.target); expect(result).to.be.true; }); }); @@ -229,11 +232,11 @@ describe('Compliance Module: SupplyLimit', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [context.accounts.anotherWallet.address, context.accounts.anotherWallet.address, 10], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ), ).to.eventually.be.fulfilled; }); @@ -257,11 +260,11 @@ describe('Compliance Module: SupplyLimit', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ + new ethers.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ context.accounts.anotherWallet.address, 10, ]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ), ).to.eventually.be.fulfilled; }); @@ -285,11 +288,11 @@ describe('Compliance Module: SupplyLimit', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ + new ethers.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ context.accounts.anotherWallet.address, 10, ]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ), ).to.eventually.be.fulfilled; }); diff --git a/test/compliances/module-time-exchange-limits.test.ts b/test/compliances/module-time-exchange-limits.test.ts index 4362b4da..0afa8df3 100644 --- a/test/compliances/module-time-exchange-limits.test.ts +++ b/test/compliances/module-time-exchange-limits.test.ts @@ -3,15 +3,16 @@ import { ethers, upgrades } from 'hardhat'; import { expect } from 'chai'; import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; +import { TimeExchangeLimitsModule } from '../../typechain-types'; async function deployTimeExchangeLimitsFixture() { const context = await loadFixture(deployComplianceFixture); const module = await ethers.deployContract('TimeExchangeLimitsModule'); - const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); - const complianceModule = await ethers.getContractAt('TimeExchangeLimitsModule', proxy.address); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('TimeExchangeLimitsModule', proxy.target); - await context.suite.compliance.addModule(complianceModule.address); + await context.suite.compliance.addModule(complianceModule.target); return { ...context, @@ -24,10 +25,10 @@ async function deployTimeExchangeLimitsFixture() { async function deployTimeExchangeLimitsFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); - const TimeExchangeLimitsModule = await ethers.getContractFactory('TimeExchangeLimitsModule'); - const complianceModule = await upgrades.deployProxy(TimeExchangeLimitsModule, []); - await context.suite.compliance.bindToken(context.suite.token.address); - await context.suite.compliance.addModule(complianceModule.address); + const module = await ethers.getContractFactory('TimeExchangeLimitsModule'); + const complianceModule = await upgrades.deployProxy(module, []); + await context.suite.compliance.bindToken(context.suite.token.target); + await context.suite.compliance.addModule(complianceModule.target); return { ...context, @@ -42,8 +43,8 @@ describe('Compliance Module: TimeExchangeLimits', () => { it('should deploy the TimeExchangeLimits contract and bind it to the compliance', async () => { const context = await loadFixture(deployTimeExchangeLimitsFixture); - expect(context.contracts.complianceModule.address).not.to.be.undefined; - expect(await context.contracts.compliance.isModuleBound(context.contracts.complianceModule.address)).to.be.true; + expect(context.contracts.complianceModule.target).not.to.be.undefined; + expect(await context.contracts.compliance.isModuleBound(context.contracts.complianceModule.target)).to.be.true; }); describe('.name()', () => { @@ -105,9 +106,9 @@ describe('Compliance Module: TimeExchangeLimits', () => { describe('when calling directly', () => { it('should revert', async () => { const context = await loadFixture(deployTimeExchangeLimitsFixture); - await expect( - context.contracts.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero), - ).to.revertedWith('Ownable: caller is not the owner'); + await expect(context.contracts.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress)).to.revertedWith( + 'Ownable: caller is not the owner', + ); }); }); @@ -118,11 +119,14 @@ describe('Compliance Module: TimeExchangeLimits', () => { const newImplementation = await ethers.deployContract('TimeExchangeLimitsModule'); // when - await context.contracts.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + await context.contracts.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.target); + const target = context.contracts.complianceModule.target; + + const address = typeof target === 'string' ? target : await target.getAddress(); // then - const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.contracts.complianceModule.address); - expect(implementationAddress).to.eq(newImplementation.address); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(address); + expect(implementationAddress).to.eq(newImplementation.target); }); }); }); @@ -147,17 +151,17 @@ describe('Compliance Module: TimeExchangeLimits', () => { const exchangeID = context.accounts.anotherWallet.address; const tx = await context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface([ + new ethers.Interface([ 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 1, limitValue: 100 }]), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ); await expect(tx) .to.emit(context.contracts.complianceModule, 'ExchangeLimitUpdated') - .withArgs(context.contracts.compliance.address, exchangeID, 100, 1); + .withArgs(context.contracts.compliance.target, exchangeID, 100, 1); - const limits = await context.contracts.complianceModule.getExchangeLimits(context.suite.compliance.address, exchangeID); + const limits = await context.contracts.complianceModule.getExchangeLimits(context.suite.compliance.target, exchangeID); expect(limits.length).to.be.eq(1); }); }); @@ -167,38 +171,38 @@ describe('Compliance Module: TimeExchangeLimits', () => { const exchangeID = context.accounts.anotherWallet.address; await context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface([ + new ethers.Interface([ 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 1, limitValue: 100 }]), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ); await context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface([ + new ethers.Interface([ 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 2, limitValue: 100 }]), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ); await context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface([ + new ethers.Interface([ 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 3, limitValue: 100 }]), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ); await context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface([ + new ethers.Interface([ 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 4, limitValue: 100 }]), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ); await expect( context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface([ + new ethers.Interface([ 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 5, limitValue: 100 }]), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ), ).to.be.revertedWithCustomError(context.contracts.complianceModule, `LimitsArraySizeExceeded`); }); @@ -211,24 +215,26 @@ describe('Compliance Module: TimeExchangeLimits', () => { const exchangeID = context.accounts.anotherWallet.address; await context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface([ - 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', - ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 1, limitValue: 90 }]), - context.contracts.complianceModule.address, + new ethers.Interface(['function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))']).encodeFunctionData( + 'setExchangeLimit', + [exchangeID, { limitTime: 1, limitValue: 90 }], + ), + context.contracts.complianceModule.target, ); const tx = await context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface([ - 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', - ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 1, limitValue: 100 }]), - context.contracts.complianceModule.address, + new ethers.Interface(['function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))']).encodeFunctionData( + 'setExchangeLimit', + [exchangeID, { limitTime: 1, limitValue: 100 }], + ), + context.contracts.complianceModule.target, ); await expect(tx) .to.emit(context.contracts.complianceModule, 'ExchangeLimitUpdated') - .withArgs(context.contracts.compliance.address, exchangeID, 100, 1); + .withArgs(context.contracts.compliance.target, exchangeID, 100, 1); - const limits = await context.contracts.complianceModule.getExchangeLimits(context.suite.compliance.address, exchangeID); + const limits = await context.contracts.complianceModule.getExchangeLimits(context.suite.compliance.target, exchangeID); expect(limits.length).to.be.eq(1); expect(limits[0][0]).to.be.eq(1); expect(limits[0][1].toString()).to.be.eq('100'); @@ -243,13 +249,14 @@ describe('Compliance Module: TimeExchangeLimits', () => { const exchangeID = context.accounts.anotherWallet.address; await context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface([ - 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', - ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 1, limitValue: 100 }]), - context.contracts.complianceModule.address, + new ethers.Interface(['function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))']).encodeFunctionData( + 'setExchangeLimit', + [exchangeID, { limitTime: 1, limitValue: 100 }], + ), + context.contracts.complianceModule.target, ); - const limits = await context.contracts.complianceModule.getExchangeLimits(context.suite.compliance.address, exchangeID); + const limits = await context.contracts.complianceModule.getExchangeLimits(context.suite.compliance.target, exchangeID); expect(limits.length).to.be.eq(1); expect(limits[0][0]).to.be.eq(1); expect(limits[0][1].toString()).to.be.eq('100'); @@ -264,24 +271,25 @@ describe('Compliance Module: TimeExchangeLimits', () => { const exchangeID = await context.suite.identityRegistry.identity(to); const investorID = await context.suite.identityRegistry.identity(from); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(exchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as TimeExchangeLimitsModule).addExchangeID(exchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ - 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', - ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 10000, limitValue: 100 }]), - context.suite.complianceModule.address, + new ethers.Interface(['function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))']).encodeFunctionData( + 'setExchangeLimit', + [exchangeID, { limitTime: 10000, limitValue: 100 }], + ), + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 10], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - const counter = await context.suite.complianceModule.getExchangeCounter(context.suite.compliance.address, exchangeID, investorID, 10000); + const counter = await context.suite.complianceModule.getExchangeCounter(context.suite.compliance.target, exchangeID, investorID, 10000); expect(counter.value).to.be.eq(10); }); }); @@ -410,29 +418,24 @@ describe('Compliance Module: TimeExchangeLimits', () => { const exchangeID = await context.suite.identityRegistry.identity(to); const investorID = await context.suite.identityRegistry.identity(from); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(exchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as TimeExchangeLimitsModule).addExchangeID(exchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ + new ethers.Interface([ 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 10000, limitValue: 100 }]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 10], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - const counter = await context.suite.complianceModule.getExchangeCounter( - context.suite.compliance.address, - exchangeID, - investorID, - 10000, - ); + const counter = await context.suite.complianceModule.getExchangeCounter(context.suite.compliance.target, exchangeID, investorID, 10000); expect(counter.value).to.be.eq(10); }); }); @@ -445,29 +448,24 @@ describe('Compliance Module: TimeExchangeLimits', () => { const exchangeID = await context.suite.identityRegistry.identity(to); const investorID = await context.suite.identityRegistry.identity(from); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(exchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as TimeExchangeLimitsModule).addExchangeID(exchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ + new ethers.Interface([ 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 10000, limitValue: 100 }]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 10], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - const counter = await context.suite.complianceModule.getExchangeCounter( - context.suite.compliance.address, - exchangeID, - investorID, - 10000, - ); + const counter = await context.suite.complianceModule.getExchangeCounter(context.suite.compliance.target, exchangeID, investorID, 10000); expect(counter.timer).to.be.gt(0); }); }); @@ -479,44 +477,39 @@ describe('Compliance Module: TimeExchangeLimits', () => { const exchangeID = await context.suite.identityRegistry.identity(to); const investorID = await context.suite.identityRegistry.identity(from); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(exchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as TimeExchangeLimitsModule).addExchangeID(exchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ + new ethers.Interface([ 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 10000, limitValue: 100 }]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 10], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); const previousCounter = await context.suite.complianceModule.getExchangeCounter( - context.suite.compliance.address, + context.suite.compliance.target, exchangeID, investorID, 10000, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 11], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - const counter = await context.suite.complianceModule.getExchangeCounter( - context.suite.compliance.address, - exchangeID, - investorID, - 10000, - ); + const counter = await context.suite.complianceModule.getExchangeCounter(context.suite.compliance.target, exchangeID, investorID, 10000); expect(counter.timer).to.be.eq(previousCounter.timer); }); }); @@ -530,24 +523,24 @@ describe('Compliance Module: TimeExchangeLimits', () => { const exchangeID = await context.suite.identityRegistry.identity(to); const investorID = await context.suite.identityRegistry.identity(from); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(exchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as TimeExchangeLimitsModule).addExchangeID(exchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ + new ethers.Interface([ 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 10000, limitValue: 100 }]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 10], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - const counter = await context.suite.complianceModule.getExchangeCounter(context.suite.compliance.address, exchangeID, investorID, 10000); + const counter = await context.suite.complianceModule.getExchangeCounter(context.suite.compliance.target, exchangeID, investorID, 10000); expect(counter.timer).to.be.eq(0); expect(counter.value).to.be.eq(0); }); @@ -564,21 +557,21 @@ describe('Compliance Module: TimeExchangeLimits', () => { const investorID = await context.suite.identityRegistry.identity(from); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ + new ethers.Interface([ 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', ]).encodeFunctionData('setExchangeLimit', [receiverID, { limitTime: 10000, limitValue: 100 }]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 10], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - const counter = await context.suite.complianceModule.getExchangeCounter(context.suite.compliance.address, receiverID, investorID, 10000); + const counter = await context.suite.complianceModule.getExchangeCounter(context.suite.compliance.target, receiverID, investorID, 10000); expect(counter.timer).to.be.eq(0); expect(counter.value).to.be.eq(0); }); @@ -592,24 +585,24 @@ describe('Compliance Module: TimeExchangeLimits', () => { const receiverID = await context.suite.identityRegistry.identity(to); const investorID = await context.suite.identityRegistry.identity(from); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(receiverID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as TimeExchangeLimitsModule).addExchangeID(receiverID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ + new ethers.Interface([ 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', ]).encodeFunctionData('setExchangeLimit', [receiverID, { limitTime: 10000, limitValue: 100 }]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 10], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - const counter = await context.suite.complianceModule.getExchangeCounter(context.suite.compliance.address, receiverID, investorID, 10000); + const counter = await context.suite.complianceModule.getExchangeCounter(context.suite.compliance.target, receiverID, investorID, 10000); expect(counter.timer).to.be.eq(0); expect(counter.value).to.be.eq(0); }); @@ -628,7 +621,7 @@ describe('Compliance Module: TimeExchangeLimits', () => { describe('.canComplianceBind', () => { it('should return true', async () => { const context = await loadFixture(deployTimeExchangeLimitsFullSuite); - expect(await context.suite.complianceModule.canComplianceBind(context.suite.compliance.address)).to.be.true; + expect(await context.suite.complianceModule.canComplianceBind(context.suite.compliance.target)).to.be.true; }); }); @@ -641,7 +634,7 @@ describe('Compliance Module: TimeExchangeLimits', () => { '0x0000000000000000000000000000000000000000', context.accounts.bobWallet.address, 100, - context.suite.compliance.address, + context.suite.compliance.target, ), ).to.be.true; }); @@ -655,7 +648,7 @@ describe('Compliance Module: TimeExchangeLimits', () => { context.accounts.tokenAgent.address, context.accounts.bobWallet.address, 100, - context.suite.compliance.address, + context.suite.compliance.target, ), ).to.be.true; }); @@ -669,7 +662,7 @@ describe('Compliance Module: TimeExchangeLimits', () => { context.accounts.aliceWallet.address, context.accounts.bobWallet.address, 100, - context.suite.compliance.address, + context.suite.compliance.target, ), ).to.be.true; }); @@ -684,18 +677,19 @@ describe('Compliance Module: TimeExchangeLimits', () => { const senderExchangeID = await context.suite.identityRegistry.identity(from); const receiverExchangeID = await context.suite.identityRegistry.identity(to); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(receiverExchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as TimeExchangeLimitsModule).addExchangeID(receiverExchangeID); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(senderExchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as TimeExchangeLimitsModule).addExchangeID(senderExchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ - 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', - ]).encodeFunctionData('setExchangeLimit', [receiverExchangeID, { limitTime: 10000, limitValue: 90 }]), - context.suite.complianceModule.address, + new ethers.Interface(['function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))']).encodeFunctionData( + 'setExchangeLimit', + [receiverExchangeID, { limitTime: 10000, limitValue: 90 }], + ), + context.suite.complianceModule.target, ); - expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.address)).to.be.true; + expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.target)).to.be.true; }); }); @@ -706,16 +700,17 @@ describe('Compliance Module: TimeExchangeLimits', () => { const to = context.accounts.bobWallet.address; const exchangeID = await context.suite.identityRegistry.identity(to); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(exchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as TimeExchangeLimitsModule).addExchangeID(exchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ - 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', - ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 10000, limitValue: 90 }]), - context.suite.complianceModule.address, + new ethers.Interface(['function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))']).encodeFunctionData( + 'setExchangeLimit', + [exchangeID, { limitTime: 10000, limitValue: 90 }], + ), + context.suite.complianceModule.target, ); - expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.address)).to.be.false; + expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.target)).to.be.false; }); }); @@ -726,16 +721,17 @@ describe('Compliance Module: TimeExchangeLimits', () => { const to = context.accounts.bobWallet.address; const exchangeID = await context.suite.identityRegistry.identity(to); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(exchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as TimeExchangeLimitsModule).addExchangeID(exchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ - 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', - ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 10000, limitValue: 150 }]), - context.suite.complianceModule.address, + new ethers.Interface(['function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))']).encodeFunctionData( + 'setExchangeLimit', + [exchangeID, { limitTime: 10000, limitValue: 150 }], + ), + context.suite.complianceModule.target, ); - expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.address)).to.be.true; + expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.target)).to.be.true; }); }); @@ -746,24 +742,25 @@ describe('Compliance Module: TimeExchangeLimits', () => { const to = context.accounts.bobWallet.address; const exchangeID = await context.suite.identityRegistry.identity(to); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(exchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as TimeExchangeLimitsModule).addExchangeID(exchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ - 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', - ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 10000, limitValue: 150 }]), - context.suite.complianceModule.address, + new ethers.Interface(['function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))']).encodeFunctionData( + 'setExchangeLimit', + [exchangeID, { limitTime: 10000, limitValue: 150 }], + ), + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 100], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.address)).to.be.false; + expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.target)).to.be.false; }); }); @@ -774,24 +771,25 @@ describe('Compliance Module: TimeExchangeLimits', () => { const to = context.accounts.bobWallet.address; const exchangeID = await context.suite.identityRegistry.identity(to); - await context.suite.complianceModule.connect(context.accounts.deployer).addExchangeID(exchangeID); + await (context.suite.complianceModule.connect(context.accounts.deployer) as TimeExchangeLimitsModule).addExchangeID(exchangeID); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface([ - 'function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))', - ]).encodeFunctionData('setExchangeLimit', [exchangeID, { limitTime: 10000, limitValue: 150 }]), - context.suite.complianceModule.address, + new ethers.Interface(['function setExchangeLimit(address _exchangeID, tuple(uint32 limitTime, uint256 limitValue))']).encodeFunctionData( + 'setExchangeLimit', + [exchangeID, { limitTime: 10000, limitValue: 150 }], + ), + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 100], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - expect(await context.suite.complianceModule.moduleCheck(from, to, 40, context.suite.compliance.address)).to.be.true; + expect(await context.suite.complianceModule.moduleCheck(from, to, 40, context.suite.compliance.target)).to.be.true; }); }); }); @@ -814,11 +812,11 @@ describe('Compliance Module: TimeExchangeLimits', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ + new ethers.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ context.accounts.anotherWallet.address, 10, ]), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ), ).to.eventually.be.fulfilled; }); @@ -842,11 +840,11 @@ describe('Compliance Module: TimeExchangeLimits', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ + new ethers.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ context.accounts.anotherWallet.address, 10, ]), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ), ).to.eventually.be.fulfilled; }); diff --git a/test/compliances/module-time-transfer-limits.test.ts b/test/compliances/module-time-transfer-limits.test.ts index c3120b61..8da100c3 100644 --- a/test/compliances/module-time-transfer-limits.test.ts +++ b/test/compliances/module-time-transfer-limits.test.ts @@ -3,13 +3,14 @@ import { ethers, upgrades } from 'hardhat'; import { expect } from 'chai'; import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; +import { TransferRestrictModule } from '../../typechain-types'; async function deployTimeTransferLimitsFixture() { const context = await loadFixture(deployComplianceFixture); const TimeTransfersLimitsModule = await ethers.getContractFactory('TimeTransfersLimitsModule'); const complianceModule = await upgrades.deployProxy(TimeTransfersLimitsModule, []); - await context.suite.compliance.addModule(complianceModule.address); + await context.suite.compliance.addModule(complianceModule.target); return { ...context, @@ -24,11 +25,11 @@ async function deployTimeTransferLimitsFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); const module = await ethers.deployContract('TimeTransfersLimitsModule'); - const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); - const complianceModule = await ethers.getContractAt('TimeTransfersLimitsModule', proxy.address); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('TimeTransfersLimitsModule', proxy.target); - await context.suite.compliance.bindToken(context.suite.token.address); - await context.suite.compliance.addModule(complianceModule.address); + await context.suite.compliance.bindToken(context.suite.token.target); + await context.suite.compliance.addModule(complianceModule.target); return { ...context, @@ -43,8 +44,8 @@ describe('Compliance Module: TimeTransferLimits', () => { it('should deploy the TimeTransferLimits contract and bind it to the compliance', async () => { const context = await loadFixture(deployTimeTransferLimitsFixture); - expect(context.contracts.complianceModule.address).not.to.be.undefined; - expect(await context.contracts.compliance.isModuleBound(context.contracts.complianceModule.address)).to.be.true; + expect(context.contracts.complianceModule.target).not.to.be.undefined; + expect(await context.contracts.compliance.isModuleBound(context.contracts.complianceModule.target)).to.be.true; }); describe('.name()', () => { @@ -82,7 +83,9 @@ describe('Compliance Module: TimeTransferLimits', () => { it('should revert', async () => { const context = await loadFixture(deployTimeTransferLimitsFixture); await expect( - context.contracts.complianceModule.connect(context.accounts.aliceWallet).transferOwnership(context.accounts.bobWallet.address), + (context.contracts.complianceModule.connect(context.accounts.aliceWallet) as TransferRestrictModule).transferOwnership( + context.accounts.bobWallet.address, + ), ).to.revertedWith('Ownable: caller is not the owner'); }); }); @@ -93,7 +96,9 @@ describe('Compliance Module: TimeTransferLimits', () => { const context = await loadFixture(deployTimeTransferLimitsFixture); // when - await context.contracts.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + await (context.contracts.complianceModule.connect(context.accounts.deployer) as TransferRestrictModule).transferOwnership( + context.accounts.bobWallet.address, + ); // then const owner = await context.contracts.complianceModule.owner(); @@ -107,7 +112,7 @@ describe('Compliance Module: TimeTransferLimits', () => { it('should revert', async () => { const context = await loadFixture(deployTimeTransferLimitsFixture); await expect( - context.contracts.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero), + (context.contracts.complianceModule.connect(context.accounts.aliceWallet) as TransferRestrictModule).upgradeTo(ethers.ZeroAddress), ).to.revertedWith('Ownable: caller is not the owner'); }); }); @@ -119,11 +124,14 @@ describe('Compliance Module: TimeTransferLimits', () => { const newImplementation = await ethers.deployContract('TimeTransfersLimitsModule'); // when - await context.contracts.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + await (context.contracts.complianceModule.connect(context.accounts.deployer) as TransferRestrictModule).upgradeTo(newImplementation.target); // then - const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.contracts.complianceModule.address); - expect(implementationAddress).to.eq(newImplementation.address); + const target = context.contracts.complianceModule.target; + + const address = typeof target === 'string' ? target : await target.getAddress(); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(address); + expect(implementationAddress).to.eq(newImplementation.target); }); }); }); @@ -145,23 +153,23 @@ describe('Compliance Module: TimeTransferLimits', () => { const context = await loadFixture(deployTimeTransferLimitsFixture); await context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 1, limitValue: 100 }], ), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ); const tx = await context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 1, limitValue: 50 }], ), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ); await expect(tx) .to.emit(context.contracts.complianceModule, 'TimeTransferLimitUpdated') - .withArgs(context.contracts.compliance.address, 1, 50); + .withArgs(context.contracts.compliance.target, 1, 50); }); }); @@ -171,40 +179,40 @@ describe('Compliance Module: TimeTransferLimits', () => { const context = await loadFixture(deployTimeTransferLimitsFixture); await context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 1, limitValue: 100 }], ), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ); await context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 7, limitValue: 1000 }], ), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ); await context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 30, limitValue: 10000 }], ), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ); await context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 365, limitValue: 100000 }], ), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ); await expect( context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 3650, limitValue: 1000000 }], ), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ), ).to.be.revertedWithCustomError(context.contracts.complianceModule, `LimitsArraySizeExceeded`); }); @@ -215,16 +223,16 @@ describe('Compliance Module: TimeTransferLimits', () => { const context = await loadFixture(deployTimeTransferLimitsFixture); const tx = await context.contracts.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 1, limitValue: 100 }], ), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ); await expect(tx) .to.emit(context.contracts.complianceModule, 'TimeTransferLimitUpdated') - .withArgs(context.contracts.compliance.address, 1, 100); + .withArgs(context.contracts.compliance.target, 1, 100); }); }); }); @@ -236,7 +244,7 @@ describe('Compliance Module: TimeTransferLimits', () => { it('should return empty array', async () => { const context = await loadFixture(deployTimeTransferLimitsFixture); - const limits = await context.contracts.complianceModule.getTimeTransferLimits(context.suite.compliance.address); + const limits = await context.contracts.complianceModule.getTimeTransferLimits(context.suite.compliance.target); expect(limits.length).to.be.eq(0); }); }); @@ -246,22 +254,22 @@ describe('Compliance Module: TimeTransferLimits', () => { const context = await loadFixture(deployTimeTransferLimitsFixture); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 10, limitValue: 120 }], ), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 15, limitValue: 100 }], ), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ); - const limits = await context.contracts.complianceModule.getTimeTransferLimits(context.suite.compliance.address); + const limits = await context.contracts.complianceModule.getTimeTransferLimits(context.suite.compliance.target); expect(limits.length).to.be.eq(2); expect(limits[0].limitTime).to.be.eq(10); expect(limits[0].limitValue).to.be.eq(120); @@ -290,35 +298,35 @@ describe('Compliance Module: TimeTransferLimits', () => { const to = context.accounts.bobWallet.address; const senderIdentity = await context.suite.identityRegistry.identity(from); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 10, limitValue: 120 }], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 15, limitValue: 100 }], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 80], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); const blockTimestamp = await time.latest(); - const counter1 = await context.suite.complianceModule.usersCounters(context.suite.compliance.address, senderIdentity, 10); + const counter1 = await context.suite.complianceModule.usersCounters(context.suite.compliance.target, senderIdentity, 10); expect(counter1.value).to.be.eq(80); expect(counter1.timer).to.be.eq(blockTimestamp + 10); - const counter2 = await context.suite.complianceModule.usersCounters(context.suite.compliance.address, senderIdentity, 15); + const counter2 = await context.suite.complianceModule.usersCounters(context.suite.compliance.target, senderIdentity, 15); expect(counter2.value).to.be.eq(80); expect(counter2.timer).to.be.eq(blockTimestamp + 15); }); @@ -331,45 +339,45 @@ describe('Compliance Module: TimeTransferLimits', () => { const to = context.accounts.bobWallet.address; const senderIdentity = await context.suite.identityRegistry.identity(from); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 100, limitValue: 120 }], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 150, limitValue: 100 }], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 20], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); const blockTimestamp = await time.latest(); await time.increase(10); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 30], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - const counter1 = await context.suite.complianceModule.usersCounters(context.suite.compliance.address, senderIdentity, 100); + const counter1 = await context.suite.complianceModule.usersCounters(context.suite.compliance.target, senderIdentity, 100); expect(counter1.value).to.be.eq(50); expect(counter1.timer).to.be.eq(blockTimestamp + 100); - const counter2 = await context.suite.complianceModule.usersCounters(context.suite.compliance.address, senderIdentity, 150); + const counter2 = await context.suite.complianceModule.usersCounters(context.suite.compliance.target, senderIdentity, 150); expect(counter2.value).to.be.eq(50); expect(counter2.timer).to.be.eq(blockTimestamp + 150); }); @@ -382,47 +390,47 @@ describe('Compliance Module: TimeTransferLimits', () => { const to = context.accounts.bobWallet.address; const senderIdentity = await context.suite.identityRegistry.identity(from); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 10, limitValue: 120 }], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 150, limitValue: 100 }], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 20], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); const blockTimestamp = await time.latest(); await time.increase(30); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 30], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); const resetTimestamp = await time.latest(); - const counter1 = await context.suite.complianceModule.usersCounters(context.suite.compliance.address, senderIdentity, 10); + const counter1 = await context.suite.complianceModule.usersCounters(context.suite.compliance.target, senderIdentity, 10); expect(counter1.value).to.be.eq(30); expect(counter1.timer).to.be.eq(resetTimestamp + 10); - const counter2 = await context.suite.complianceModule.usersCounters(context.suite.compliance.address, senderIdentity, 150); + const counter2 = await context.suite.complianceModule.usersCounters(context.suite.compliance.target, senderIdentity, 150); expect(counter2.value).to.be.eq(50); expect(counter2.timer).to.be.eq(blockTimestamp + 150); }); @@ -440,7 +448,7 @@ describe('Compliance Module: TimeTransferLimits', () => { describe('.canComplianceBind', () => { it('should return true', async () => { const context = await loadFixture(deployTimeTransferLimitsFullSuite); - expect(await context.suite.complianceModule.canComplianceBind(context.suite.compliance.address)).to.be.true; + expect(await context.suite.complianceModule.canComplianceBind(context.suite.compliance.target)).to.be.true; }); }); @@ -453,7 +461,7 @@ describe('Compliance Module: TimeTransferLimits', () => { '0x0000000000000000000000000000000000000000', context.accounts.bobWallet.address, 100, - context.suite.compliance.address, + context.suite.compliance.target, ), ).to.be.true; }); @@ -467,7 +475,7 @@ describe('Compliance Module: TimeTransferLimits', () => { context.accounts.tokenAgent.address, context.accounts.bobWallet.address, 100, - context.suite.compliance.address, + context.suite.compliance.target, ), ).to.be.true; }); @@ -478,11 +486,11 @@ describe('Compliance Module: TimeTransferLimits', () => { const context = await loadFixture(deployTimeTransferLimitsFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 10, limitValue: 50 }], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); expect( @@ -490,7 +498,7 @@ describe('Compliance Module: TimeTransferLimits', () => { context.accounts.aliceWallet.address, context.accounts.bobWallet.address, 100, - context.suite.compliance.address, + context.suite.compliance.target, ), ).to.be.false; }); @@ -504,21 +512,21 @@ describe('Compliance Module: TimeTransferLimits', () => { const to = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 10, limitValue: 120 }], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 100], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.address)).to.be.false; + expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.target)).to.be.false; }); }); @@ -529,14 +537,14 @@ describe('Compliance Module: TimeTransferLimits', () => { const to = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 10, limitValue: 120 }], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); - expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.address)).to.be.true; + expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.target)).to.be.true; }); }); @@ -547,23 +555,23 @@ describe('Compliance Module: TimeTransferLimits', () => { const to = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( + new ethers.Interface(['function setTimeTransferLimit(tuple(uint32 limitTime, uint256 limitValue) _limit)']).encodeFunctionData( 'setTimeTransferLimit', [{ limitTime: 10, limitValue: 120 }], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 100], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await time.increase(30); - expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.address)).to.be.true; + expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.target)).to.be.true; }); }); }); @@ -586,11 +594,11 @@ describe('Compliance Module: TimeTransferLimits', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ + new ethers.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ context.accounts.anotherWallet.address, 10, ]), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ), ).to.eventually.be.fulfilled; }); @@ -614,11 +622,11 @@ describe('Compliance Module: TimeTransferLimits', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ + new ethers.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ context.accounts.anotherWallet.address, 10, ]), - context.contracts.complianceModule.address, + context.contracts.complianceModule.target, ), ).to.eventually.be.fulfilled; }); diff --git a/test/compliances/module-transfer-fees.test.ts b/test/compliances/module-transfer-fees.test.ts index c63e5b6f..6a8f5b30 100644 --- a/test/compliances/module-transfer-fees.test.ts +++ b/test/compliances/module-transfer-fees.test.ts @@ -8,12 +8,12 @@ async function deployTransferFeesFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); const module = await ethers.deployContract('TransferFeesModule'); - const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); - const complianceModule = await ethers.getContractAt('TransferFeesModule', proxy.address); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('TransferFeesModule', proxy.target); - await context.suite.token.addAgent(complianceModule.address); - await context.suite.compliance.bindToken(context.suite.token.address); - await context.suite.compliance.addModule(complianceModule.address); + await context.suite.token.addAgent(complianceModule.target); + await context.suite.compliance.bindToken(context.suite.token.target); + await context.suite.compliance.addModule(complianceModule.target); const identity = await context.suite.identityRegistry.identity(context.accounts.aliceWallet.address); await context.suite.identityRegistry.connect(context.accounts.tokenAgent).registerIdentity(context.accounts.charlieWallet.address, identity, 0); @@ -31,8 +31,8 @@ describe('Compliance Module: TransferFees', () => { it('should deploy the TransferFees contract and bind it to the compliance', async () => { const context = await loadFixture(deployTransferFeesFullSuite); - expect(context.suite.complianceModule.address).not.to.be.undefined; - expect(await context.suite.compliance.isModuleBound(context.suite.complianceModule.address)).to.be.true; + expect(context.suite.complianceModule.target).not.to.be.undefined; + expect(await context.suite.compliance.isModuleBound(context.suite.complianceModule.target)).to.be.true; }); describe('.owner', () => { @@ -86,7 +86,7 @@ describe('Compliance Module: TransferFees', () => { describe('when calling directly', () => { it('should revert', async () => { const context = await loadFixture(deployTransferFeesFullSuite); - await expect(context.suite.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero)).to.revertedWith( + await expect(context.suite.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress)).to.revertedWith( 'Ownable: caller is not the owner', ); }); @@ -99,11 +99,14 @@ describe('Compliance Module: TransferFees', () => { const newImplementation = await ethers.deployContract('TransferFeesModule'); // when - await context.suite.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + await context.suite.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.target); + const target = context.suite.complianceModule.target; + + const address = typeof target === 'string' ? target : await target.getAddress(); // then - const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.complianceModule.address); - expect(implementationAddress).to.eq(newImplementation.address); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(address); + expect(implementationAddress).to.eq(newImplementation.target); }); }); }); @@ -128,8 +131,8 @@ describe('Compliance Module: TransferFees', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [10001, collector]), - context.suite.complianceModule.address, + new ethers.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [10001, collector]), + context.suite.complianceModule.target, ), ).to.be.revertedWithCustomError(context.suite.complianceModule, `FeeRateIsOutOfRange`); }); @@ -142,8 +145,8 @@ describe('Compliance Module: TransferFees', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [1, collector]), - context.suite.complianceModule.address, + new ethers.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [1, collector]), + context.suite.complianceModule.target, ), ).to.be.revertedWithCustomError(context.suite.complianceModule, `CollectorAddressIsNotVerified`); }); @@ -155,13 +158,13 @@ describe('Compliance Module: TransferFees', () => { const collector = context.accounts.aliceWallet.address; const tx = await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [1, collector]), - context.suite.complianceModule.address, + new ethers.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [1, collector]), + context.suite.complianceModule.target, ); - await expect(tx).to.emit(context.suite.complianceModule, 'FeeUpdated').withArgs(context.suite.compliance.address, 1, collector); + await expect(tx).to.emit(context.suite.complianceModule, 'FeeUpdated').withArgs(context.suite.compliance.target, 1, collector); - const fee = await context.suite.complianceModule.getFee(context.suite.compliance.address); + const fee = await context.suite.complianceModule.getFee(context.suite.compliance.target); expect(fee.rate).to.be.eq(1); expect(fee.collector).to.be.eq(collector); }); @@ -174,11 +177,11 @@ describe('Compliance Module: TransferFees', () => { const context = await loadFixture(deployTransferFeesFullSuite); const collector = context.accounts.aliceWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [1, collector]), - context.suite.complianceModule.address, + new ethers.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [1, collector]), + context.suite.complianceModule.target, ); - const fee = await context.suite.complianceModule.getFee(context.suite.compliance.address); + const fee = await context.suite.complianceModule.getFee(context.suite.compliance.target); expect(fee.rate).to.be.eq(1); expect(fee.collector).to.be.eq(collector); }); @@ -195,10 +198,10 @@ describe('Compliance Module: TransferFees', () => { describe('when the module is not registered as a token agent', () => { it('should return false', async () => { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); - await context.suite.compliance.bindToken(context.suite.token.address); + await context.suite.compliance.bindToken(context.suite.token.target); const complianceModule = await ethers.deployContract('TransferFeesModule'); - const result = await complianceModule.canComplianceBind(context.suite.compliance.address); + const result = await complianceModule.canComplianceBind(context.suite.compliance.target); expect(result).to.be.false; }); }); @@ -206,7 +209,7 @@ describe('Compliance Module: TransferFees', () => { describe('when the module is registered as a token agent', () => { it('should return true', async () => { const context = await loadFixture(deployTransferFeesFullSuite); - const result = await context.suite.complianceModule.canComplianceBind(context.suite.compliance.address); + const result = await context.suite.complianceModule.canComplianceBind(context.suite.compliance.target); expect(result).to.be.true; }); }); @@ -229,8 +232,8 @@ describe('Compliance Module: TransferFees', () => { const context = await loadFixture(deployTransferFeesFullSuite); const collector = context.accounts.charlieWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [1000, collector]), - context.suite.complianceModule.address, + new ethers.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [1000, collector]), + context.suite.complianceModule.target, ); const from = context.accounts.aliceWallet.address; @@ -239,11 +242,11 @@ describe('Compliance Module: TransferFees', () => { await context.suite.identityRegistry.connect(context.accounts.tokenAgent).registerIdentity(to, identity, 0); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 80], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); const collectedAmount = await context.suite.token.balanceOf(collector); @@ -256,19 +259,19 @@ describe('Compliance Module: TransferFees', () => { const context = await loadFixture(deployTransferFeesFullSuite); const collector = context.accounts.charlieWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [0, collector]), - context.suite.complianceModule.address, + new ethers.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [0, collector]), + context.suite.complianceModule.target, ); const from = context.accounts.aliceWallet.address; const to = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 80], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); const collectedAmount = await context.suite.token.balanceOf(collector); @@ -281,18 +284,18 @@ describe('Compliance Module: TransferFees', () => { const context = await loadFixture(deployTransferFeesFullSuite); const collector = context.accounts.charlieWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [1000, collector]), - context.suite.complianceModule.address, + new ethers.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [1000, collector]), + context.suite.complianceModule.target, ); const to = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [collector, to, 80], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); const collectedAmount = await context.suite.token.balanceOf(collector); @@ -305,19 +308,19 @@ describe('Compliance Module: TransferFees', () => { const context = await loadFixture(deployTransferFeesFullSuite); const collector = context.accounts.charlieWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [1000, collector]), - context.suite.complianceModule.address, + new ethers.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [1000, collector]), + context.suite.complianceModule.target, ); const from = context.accounts.bobWallet.address; await context.suite.token.connect(context.accounts.tokenAgent).mint(collector, 5000); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, collector, 80], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); const collectedAmount = await context.suite.token.balanceOf(collector); @@ -330,19 +333,19 @@ describe('Compliance Module: TransferFees', () => { const context = await loadFixture(deployTransferFeesFullSuite); const collector = context.accounts.charlieWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [1, collector]), - context.suite.complianceModule.address, + new ethers.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [1, collector]), + context.suite.complianceModule.target, ); const from = context.accounts.aliceWallet.address; const to = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 80], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); const collectedAmount = await context.suite.token.balanceOf(collector); @@ -355,19 +358,19 @@ describe('Compliance Module: TransferFees', () => { const context = await loadFixture(deployTransferFeesFullSuite); const collector = context.accounts.charlieWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [1000, collector]), - context.suite.complianceModule.address, + new ethers.Interface(['function setFee(uint256 _rate, address _collector)']).encodeFunctionData('setFee', [1000, collector]), + context.suite.complianceModule.target, ); const from = context.accounts.aliceWallet.address; const to = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [from, to, 80], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); const collectedAmount = await context.suite.token.balanceOf(collector); @@ -397,11 +400,11 @@ describe('Compliance Module: TransferFees', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ + new ethers.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ context.accounts.anotherWallet.address, 10, ]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ), ).to.eventually.be.fulfilled; }); @@ -425,11 +428,11 @@ describe('Compliance Module: TransferFees', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ + new ethers.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ context.accounts.anotherWallet.address, 10, ]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ), ).to.eventually.be.fulfilled; }); @@ -441,7 +444,7 @@ describe('Compliance Module: TransferFees', () => { const context = await loadFixture(deployTransferFeesFullSuite); const from = context.accounts.aliceWallet.address; const to = context.accounts.bobWallet.address; - expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.address)).to.be.true; + expect(await context.suite.complianceModule.moduleCheck(from, to, 100, context.suite.compliance.target)).to.be.true; }); }); diff --git a/test/compliances/module-transfer-restrict.test.ts b/test/compliances/module-transfer-restrict.test.ts index 3a560dff..6207d1c6 100644 --- a/test/compliances/module-transfer-restrict.test.ts +++ b/test/compliances/module-transfer-restrict.test.ts @@ -7,11 +7,11 @@ import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; async function deployTransferRestrictFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); const module = await ethers.deployContract('TransferRestrictModule'); - const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); - const complianceModule = await ethers.getContractAt('TransferRestrictModule', proxy.address); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('TransferRestrictModule', proxy.target); - await context.suite.compliance.bindToken(context.suite.token.address); - await context.suite.compliance.addModule(complianceModule.address); + await context.suite.compliance.bindToken(context.suite.token.target); + await context.suite.compliance.addModule(complianceModule.target); return { ...context, @@ -26,8 +26,8 @@ describe('Compliance Module: TransferRestrict', () => { it('should deploy the TransferRestrict contract and bind it to the compliance', async () => { const context = await loadFixture(deployTransferRestrictFullSuite); - expect(context.suite.complianceModule.address).not.to.be.undefined; - expect(await context.suite.compliance.isModuleBound(context.suite.complianceModule.address)).to.be.true; + expect(context.suite.complianceModule.target).not.to.be.undefined; + expect(await context.suite.compliance.isModuleBound(context.suite.complianceModule.target)).to.be.true; }); describe('.name', () => { @@ -49,7 +49,7 @@ describe('Compliance Module: TransferRestrict', () => { it('should return true', async () => { const context = await loadFixture(deployTransferRestrictFullSuite); const complianceModule = await ethers.deployContract('TransferRestrictModule'); - expect(await complianceModule.canComplianceBind(context.suite.compliance.address)).to.be.true; + expect(await complianceModule.canComplianceBind(context.suite.compliance.target)).to.be.true; }); }); @@ -104,7 +104,7 @@ describe('Compliance Module: TransferRestrict', () => { describe('when calling directly', () => { it('should revert', async () => { const context = await loadFixture(deployTransferRestrictFullSuite); - await expect(context.suite.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero)).to.revertedWith( + await expect(context.suite.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress)).to.revertedWith( 'Ownable: caller is not the owner', ); }); @@ -117,11 +117,14 @@ describe('Compliance Module: TransferRestrict', () => { const newImplementation = await ethers.deployContract('TransferRestrictModule'); // when - await context.suite.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + await context.suite.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.target); + const target = context.suite.complianceModule.target; + + const address = typeof target === 'string' ? target : await target.getAddress(); // then - const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.complianceModule.address); - expect(implementationAddress).to.eq(newImplementation.address); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(address); + expect(implementationAddress).to.eq(newImplementation.target); }); }); }); @@ -142,15 +145,13 @@ describe('Compliance Module: TransferRestrict', () => { const context = await loadFixture(deployTransferRestrictFullSuite); const tx = await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function allowUser(address _userAddress)']).encodeFunctionData('allowUser', [ - context.accounts.aliceWallet.address, - ]), - context.suite.complianceModule.address, + new ethers.Interface(['function allowUser(address _userAddress)']).encodeFunctionData('allowUser', [context.accounts.aliceWallet.address]), + context.suite.complianceModule.target, ); await expect(tx) .to.emit(context.suite.complianceModule, 'UserAllowed') - .withArgs(context.suite.compliance.address, context.accounts.aliceWallet.address); + .withArgs(context.suite.compliance.target, context.accounts.aliceWallet.address); }); }); }); @@ -171,17 +172,17 @@ describe('Compliance Module: TransferRestrict', () => { const context = await loadFixture(deployTransferRestrictFullSuite); const tx = await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function batchAllowUsers(address[] _identities)']).encodeFunctionData('batchAllowUsers', [ + new ethers.Interface(['function batchAllowUsers(address[] _identities)']).encodeFunctionData('batchAllowUsers', [ [context.accounts.aliceWallet.address, context.accounts.bobWallet.address], ]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await expect(tx) .to.emit(context.suite.complianceModule, 'UserAllowed') - .withArgs(context.suite.compliance.address, context.accounts.aliceWallet.address) + .withArgs(context.suite.compliance.target, context.accounts.aliceWallet.address) .to.emit(context.suite.complianceModule, 'UserAllowed') - .withArgs(context.suite.compliance.address, context.accounts.bobWallet.address); + .withArgs(context.suite.compliance.target, context.accounts.bobWallet.address); }); }); }); @@ -201,22 +202,20 @@ describe('Compliance Module: TransferRestrict', () => { it('should disallow user', async () => { const context = await loadFixture(deployTransferRestrictFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function allowUser(address _userAddress)']).encodeFunctionData('allowUser', [ - context.accounts.aliceWallet.address, - ]), - context.suite.complianceModule.address, + new ethers.Interface(['function allowUser(address _userAddress)']).encodeFunctionData('allowUser', [context.accounts.aliceWallet.address]), + context.suite.complianceModule.target, ); const tx = await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function disallowUser(address _userAddress)']).encodeFunctionData('disallowUser', [ + new ethers.Interface(['function disallowUser(address _userAddress)']).encodeFunctionData('disallowUser', [ context.accounts.aliceWallet.address, ]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await expect(tx) .to.emit(context.suite.complianceModule, 'UserDisallowed') - .withArgs(context.suite.compliance.address, context.accounts.aliceWallet.address); + .withArgs(context.suite.compliance.target, context.accounts.aliceWallet.address); }); }); }); @@ -236,24 +235,24 @@ describe('Compliance Module: TransferRestrict', () => { it('should disallow user', async () => { const context = await loadFixture(deployTransferRestrictFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function batchAllowUsers(address[] _identities)']).encodeFunctionData('batchAllowUsers', [ + new ethers.Interface(['function batchAllowUsers(address[] _identities)']).encodeFunctionData('batchAllowUsers', [ [context.accounts.aliceWallet.address, context.accounts.bobWallet.address], ]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); const tx = await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function batchDisallowUsers(address[] _identities)']).encodeFunctionData('batchDisallowUsers', [ + new ethers.Interface(['function batchDisallowUsers(address[] _identities)']).encodeFunctionData('batchDisallowUsers', [ [context.accounts.aliceWallet.address, context.accounts.bobWallet.address], ]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ); await expect(tx) .to.emit(context.suite.complianceModule, 'UserDisallowed') - .withArgs(context.suite.compliance.address, context.accounts.aliceWallet.address) + .withArgs(context.suite.compliance.target, context.accounts.aliceWallet.address) .to.emit(context.suite.complianceModule, 'UserDisallowed') - .withArgs(context.suite.compliance.address, context.accounts.bobWallet.address); + .withArgs(context.suite.compliance.target, context.accounts.bobWallet.address); }); }); }); @@ -263,13 +262,11 @@ describe('Compliance Module: TransferRestrict', () => { it('should return true', async () => { const context = await loadFixture(deployTransferRestrictFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function allowUser(address _userAddress)']).encodeFunctionData('allowUser', [ - context.accounts.aliceWallet.address, - ]), - context.suite.complianceModule.address, + new ethers.Interface(['function allowUser(address _userAddress)']).encodeFunctionData('allowUser', [context.accounts.aliceWallet.address]), + context.suite.complianceModule.target, ); - const result = await context.suite.complianceModule.isUserAllowed(context.suite.compliance.address, context.accounts.aliceWallet.address); + const result = await context.suite.complianceModule.isUserAllowed(context.suite.compliance.target, context.accounts.aliceWallet.address); expect(result).to.be.true; }); }); @@ -277,7 +274,7 @@ describe('Compliance Module: TransferRestrict', () => { describe('when user is not allowed', () => { it('should return false', async () => { const context = await loadFixture(deployTransferRestrictFullSuite); - const result = await context.suite.complianceModule.isUserAllowed(context.suite.compliance.address, context.accounts.aliceWallet.address); + const result = await context.suite.complianceModule.isUserAllowed(context.suite.compliance.target, context.accounts.aliceWallet.address); expect(result).to.be.false; }); }); @@ -289,7 +286,7 @@ describe('Compliance Module: TransferRestrict', () => { const context = await loadFixture(deployTransferRestrictFullSuite); const to = context.accounts.anotherWallet.address; const from = context.accounts.aliceWallet.address; - const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.target); expect(result).to.be.false; }); }); @@ -301,11 +298,11 @@ describe('Compliance Module: TransferRestrict', () => { const from = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function allowUser(address _userAddress)']).encodeFunctionData('allowUser', [from]), - context.suite.complianceModule.address, + new ethers.Interface(['function allowUser(address _userAddress)']).encodeFunctionData('allowUser', [from]), + context.suite.complianceModule.target, ); - const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.target); expect(result).to.be.true; }); }); @@ -317,11 +314,11 @@ describe('Compliance Module: TransferRestrict', () => { const from = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function allowUser(address _userAddress)']).encodeFunctionData('allowUser', [to]), - context.suite.complianceModule.address, + new ethers.Interface(['function allowUser(address _userAddress)']).encodeFunctionData('allowUser', [to]), + context.suite.complianceModule.target, ); - const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.target); expect(result).to.be.true; }); }); @@ -344,11 +341,11 @@ describe('Compliance Module: TransferRestrict', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ + new ethers.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ context.accounts.anotherWallet.address, 10, ]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ), ).to.eventually.be.fulfilled; }); @@ -372,11 +369,11 @@ describe('Compliance Module: TransferRestrict', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ + new ethers.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ context.accounts.anotherWallet.address, 10, ]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ), ).to.eventually.be.fulfilled; }); @@ -400,11 +397,11 @@ describe('Compliance Module: TransferRestrict', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [context.accounts.aliceWallet.address, context.accounts.anotherWallet.address, 80], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ), ).to.eventually.be.fulfilled; }); diff --git a/test/dva.test.ts b/test/dva.test.ts index f21c20a0..6a0a0e14 100644 --- a/test/dva.test.ts +++ b/test/dva.test.ts @@ -1,8 +1,8 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { expect } from 'chai'; import { ethers } from 'hardhat'; +import { Signer } from 'ethers'; -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; import { deployFullSuiteFixture } from './fixtures/deploy-full-suite.fixture'; describe('DVATransferManager', () => { @@ -23,20 +23,20 @@ describe('DVATransferManager', () => { async function deployFullSuiteWithVerifiedTransferManager() { const context = await loadFixture(deployFullSuiteWithTransferManager); const identity = await context.suite.identityRegistry.identity(context.accounts.aliceWallet.address); - await context.suite.identityRegistry.connect(context.accounts.tokenAgent).registerIdentity(context.suite.transferManager.address, identity, 0); + await context.suite.identityRegistry.connect(context.accounts.tokenAgent).registerIdentity(context.suite.transferManager.target, identity, 0); return context; } async function signTransfer( transferID: string, - signer: SignerWithAddress, + signer: Signer, ): Promise<{ v: number; r: string; s: string; }> { - const rawSignature = await signer.signMessage(ethers.utils.arrayify(transferID)); - const { v, r, s } = ethers.utils.splitSignature(rawSignature); + const rawSignature = await signer.signMessage(ethers.getBytes(transferID)); + const { v, r, s } = ethers.Signature.from(rawSignature); return { v, r, s }; } @@ -44,9 +44,9 @@ describe('DVATransferManager', () => { const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); await context.suite.transferManager .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, true, true, false, [context.accounts.charlieWallet.address]); + .setApprovalCriteria(context.suite.token.target, true, true, false, [context.accounts.charlieWallet.address]); - await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.address, 100000); + await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.target, 100000); const transferID = await context.suite.transferManager.calculateTransferID( 0, context.accounts.aliceWallet.address, @@ -56,7 +56,7 @@ describe('DVATransferManager', () => { await context.suite.transferManager .connect(context.accounts.aliceWallet) - .initiateTransfer(context.suite.token.address, context.accounts.bobWallet.address, 100); + .initiateTransfer(context.suite.token.target, context.accounts.bobWallet.address, 100); return { ...context, @@ -68,9 +68,9 @@ describe('DVATransferManager', () => { const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); await context.suite.transferManager .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, true, true, true, [context.accounts.charlieWallet.address]); + .setApprovalCriteria(context.suite.token.target, true, true, true, [context.accounts.charlieWallet.address]); - await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.address, 100000); + await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.target, 100000); const transferID = await context.suite.transferManager.calculateTransferID( 0, context.accounts.aliceWallet.address, @@ -80,7 +80,7 @@ describe('DVATransferManager', () => { await context.suite.transferManager .connect(context.accounts.aliceWallet) - .initiateTransfer(context.suite.token.address, context.accounts.bobWallet.address, 100); + .initiateTransfer(context.suite.token.target, context.accounts.bobWallet.address, 100); return { ...context, @@ -96,7 +96,7 @@ describe('DVATransferManager', () => { await expect( context.suite.transferManager .connect(context.accounts.anotherWallet) - .setApprovalCriteria(context.suite.token.address, false, true, true, []), + .setApprovalCriteria(context.suite.token.target, false, true, true, []), ).to.be.revertedWithCustomError(context.suite.transferManager, `OnlyTokenAgentCanCall`); }); }); @@ -107,9 +107,7 @@ describe('DVATransferManager', () => { const context = await loadFixture(deployFullSuiteWithTransferManager); await expect( - context.suite.transferManager - .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, false, true, true, []), + context.suite.transferManager.connect(context.accounts.tokenAgent).setApprovalCriteria(context.suite.token.target, false, true, true, []), ).to.be.revertedWithCustomError(context.suite.transferManager, `DVAManagerIsNotVerifiedForTheToken`); }); }); @@ -121,31 +119,31 @@ describe('DVATransferManager', () => { const identity = await context.suite.identityRegistry.identity(context.accounts.aliceWallet.address); await context.suite.identityRegistry .connect(context.accounts.tokenAgent) - .registerIdentity(context.suite.transferManager.address, identity, 0); + .registerIdentity(context.suite.transferManager.target, identity, 0); const tx = context.suite.transferManager .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, true, true, true, [ + .setApprovalCriteria(context.suite.token.target, true, true, true, [ context.accounts.anotherWallet.address, context.accounts.bobWallet.address, ]); + await tx; - const approvalCriteria = await context.suite.transferManager.getApprovalCriteria(context.suite.token.address); - expect(approvalCriteria.includeRecipientApprover).to.be.true; - expect(approvalCriteria.includeAgentApprover).to.be.true; - expect(approvalCriteria.sequentialApproval).to.be.true; - expect(approvalCriteria.additionalApprovers).to.be.eql([context.accounts.anotherWallet.address, context.accounts.bobWallet.address]); - + const approvalCriteria = await context.suite.transferManager.getApprovalCriteria(context.suite.token.target); await expect(tx) .to.emit(context.suite.transferManager, 'ApprovalCriteriaSet') .withArgs( - context.suite.token.address, + context.suite.token.target, true, true, true, [context.accounts.anotherWallet.address, context.accounts.bobWallet.address], approvalCriteria.hash, ); + expect(approvalCriteria.includeRecipientApprover).to.be.true; + expect(approvalCriteria.includeAgentApprover).to.be.true; + expect(approvalCriteria.sequentialApproval).to.be.true; + expect(approvalCriteria.additionalApprovers).to.be.eql([context.accounts.anotherWallet.address, context.accounts.bobWallet.address]); }); }); @@ -155,23 +153,23 @@ describe('DVATransferManager', () => { const identity = await context.suite.identityRegistry.identity(context.accounts.aliceWallet.address); await context.suite.identityRegistry .connect(context.accounts.tokenAgent) - .registerIdentity(context.suite.transferManager.address, identity, 0); + .registerIdentity(context.suite.transferManager.target, identity, 0); await context.suite.transferManager .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, true, true, true, [ + .setApprovalCriteria(context.suite.token.target, true, true, true, [ context.accounts.anotherWallet.address, context.accounts.bobWallet.address, ]); - const previousApprovalCriteria = await context.suite.transferManager.getApprovalCriteria(context.suite.token.address); + const previousApprovalCriteria = await context.suite.transferManager.getApprovalCriteria(context.suite.token.target); const tx = await context.suite.transferManager .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, false, false, false, [context.accounts.davidWallet.address]); + .setApprovalCriteria(context.suite.token.target, false, false, false, [context.accounts.davidWallet.address]); await tx.wait(); - const approvalCriteria = await context.suite.transferManager.getApprovalCriteria(context.suite.token.address); + const approvalCriteria = await context.suite.transferManager.getApprovalCriteria(context.suite.token.target); expect(approvalCriteria.includeRecipientApprover).to.be.false; expect(approvalCriteria.includeAgentApprover).to.be.false; expect(approvalCriteria.sequentialApproval).to.be.false; @@ -180,7 +178,7 @@ describe('DVATransferManager', () => { await expect(tx) .to.emit(context.suite.transferManager, 'ApprovalCriteriaSet') - .withArgs(context.suite.token.address, false, false, false, [context.accounts.davidWallet.address], approvalCriteria.hash); + .withArgs(context.suite.token.target, false, false, false, [context.accounts.davidWallet.address], approvalCriteria.hash); }); }); }); @@ -195,7 +193,7 @@ describe('DVATransferManager', () => { await expect( context.suite.transferManager .connect(context.accounts.aliceWallet) - .initiateTransfer(context.suite.token.address, context.accounts.bobWallet.address, 10), + .initiateTransfer(context.suite.token.target, context.accounts.bobWallet.address, 10), ).to.be.revertedWithCustomError(context.suite.transferManager, `TokenIsNotRegistered`); }); }); @@ -206,7 +204,7 @@ describe('DVATransferManager', () => { const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); await context.suite.transferManager .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, true, true, true, [ + .setApprovalCriteria(context.suite.token.target, true, true, true, [ context.accounts.charlieWallet.address, context.accounts.anotherWallet.address, ]); @@ -214,7 +212,7 @@ describe('DVATransferManager', () => { await expect( context.suite.transferManager .connect(context.accounts.aliceWallet) - .initiateTransfer(context.suite.token.address, context.accounts.anotherWallet.address, 10), + .initiateTransfer(context.suite.token.target, context.accounts.anotherWallet.address, 10), ).to.be.revertedWithCustomError(context.suite.transferManager, `RecipientIsNotVerified`); }); }); @@ -224,17 +222,17 @@ describe('DVATransferManager', () => { const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); await context.suite.transferManager .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, true, true, true, [ + .setApprovalCriteria(context.suite.token.target, true, true, true, [ context.accounts.charlieWallet.address, context.accounts.anotherWallet.address, ]); - await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.address, 100000); + await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.target, 100000); await expect( context.suite.transferManager .connect(context.accounts.aliceWallet) - .initiateTransfer(context.suite.token.address, context.accounts.bobWallet.address, 100000), + .initiateTransfer(context.suite.token.target, context.accounts.bobWallet.address, 100000), ).to.be.revertedWith('Insufficient Balance'); }); }); @@ -245,9 +243,9 @@ describe('DVATransferManager', () => { const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); await context.suite.transferManager .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, true, false, true, []); + .setApprovalCriteria(context.suite.token.target, true, false, true, []); - await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.address, 100000); + await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.target, 100000); const transferID = await context.suite.transferManager.calculateTransferID( 0, context.accounts.aliceWallet.address, @@ -257,19 +255,17 @@ describe('DVATransferManager', () => { const tx = context.suite.transferManager .connect(context.accounts.aliceWallet) - .initiateTransfer(context.suite.token.address, context.accounts.bobWallet.address, 100); + .initiateTransfer(context.suite.token.target, context.accounts.bobWallet.address, 100); await expect(tx) .to.emit(context.suite.transferManager, 'TransferInitiated') .withArgs( transferID, - context.suite.token.address, + context.suite.token.target, context.accounts.aliceWallet.address, context.accounts.bobWallet.address, 100, - ( - await context.suite.transferManager.getApprovalCriteria(context.suite.token.address) - ).hash, + (await context.suite.transferManager.getApprovalCriteria(context.suite.token.target)).hash, ); await (await tx).wait(); @@ -285,9 +281,9 @@ describe('DVATransferManager', () => { const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); await context.suite.transferManager .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, false, true, true, []); + .setApprovalCriteria(context.suite.token.target, false, true, true, []); - await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.address, 100000); + await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.target, 100000); const transferID = await context.suite.transferManager.calculateTransferID( 0, context.accounts.aliceWallet.address, @@ -297,19 +293,17 @@ describe('DVATransferManager', () => { const tx = context.suite.transferManager .connect(context.accounts.aliceWallet) - .initiateTransfer(context.suite.token.address, context.accounts.bobWallet.address, 100); + .initiateTransfer(context.suite.token.target, context.accounts.bobWallet.address, 100); await expect(tx) .to.emit(context.suite.transferManager, 'TransferInitiated') .withArgs( transferID, - context.suite.token.address, + context.suite.token.target, context.accounts.aliceWallet.address, context.accounts.bobWallet.address, 100, - ( - await context.suite.transferManager.getApprovalCriteria(context.suite.token.address) - ).hash, + (await context.suite.transferManager.getApprovalCriteria(context.suite.token.target)).hash, ); await (await tx).wait(); @@ -325,12 +319,12 @@ describe('DVATransferManager', () => { const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); await context.suite.transferManager .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, false, false, true, [ + .setApprovalCriteria(context.suite.token.target, false, false, true, [ context.accounts.charlieWallet.address, context.accounts.anotherWallet.address, ]); - await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.address, 100000); + await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.target, 100000); const transferID = await context.suite.transferManager.calculateTransferID( 0, context.accounts.aliceWallet.address, @@ -340,19 +334,17 @@ describe('DVATransferManager', () => { const tx = context.suite.transferManager .connect(context.accounts.aliceWallet) - .initiateTransfer(context.suite.token.address, context.accounts.bobWallet.address, 100); + .initiateTransfer(context.suite.token.target, context.accounts.bobWallet.address, 100); await expect(tx) .to.emit(context.suite.transferManager, 'TransferInitiated') .withArgs( transferID, - context.suite.token.address, + context.suite.token.target, context.accounts.aliceWallet.address, context.accounts.bobWallet.address, 100, - ( - await context.suite.transferManager.getApprovalCriteria(context.suite.token.address) - ).hash, + (await context.suite.transferManager.getApprovalCriteria(context.suite.token.target)).hash, ); const transfer = await context.suite.transferManager.getTransfer(transferID); @@ -369,12 +361,12 @@ describe('DVATransferManager', () => { const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); await context.suite.transferManager .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, true, true, true, [ + .setApprovalCriteria(context.suite.token.target, true, true, true, [ context.accounts.charlieWallet.address, context.accounts.anotherWallet.address, ]); - await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.address, 100000); + await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.target, 100000); const transferID = await context.suite.transferManager.calculateTransferID( 0, context.accounts.aliceWallet.address, @@ -384,19 +376,17 @@ describe('DVATransferManager', () => { const tx = context.suite.transferManager .connect(context.accounts.aliceWallet) - .initiateTransfer(context.suite.token.address, context.accounts.bobWallet.address, 100); + .initiateTransfer(context.suite.token.target, context.accounts.bobWallet.address, 100); await expect(tx) .to.emit(context.suite.transferManager, 'TransferInitiated') .withArgs( transferID, - context.suite.token.address, + context.suite.token.target, context.accounts.aliceWallet.address, context.accounts.bobWallet.address, 100, - ( - await context.suite.transferManager.getApprovalCriteria(context.suite.token.address) - ).hash, + (await context.suite.transferManager.getApprovalCriteria(context.suite.token.target)).hash, ); await (await tx).wait(); @@ -414,7 +404,7 @@ describe('DVATransferManager', () => { const senderBalance = await context.suite.token.balanceOf(context.accounts.aliceWallet.address); expect(senderBalance).to.be.eq(900); - const dvaBalance = await context.suite.token.balanceOf(context.suite.transferManager.address); + const dvaBalance = await context.suite.token.balanceOf(context.suite.transferManager.target); expect(dvaBalance).to.be.eq(100); }); }); @@ -458,13 +448,13 @@ describe('DVATransferManager', () => { const context = await loadFixture(deployFullSuiteWithNonSequentialTransfer); const modifyTx = await context.suite.transferManager .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, false, false, false, [context.accounts.davidWallet.address]); + .setApprovalCriteria(context.suite.token.target, false, false, false, [context.accounts.davidWallet.address]); await modifyTx.wait(); const tx = context.suite.transferManager.connect(context.accounts.charlieWallet).approveTransfer(context.transferID); await expect(tx) .to.emit(context.suite.transferManager, 'TransferApprovalStateReset') - .withArgs(context.transferID, (await context.suite.transferManager.getApprovalCriteria(context.suite.token.address)).hash); + .withArgs(context.transferID, (await context.suite.transferManager.getApprovalCriteria(context.suite.token.target)).hash); await (await tx).wait(); const transfer = await context.suite.transferManager.getTransfer(context.transferID); @@ -479,7 +469,7 @@ describe('DVATransferManager', () => { const context = await loadFixture(deployFullSuiteWithNonSequentialTransfer); const modifyTx = await context.suite.transferManager .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, false, false, false, [context.accounts.davidWallet.address]); + .setApprovalCriteria(context.suite.token.target, false, false, false, [context.accounts.davidWallet.address]); await modifyTx.wait(); const resetTx = await context.suite.transferManager.connect(context.accounts.charlieWallet).approveTransfer(context.transferID); @@ -528,7 +518,7 @@ describe('DVATransferManager', () => { await expect(tx) .to.emit(context.suite.transferManager, 'TransferCompleted') - .withArgs(context.transferID, context.suite.token.address, context.accounts.aliceWallet.address, context.accounts.bobWallet.address, 100); + .withArgs(context.transferID, context.suite.token.target, context.accounts.aliceWallet.address, context.accounts.bobWallet.address, 100); const transfer = await context.suite.transferManager.getTransfer(context.transferID); expect(transfer.status).to.be.eq(1); @@ -539,7 +529,7 @@ describe('DVATransferManager', () => { const receiverBalance = await context.suite.token.balanceOf(context.accounts.bobWallet.address); expect(receiverBalance).to.be.eq(600); - const dvaBalance = await context.suite.token.balanceOf(context.suite.transferManager.address); + const dvaBalance = await context.suite.token.balanceOf(context.suite.transferManager.target); expect(dvaBalance).to.be.eq(0); }); }); @@ -581,7 +571,7 @@ describe('DVATransferManager', () => { await expect(tx) .to.emit(context.suite.transferManager, 'TransferCompleted') - .withArgs(context.transferID, context.suite.token.address, context.accounts.aliceWallet.address, context.accounts.bobWallet.address, 100); + .withArgs(context.transferID, context.suite.token.target, context.accounts.aliceWallet.address, context.accounts.bobWallet.address, 100); const transfer = await context.suite.transferManager.getTransfer(context.transferID); expect(transfer.status).to.be.eq(1); @@ -592,7 +582,7 @@ describe('DVATransferManager', () => { const receiverBalance = await context.suite.token.balanceOf(context.accounts.bobWallet.address); expect(receiverBalance).to.be.eq(600); - const dvaBalance = await context.suite.token.balanceOf(context.suite.transferManager.address); + const dvaBalance = await context.suite.token.balanceOf(context.suite.transferManager.target); expect(dvaBalance).to.be.eq(0); }); }); @@ -652,7 +642,7 @@ describe('DVATransferManager', () => { const context = await loadFixture(deployFullSuiteWithNonSequentialTransfer); const modifyTx = await context.suite.transferManager .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, false, false, false, [context.accounts.davidWallet.address]); + .setApprovalCriteria(context.suite.token.target, false, false, false, [context.accounts.davidWallet.address]); await modifyTx.wait(); const tx = context.suite.transferManager @@ -661,7 +651,7 @@ describe('DVATransferManager', () => { await expect(tx) .to.emit(context.suite.transferManager, 'TransferApprovalStateReset') - .withArgs(context.transferID, (await context.suite.transferManager.getApprovalCriteria(context.suite.token.address)).hash); + .withArgs(context.transferID, (await context.suite.transferManager.getApprovalCriteria(context.suite.token.target)).hash); await (await tx).wait(); const transfer = await context.suite.transferManager.getTransfer(context.transferID); @@ -676,7 +666,7 @@ describe('DVATransferManager', () => { const context = await loadFixture(deployFullSuiteWithNonSequentialTransfer); const modifyTx = await context.suite.transferManager .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, false, false, false, [context.accounts.davidWallet.address]); + .setApprovalCriteria(context.suite.token.target, false, false, false, [context.accounts.davidWallet.address]); await modifyTx.wait(); const resetTx = await context.suite.transferManager.connect(context.accounts.charlieWallet).approveTransfer(context.transferID); @@ -739,7 +729,7 @@ describe('DVATransferManager', () => { await expect(tx) .to.emit(context.suite.transferManager, 'TransferCompleted') - .withArgs(context.transferID, context.suite.token.address, context.accounts.aliceWallet.address, context.accounts.bobWallet.address, 100); + .withArgs(context.transferID, context.suite.token.target, context.accounts.aliceWallet.address, context.accounts.bobWallet.address, 100); const transfer = await context.suite.transferManager.getTransfer(context.transferID); expect(transfer.status).to.be.eq(1); @@ -750,7 +740,7 @@ describe('DVATransferManager', () => { const receiverBalance = await context.suite.token.balanceOf(context.accounts.bobWallet.address); expect(receiverBalance).to.be.eq(600); - const dvaBalance = await context.suite.token.balanceOf(context.suite.transferManager.address); + const dvaBalance = await context.suite.token.balanceOf(context.suite.transferManager.target); expect(dvaBalance).to.be.eq(0); }); }); @@ -904,13 +894,13 @@ describe('DVATransferManager', () => { const context = await loadFixture(deployFullSuiteWithNonSequentialTransfer); const modifyTx = await context.suite.transferManager .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, false, false, false, [context.accounts.davidWallet.address]); + .setApprovalCriteria(context.suite.token.target, false, false, false, [context.accounts.davidWallet.address]); await modifyTx.wait(); const tx = context.suite.transferManager.connect(context.accounts.charlieWallet).rejectTransfer(context.transferID); await expect(tx) .to.emit(context.suite.transferManager, 'TransferApprovalStateReset') - .withArgs(context.transferID, (await context.suite.transferManager.getApprovalCriteria(context.suite.token.address)).hash); + .withArgs(context.transferID, (await context.suite.transferManager.getApprovalCriteria(context.suite.token.target)).hash); await (await tx).wait(); const transfer = await context.suite.transferManager.getTransfer(context.transferID); @@ -925,7 +915,7 @@ describe('DVATransferManager', () => { const context = await loadFixture(deployFullSuiteWithNonSequentialTransfer); const modifyTx = await context.suite.transferManager .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, false, false, false, [context.accounts.davidWallet.address]); + .setApprovalCriteria(context.suite.token.target, false, false, false, [context.accounts.davidWallet.address]); await modifyTx.wait(); const resetTx = await context.suite.transferManager.connect(context.accounts.charlieWallet).rejectTransfer(context.transferID); @@ -970,7 +960,7 @@ describe('DVATransferManager', () => { const context = await loadFixture(deployFullSuiteWithNonSequentialTransfer); const transfer = await context.suite.transferManager.getTransfer(context.transferID); - expect(transfer.tokenAddress).to.be.eq(context.suite.token.address); + expect(transfer.tokenAddress).to.be.eq(context.suite.token.target); expect(transfer.sender).to.be.eq(context.accounts.aliceWallet.address); expect(transfer.recipient).to.be.eq(context.accounts.bobWallet.address); expect(transfer.amount).to.be.eq(100); @@ -1057,7 +1047,7 @@ describe('DVATransferManager', () => { describe('when token is not registered', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); - await expect(context.suite.transferManager.getApprovalCriteria(context.suite.token.address)).to.be.revertedWithCustomError( + await expect(context.suite.transferManager.getApprovalCriteria(context.suite.token.target)).to.be.revertedWithCustomError( context.suite.transferManager, `TokenIsNotRegistered`, ); @@ -1067,7 +1057,7 @@ describe('DVATransferManager', () => { describe('when token is registered', () => { it('should return criteria', async () => { const context = await loadFixture(deployFullSuiteWithSequentialTransfer); - const approvalCriteria = await context.suite.transferManager.getApprovalCriteria(context.suite.token.address); + const approvalCriteria = await context.suite.transferManager.getApprovalCriteria(context.suite.token.target); expect(approvalCriteria.includeRecipientApprover).to.be.true; expect(approvalCriteria.includeAgentApprover).to.be.true; expect(approvalCriteria.sequentialApproval).to.be.true; diff --git a/test/dvd.test.ts b/test/dvd.test.ts index 7a9fcd59..59c6bb16 100644 --- a/test/dvd.test.ts +++ b/test/dvd.test.ts @@ -2,6 +2,7 @@ import { anyValue } from '@nomicfoundation/hardhat-chai-matchers/withArgs'; import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { expect } from 'chai'; import { ethers } from 'hardhat'; +import { EventLog } from 'ethers'; import { deployFullSuiteFixture } from './fixtures/deploy-full-suite.fixture'; @@ -33,17 +34,20 @@ describe('DVDTransferManager', () => { const context = await loadFixture(deployFullSuiteWithTransferManager); await context.suite.erc20A.mint(context.accounts.aliceWallet.address, 1000); - await context.suite.erc20A.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.address, 1000); + await context.suite.erc20A.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.target, 1000); await context.suite.erc20B.mint(context.accounts.bobWallet.address, 500); - await context.suite.erc20B.connect(context.accounts.bobWallet).approve(context.suite.transferManager.address, 500); + await context.suite.erc20B.connect(context.accounts.bobWallet).approve(context.suite.transferManager.target, 500); const tx = await context.suite.transferManager .connect(context.accounts.aliceWallet) - .initiateDVDTransfer(context.suite.erc20A.address, 1000, context.accounts.bobWallet.address, context.suite.erc20B.address, 500); + .initiateDVDTransfer(context.suite.erc20A.target, 1000, context.accounts.bobWallet.address, context.suite.erc20B.target, 500); const receipt = await tx.wait(); + if (!receipt) throw new Error('ContractTransactionReceipt is null'); - const event = receipt.events.find((e: { event?: string }) => e.event === 'DVDTransferInitiated'); - const transferId = event.args.transferID; + const event = receipt.logs.find((e) => (e as EventLog)?.fragment?.name === 'DVDTransferInitiated') as EventLog; + + if (!event) throw new Error('DVDTransferInitiated event not found'); + const transferId = event.args[0]; return { ...context, @@ -62,7 +66,7 @@ describe('DVDTransferManager', () => { } = await loadFixture(deployFullSuiteWithTransferManager); await expect( - transferManager.connect(anotherWallet).modifyFee(erc20A.address, erc20B.address, 1, 1, 1, charlieWallet.address, davidWallet.address), + transferManager.connect(anotherWallet).modifyFee(erc20A.target, erc20B.target, 1, 1, 1, charlieWallet.address, davidWallet.address), ).to.be.revertedWith('Ownable: only owner can call'); }); }); @@ -75,7 +79,7 @@ describe('DVDTransferManager', () => { } = await loadFixture(deployFullSuiteWithTransferManager); await expect( - transferManager.connect(deployer).modifyFee(token.address, erc20A.address, 1, 1, 1, charlieWallet.address, davidWallet.address), + transferManager.connect(deployer).modifyFee(token.target, erc20A.target, 1, 1, 1, charlieWallet.address, davidWallet.address), ).to.be.revertedWith('invalid fee settings'); }); @@ -86,7 +90,7 @@ describe('DVDTransferManager', () => { } = await loadFixture(deployFullSuiteWithTransferManager); await expect( - transferManager.connect(deployer).modifyFee(erc20A.address, token.address, 1, 1, 1, charlieWallet.address, davidWallet.address), + transferManager.connect(deployer).modifyFee(erc20A.target, token.target, 1, 1, 1, charlieWallet.address, davidWallet.address), ).to.be.revertedWith('invalid fee settings'); }); }); @@ -101,7 +105,7 @@ describe('DVDTransferManager', () => { } = await loadFixture(deployFullSuiteWithTransferManager); await expect( - transferManager.connect(deployer).modifyFee(erc20A.address, erc20B.address, 1000, 1, 2, charlieWallet.address, davidWallet.address), + transferManager.connect(deployer).modifyFee(erc20A.target, erc20B.target, 1000, 1, 2, charlieWallet.address, davidWallet.address), ).to.be.revertedWith('invalid fee settings'); }); }); @@ -114,7 +118,7 @@ describe('DVDTransferManager', () => { } = await loadFixture(deployFullSuiteWithTransferManager); await expect( - transferManager.connect(deployer).modifyFee(erc20A.address, erc20B.address, 1, 1000, 2, charlieWallet.address, davidWallet.address), + transferManager.connect(deployer).modifyFee(erc20A.target, erc20B.target, 1, 1000, 2, charlieWallet.address, davidWallet.address), ).to.be.revertedWith('invalid fee settings'); }); }); @@ -127,7 +131,7 @@ describe('DVDTransferManager', () => { } = await loadFixture(deployFullSuiteWithTransferManager); await expect( - transferManager.connect(deployer).modifyFee(erc20A.address, erc20B.address, 0, 0, 1, charlieWallet.address, davidWallet.address), + transferManager.connect(deployer).modifyFee(erc20A.target, erc20B.target, 0, 0, 1, charlieWallet.address, davidWallet.address), ).to.be.revertedWith('invalid fee settings'); }); }); @@ -140,7 +144,7 @@ describe('DVDTransferManager', () => { } = await loadFixture(deployFullSuiteWithTransferManager); await expect( - transferManager.connect(deployer).modifyFee(erc20A.address, erc20B.address, 1000, 1, 10, charlieWallet.address, davidWallet.address), + transferManager.connect(deployer).modifyFee(erc20A.target, erc20B.target, 1000, 1, 10, charlieWallet.address, davidWallet.address), ).to.be.revertedWith('invalid fee settings'); }); }); @@ -153,7 +157,7 @@ describe('DVDTransferManager', () => { } = await loadFixture(deployFullSuiteWithTransferManager); await expect( - transferManager.connect(deployer).modifyFee(erc20A.address, erc20B.address, 2, 0, 2, ethers.constants.AddressZero, davidWallet.address), + transferManager.connect(deployer).modifyFee(erc20A.target, erc20B.target, 2, 0, 2, ethers.ZeroAddress, davidWallet.address), ).to.be.revertedWith('fee wallet 1 cannot be zero address'); }); }); @@ -166,9 +170,7 @@ describe('DVDTransferManager', () => { } = await loadFixture(deployFullSuiteWithTransferManager); await expect( - transferManager - .connect(deployer) - .modifyFee(erc20A.address, erc20B.address, 0, 1, 2, ethers.constants.AddressZero, ethers.constants.AddressZero), + transferManager.connect(deployer).modifyFee(erc20A.target, erc20B.target, 0, 1, 2, ethers.ZeroAddress, ethers.ZeroAddress), ).to.be.revertedWith('fee wallet 2 cannot be zero address'); }); }); @@ -183,13 +185,13 @@ describe('DVDTransferManager', () => { const tx = await transferManager .connect(deployer) - .modifyFee(erc20A.address, erc20B.address, 2, 1, 2, charlieWallet.address, davidWallet.address); + .modifyFee(erc20A.target, erc20B.target, 2, 1, 2, charlieWallet.address, davidWallet.address); await expect(tx) .to.emit(transferManager, 'FeeModified') .withArgs( - ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['address', 'address'], [erc20A.address, erc20B.address])), - erc20A.address, - erc20B.address, + ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address', 'address'], [erc20A.target, erc20B.target])), + erc20A.target, + erc20B.target, 2, 1, 2, @@ -199,9 +201,9 @@ describe('DVDTransferManager', () => { await expect(tx) .to.emit(transferManager, 'FeeModified') .withArgs( - ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['address', 'address'], [erc20B.address, erc20A.address])), - erc20B.address, - erc20A.address, + ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address', 'address'], [erc20B.target, erc20A.target])), + erc20B.target, + erc20A.target, 1, 2, 2, @@ -218,29 +220,29 @@ describe('DVDTransferManager', () => { const tx = await transferManager .connect(deployer) - .modifyFee(erc20A.address, erc20B.address, 2, 0, 2, charlieWallet.address, ethers.constants.AddressZero); + .modifyFee(erc20A.target, erc20B.target, 2, 0, 2, charlieWallet.address, ethers.ZeroAddress); await expect(tx) .to.emit(transferManager, 'FeeModified') .withArgs( - ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['address', 'address'], [erc20A.address, erc20B.address])), - erc20A.address, - erc20B.address, + ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address', 'address'], [erc20A.target, erc20B.target])), + erc20A.target, + erc20B.target, 2, 0, 2, charlieWallet.address, - ethers.constants.AddressZero, + ethers.ZeroAddress, ); await expect(tx) .to.emit(transferManager, 'FeeModified') .withArgs( - ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['address', 'address'], [erc20B.address, erc20A.address])), - erc20B.address, - erc20A.address, + ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address', 'address'], [erc20B.target, erc20A.target])), + erc20B.target, + erc20A.target, 0, 2, 2, - ethers.constants.AddressZero, + ethers.ZeroAddress, charlieWallet.address, ); }); @@ -257,7 +259,7 @@ describe('DVDTransferManager', () => { } = await loadFixture(deployFullSuiteWithTransferManager); await expect( - transferManager.connect(charlieWallet).initiateDVDTransfer(erc20A.address, 1000, charlieWallet.address, erc20B.address, 1000), + transferManager.connect(charlieWallet).initiateDVDTransfer(erc20A.target, 1000, charlieWallet.address, erc20B.target, 1000), ).to.be.revertedWith('Not enough tokens in balance'); }); }); @@ -271,7 +273,7 @@ describe('DVDTransferManager', () => { await erc20A.connect(deployer).mint(charlieWallet.address, 1000); await expect( - transferManager.connect(charlieWallet).initiateDVDTransfer(erc20A.address, 1000, davidWallet.address, erc20B.address, 1000), + transferManager.connect(charlieWallet).initiateDVDTransfer(erc20A.target, 1000, davidWallet.address, erc20B.target, 1000), ).to.be.revertedWith('not enough allowance to initiate transfer'); }); }); @@ -284,9 +286,9 @@ describe('DVDTransferManager', () => { } = await loadFixture(deployFullSuiteWithTransferManager); await erc20A.connect(deployer).mint(charlieWallet.address, 1000); - await erc20A.connect(charlieWallet).approve(transferManager.address, 1000); + await erc20A.connect(charlieWallet).approve(transferManager.target, 1000); await expect( - transferManager.connect(charlieWallet).initiateDVDTransfer(erc20A.address, 1000, ethers.constants.AddressZero, erc20B.address, 1000), + transferManager.connect(charlieWallet).initiateDVDTransfer(erc20A.target, 1000, ethers.ZeroAddress, erc20B.target, 1000), ).to.be.revertedWith('counterpart cannot be null'); }); }); @@ -299,9 +301,9 @@ describe('DVDTransferManager', () => { } = await loadFixture(deployFullSuiteWithTransferManager); await erc20A.connect(deployer).mint(charlieWallet.address, 1000); - await erc20A.connect(charlieWallet).approve(transferManager.address, 1000); + await erc20A.connect(charlieWallet).approve(transferManager.target, 1000); await expect( - transferManager.connect(charlieWallet).initiateDVDTransfer(erc20A.address, 1000, davidWallet.address, erc20C.address, 1000), + transferManager.connect(charlieWallet).initiateDVDTransfer(erc20A.target, 1000, davidWallet.address, erc20C.target, 1000), ).to.be.revertedWith('invalid address : address is not an ERC20'); }); }); @@ -314,11 +316,11 @@ describe('DVDTransferManager', () => { } = await loadFixture(deployFullSuiteWithTransferManager); await erc20A.connect(deployer).mint(charlieWallet.address, 1000); - await erc20A.connect(charlieWallet).approve(transferManager.address, 1000); - const tx = await transferManager.connect(charlieWallet).initiateDVDTransfer(erc20A.address, 1000, davidWallet.address, erc20B.address, 500); + await erc20A.connect(charlieWallet).approve(transferManager.target, 1000); + const tx = await transferManager.connect(charlieWallet).initiateDVDTransfer(erc20A.target, 1000, davidWallet.address, erc20B.target, 500); await expect(tx) .to.emit(transferManager, 'DVDTransferInitiated') - .withArgs(anyValue, charlieWallet.address, erc20A.address, 1000, davidWallet.address, erc20B.address, 500); + .withArgs(anyValue, charlieWallet.address, erc20A.target, 1000, davidWallet.address, erc20B.target, 500); }); }); }); @@ -331,9 +333,7 @@ describe('DVDTransferManager', () => { accounts: { charlieWallet }, } = await loadFixture(deployFullSuiteWithTransferManager); - await expect(transferManager.connect(charlieWallet).cancelDVDTransfer(ethers.constants.HashZero)).to.be.revertedWith( - 'transfer ID does not exist', - ); + await expect(transferManager.connect(charlieWallet).cancelDVDTransfer(ethers.ZeroHash)).to.be.revertedWith('transfer ID does not exist'); }); }); @@ -416,9 +416,7 @@ describe('DVDTransferManager', () => { accounts: { charlieWallet }, } = await loadFixture(deployFullSuiteWithTransferManager); - await expect(transferManager.connect(charlieWallet).takeDVDTransfer(ethers.constants.HashZero)).to.be.revertedWith( - 'transfer ID does not exist', - ); + await expect(transferManager.connect(charlieWallet).takeDVDTransfer(ethers.ZeroHash)).to.be.revertedWith('transfer ID does not exist'); }); }); @@ -445,7 +443,7 @@ describe('DVDTransferManager', () => { values: { transferId }, } = await loadFixture(deployFullSuiteWithTransferManagerAndInitiatedTransfer); - await transferManager.modifyFee(erc20A.address, erc20B.address, 1, 2, 2, charlieWallet.address, davidWallet.address); + await transferManager.modifyFee(erc20A.target, erc20B.target, 1, 2, 2, charlieWallet.address, davidWallet.address); const tx = await transferManager.connect(bobWallet).takeDVDTransfer(transferId); await expect(tx).to.emit(transferManager, 'DVDTransferExecuted').withArgs(transferId); @@ -483,7 +481,7 @@ describe('DVDTransferManager', () => { accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteWithTransferManager); - expect(await transferManager.isTREXAgent(token.address, anotherWallet.address)).to.be.false; + expect(await transferManager.isTREXAgent(token.target, anotherWallet.address)).to.be.false; }); }); @@ -494,7 +492,7 @@ describe('DVDTransferManager', () => { accounts: { tokenAgent }, } = await loadFixture(deployFullSuiteWithTransferManager); - expect(await transferManager.isTREXAgent(token.address, tokenAgent.address)).to.be.true; + expect(await transferManager.isTREXAgent(token.target, tokenAgent.address)).to.be.true; }); }); }); @@ -507,7 +505,7 @@ describe('DVDTransferManager', () => { accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteWithTransferManager); - expect(await transferManager.isTREXOwner(token.address, anotherWallet.address)).to.be.false; + expect(await transferManager.isTREXOwner(token.target, anotherWallet.address)).to.be.false; }); }); @@ -518,7 +516,7 @@ describe('DVDTransferManager', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteWithTransferManager); - expect(await transferManager.isTREXOwner(token.address, deployer.address)).to.be.true; + expect(await transferManager.isTREXOwner(token.target, deployer.address)).to.be.true; }); }); }); @@ -530,9 +528,9 @@ describe('DVDTransferManager', () => { suite: { transferManager, token }, } = await loadFixture(deployFullSuiteWithTransferManager); - await token.setIdentityRegistry(ethers.constants.AddressZero); + await token.setIdentityRegistry(ethers.ZeroAddress); - expect(await transferManager.isTREX(token.address)).to.be.false; + expect(await transferManager.isTREX(token.target)).to.be.false; }); }); }); diff --git a/test/factory.test.ts b/test/factory.test.ts index 63f4c7e4..e126a847 100644 --- a/test/factory.test.ts +++ b/test/factory.test.ts @@ -2,11 +2,21 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { expect } from 'chai'; import { ethers } from 'hardhat'; -import { Event } from 'ethers'; +import { EventLog, ContractTransactionResponse } from 'ethers'; import OnchainID from '@onchain-id/solidity'; import { deployFullSuiteFixture } from './fixtures/deploy-full-suite.fixture'; describe('TREXFactory', () => { + async function getTREXSuiteDeployedTokenAddress(tx: ContractTransactionResponse): Promise { + const receipt = await tx.wait(); + if (!receipt) throw new Error('ContractTransactionReceipt is null'); + + const event = receipt.logs.find((e) => (e as EventLog)?.fragment?.name === 'TREXSuiteDeployed') as EventLog; + if (!event) throw new Error('TREXSuiteDeployed event not found'); + + return event.args[0]; + } + describe('.deployTREXSuite()', () => { describe('when called by not owner', () => { it('should revert', async () => { @@ -23,8 +33,8 @@ describe('TREXFactory', () => { name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -55,8 +65,8 @@ describe('TREXFactory', () => { name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -77,8 +87,8 @@ describe('TREXFactory', () => { name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -109,8 +119,8 @@ describe('TREXFactory', () => { name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -118,7 +128,7 @@ describe('TREXFactory', () => { }, { claimTopics: [], - issuers: [ethers.constants.AddressZero], + issuers: [ethers.ZeroAddress], issuerClaims: [], }, ), @@ -141,8 +151,8 @@ describe('TREXFactory', () => { name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -150,7 +160,7 @@ describe('TREXFactory', () => { }, { claimTopics: [], - issuers: Array.from({ length: 6 }, () => ethers.constants.AddressZero), + issuers: Array.from({ length: 6 }, () => ethers.ZeroAddress), issuerClaims: Array.from({ length: 6 }, () => []), }, ), @@ -173,15 +183,15 @@ describe('TREXFactory', () => { name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], complianceSettings: [], }, { - claimTopics: Array.from({ length: 6 }, () => ethers.constants.HashZero), + claimTopics: Array.from({ length: 6 }, () => ethers.ZeroHash), issuers: [], issuerClaims: [], }, @@ -205,9 +215,9 @@ describe('TREXFactory', () => { name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, - irAgents: Array.from({ length: 6 }, () => ethers.constants.AddressZero), + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, + irAgents: Array.from({ length: 6 }, () => ethers.ZeroAddress), tokenAgents: [], complianceModules: [], complianceSettings: [], @@ -237,11 +247,11 @@ describe('TREXFactory', () => { name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], - complianceModules: Array.from({ length: 31 }, () => ethers.constants.AddressZero), + complianceModules: Array.from({ length: 31 }, () => ethers.ZeroAddress), complianceSettings: [], }, { @@ -269,8 +279,8 @@ describe('TREXFactory', () => { name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -303,21 +313,21 @@ describe('TREXFactory', () => { name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [aliceWallet.address], tokenAgents: [bobWallet.address], - complianceModules: [countryAllowModule.address], + complianceModules: [countryAllowModule.target], complianceSettings: [ - new ethers.utils.Interface(['function batchAllowCountries(uint16[] calldata countries)']).encodeFunctionData('batchAllowCountries', [ + new ethers.Interface(['function batchAllowCountries(uint16[] calldata countries)']).encodeFunctionData('batchAllowCountries', [ [42, 66], ]), ], }, { - claimTopics: [ethers.utils.keccak256(ethers.utils.toUtf8Bytes('DEMO_TOPIC'))], - issuers: [claimIssuerContract.address], - issuerClaims: [[ethers.utils.keccak256(ethers.utils.toUtf8Bytes('DEMO_TOPIC'))]], + claimTopics: [ethers.keccak256(ethers.toUtf8Bytes('DEMO_TOPIC'))], + issuers: [claimIssuerContract.target], + issuerClaims: [[ethers.keccak256(ethers.toUtf8Bytes('DEMO_TOPIC'))]], }, ); expect(tx).to.emit(trexFactory, 'TREXSuiteDeployed'); @@ -343,8 +353,8 @@ describe('TREXFactory', () => { name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -357,8 +367,7 @@ describe('TREXFactory', () => { }, ); - const receipt = await tx.wait(); - const tokenAddressExpected = receipt.events.find((event: Event) => event.event === 'TREXSuiteDeployed').args[0]; + const tokenAddressExpected = await getTREXSuiteDeployedTokenAddress(tx); const tokenAddress = await trexFactory.getToken('salt'); expect(tokenAddress).to.equal(tokenAddressExpected); @@ -374,7 +383,7 @@ describe('TREXFactory', () => { factories: { trexFactory }, } = await loadFixture(deployFullSuiteFixture); - await expect(trexFactory.connect(deployer).setIdFactory(ethers.constants.AddressZero)).to.be.revertedWith('invalid argument - zero address'); + await expect(trexFactory.connect(deployer).setIdFactory(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); }); }); describe('when try to input a valid address', () => { @@ -386,12 +395,12 @@ describe('TREXFactory', () => { } = await loadFixture(deployFullSuiteFixture); const newIdFactory = await new ethers.ContractFactory(OnchainID.contracts.Factory.abi, OnchainID.contracts.Factory.bytecode, deployer).deploy( - identityImplementationAuthority.address, + identityImplementationAuthority.target, ); - const tx = await trexFactory.setIdFactory(newIdFactory.address); + const tx = await trexFactory.setIdFactory(newIdFactory.target); expect(tx).to.emit(trexFactory, 'IdFactorySet'); - expect(await trexFactory.getIdFactory()).to.equal(newIdFactory.address); + expect(await trexFactory.getIdFactory()).to.equal(newIdFactory.target); }); }); }); @@ -411,8 +420,8 @@ describe('TREXFactory', () => { name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -425,8 +434,7 @@ describe('TREXFactory', () => { }, ); - const receipt = await tx.wait(); - const tokenAddress = receipt.events.find((event: Event) => event.event === 'TREXSuiteDeployed').args[0]; + const tokenAddress = await getTREXSuiteDeployedTokenAddress(tx); await expect(trexFactory.connect(aliceWallet).recoverContractOwnership(tokenAddress, aliceWallet.address)).to.be.revertedWith( 'Ownable: caller is not the owner', @@ -444,12 +452,12 @@ describe('TREXFactory', () => { const deployTx = await trexFactory.connect(deployer).deployTREXSuite( 'salt', { - owner: trexFactory.address, + owner: trexFactory.target, name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -462,14 +470,13 @@ describe('TREXFactory', () => { }, ); - const receipt = await deployTx.wait(); - const tokenAddress = receipt.events.find((event: Event) => event.event === 'TREXSuiteDeployed').args[0]; + const tokenAddress = await getTREXSuiteDeployedTokenAddress(deployTx); const tx = await trexFactory.connect(deployer).recoverContractOwnership(tokenAddress, aliceWallet.address); const token = await ethers.getContractAt('Token', tokenAddress); - await expect(tx).to.emit(token, 'OwnershipTransferred').withArgs(trexFactory.address, aliceWallet.address); + await expect(tx).to.emit(token, 'OwnershipTransferred').withArgs(trexFactory.target, aliceWallet.address); await expect(token.owner()).to.eventually.eq(aliceWallet.address); }); diff --git a/test/fixtures/deploy-full-suite.fixture.ts b/test/fixtures/deploy-full-suite.fixture.ts index eefa68ed..46411712 100644 --- a/test/fixtures/deploy-full-suite.fixture.ts +++ b/test/fixtures/deploy-full-suite.fixture.ts @@ -1,15 +1,15 @@ -import { BigNumber, Contract, Signer } from 'ethers'; +import { Contract, Signer } from 'ethers'; import { ethers } from 'hardhat'; import OnchainID from '@onchain-id/solidity'; import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { IIdFactory } from '../../typechain-types'; -export async function deployIdentityProxy(implementationAuthority: Contract['address'], managementKey: string, signer: Signer) { +export async function deployIdentityProxy(implementationAuthority: Contract['target'], managementKey: string, signer: Signer) { const identity = await new ethers.ContractFactory(OnchainID.contracts.IdentityProxy.abi, OnchainID.contracts.IdentityProxy.bytecode, signer).deploy( implementationAuthority, managementKey, ); - - return ethers.getContractAt('Identity', identity.address, signer); + return ethers.getContractAt('Identity', identity.target, signer); } export async function deployFullSuiteFixture() { @@ -17,7 +17,6 @@ export async function deployFullSuiteFixture() { await ethers.getSigners(); const claimIssuerSigningKey = ethers.Wallet.createRandom(); const aliceActionKey = ethers.Wallet.createRandom(); - // Deploy implementations const claimTopicsRegistryImplementation = await ethers.deployContract('ClaimTopicsRegistry', deployer); const trustedIssuersRegistryImplementation = await ethers.deployContract('TrustedIssuersRegistry', deployer); @@ -30,20 +29,17 @@ export async function deployFullSuiteFixture() { OnchainID.contracts.Identity.bytecode, deployer, ).deploy(deployer.address, true); - const identityImplementationAuthority = await new ethers.ContractFactory( OnchainID.contracts.ImplementationAuthority.abi, OnchainID.contracts.ImplementationAuthority.bytecode, deployer, - ).deploy(identityImplementation.address); - + ).deploy(identityImplementation.target); const identityFactory = await new ethers.ContractFactory(OnchainID.contracts.Factory.abi, OnchainID.contracts.Factory.bytecode, deployer).deploy( - identityImplementationAuthority.address, + identityImplementationAuthority.target, ); - const trexImplementationAuthority = await ethers.deployContract( 'TREXImplementationAuthority', - [true, ethers.constants.AddressZero, ethers.constants.AddressZero], + [true, ethers.ZeroAddress, ethers.ZeroAddress], deployer, ); const versionStruct = { @@ -52,102 +48,89 @@ export async function deployFullSuiteFixture() { patch: 0, }; const contractsStruct = { - tokenImplementation: tokenImplementation.address, - ctrImplementation: claimTopicsRegistryImplementation.address, - irImplementation: identityRegistryImplementation.address, - irsImplementation: identityRegistryStorageImplementation.address, - tirImplementation: trustedIssuersRegistryImplementation.address, - mcImplementation: modularComplianceImplementation.address, + tokenImplementation: tokenImplementation.target, + ctrImplementation: claimTopicsRegistryImplementation.target, + irImplementation: identityRegistryImplementation.target, + irsImplementation: identityRegistryStorageImplementation.target, + tirImplementation: trustedIssuersRegistryImplementation.target, + mcImplementation: modularComplianceImplementation.target, }; await trexImplementationAuthority.connect(deployer).addAndUseTREXVersion(versionStruct, contractsStruct); - const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.address, identityFactory.address], deployer); - await identityFactory.connect(deployer).addTokenFactory(trexFactory.address); + const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.target, identityFactory.target], deployer); + await (identityFactory.connect(deployer) as IIdFactory).addTokenFactory(trexFactory.target); const claimTopicsRegistry = await ethers - .deployContract('ClaimTopicsRegistryProxy', [trexImplementationAuthority.address], deployer) - .then(async (proxy) => ethers.getContractAt('ClaimTopicsRegistry', proxy.address)); - + .deployContract('ClaimTopicsRegistryProxy', [trexImplementationAuthority.target], deployer) + .then(async (proxy) => ethers.getContractAt('ClaimTopicsRegistry', proxy.target)); const trustedIssuersRegistry = await ethers - .deployContract('TrustedIssuersRegistryProxy', [trexImplementationAuthority.address], deployer) - .then(async (proxy) => ethers.getContractAt('TrustedIssuersRegistry', proxy.address)); - + .deployContract('TrustedIssuersRegistryProxy', [trexImplementationAuthority.target], deployer) + .then(async (proxy) => ethers.getContractAt('TrustedIssuersRegistry', proxy.target)); const identityRegistryStorage = await ethers - .deployContract('IdentityRegistryStorageProxy', [trexImplementationAuthority.address], deployer) - .then(async (proxy) => ethers.getContractAt('IdentityRegistryStorage', proxy.address)); - + .deployContract('IdentityRegistryStorageProxy', [trexImplementationAuthority.target], deployer) + .then(async (proxy) => ethers.getContractAt('IdentityRegistryStorage', proxy.target)); const defaultCompliance = await ethers.deployContract('DefaultCompliance', deployer); const identityRegistry = await ethers .deployContract( 'IdentityRegistryProxy', - [trexImplementationAuthority.address, trustedIssuersRegistry.address, claimTopicsRegistry.address, identityRegistryStorage.address], + [trexImplementationAuthority.target, trustedIssuersRegistry.target, claimTopicsRegistry.target, identityRegistryStorage.target], deployer, ) - .then(async (proxy) => ethers.getContractAt('IdentityRegistry', proxy.address)); + .then(async (proxy) => ethers.getContractAt('IdentityRegistry', proxy.target)); - const tokenOID = await deployIdentityProxy(identityImplementationAuthority.address, tokenIssuer.address, deployer); + const tokenOID = await deployIdentityProxy(identityImplementationAuthority.target, tokenIssuer.address, deployer); const tokenName = 'TREXDINO'; const tokenSymbol = 'TREX'; - const tokenDecimals = BigNumber.from('0'); + const tokenDecimals = 0n; const token = await ethers .deployContract( 'TokenProxy', - [ - trexImplementationAuthority.address, - identityRegistry.address, - defaultCompliance.address, - tokenName, - tokenSymbol, - tokenDecimals, - tokenOID.address, - ], + [trexImplementationAuthority.target, identityRegistry.target, defaultCompliance.target, tokenName, tokenSymbol, tokenDecimals, tokenOID.target], deployer, ) - .then(async (proxy) => ethers.getContractAt('Token', proxy.address)); - - const agentManager = await ethers.deployContract('AgentManager', [token.address], tokenAgent); - - await identityRegistryStorage.connect(deployer).bindIdentityRegistry(identityRegistry.address); + .then(async (proxy) => ethers.getContractAt('Token', proxy.target)); + const agentManager = await ethers.deployContract('AgentManager', [token.target], tokenAgent); + await identityRegistryStorage.connect(deployer).bindIdentityRegistry(identityRegistry.target); await token.connect(deployer).addAgent(tokenAgent.address); - const claimTopics = [ethers.utils.id('CLAIM_TOPIC')]; + const claimTopics = [ethers.keccak256(ethers.toUtf8Bytes('CLAIM_TOPIC'))]; await claimTopicsRegistry.connect(deployer).addClaimTopic(claimTopics[0]); const claimIssuerContract = await ethers.deployContract('ClaimIssuer', [claimIssuer.address], claimIssuer); await claimIssuerContract .connect(claimIssuer) - .addKey(ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['address'], [claimIssuerSigningKey.address])), 3, 1); + .addKey(ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address'], [claimIssuerSigningKey.address])), 3, 1); - await trustedIssuersRegistry.connect(deployer).addTrustedIssuer(claimIssuerContract.address, claimTopics); + await trustedIssuersRegistry.connect(deployer).addTrustedIssuer(claimIssuerContract.target, claimTopics); - const aliceIdentity = await deployIdentityProxy(identityImplementationAuthority.address, aliceWallet.address, deployer); + const aliceIdentity = await deployIdentityProxy(identityImplementationAuthority.target, aliceWallet.address, deployer); await aliceIdentity .connect(aliceWallet) - .addKey(ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['address'], [aliceActionKey.address])), 2, 1); - const bobIdentity = await deployIdentityProxy(identityImplementationAuthority.address, bobWallet.address, deployer); - const charlieIdentity = await deployIdentityProxy(identityImplementationAuthority.address, charlieWallet.address, deployer); + .addKey(ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address'], [aliceActionKey.address])), 2, 1); + const bobIdentity = await deployIdentityProxy(identityImplementationAuthority.target, bobWallet.address, deployer); + const charlieIdentity = await deployIdentityProxy(identityImplementationAuthority.target, charlieWallet.address, deployer); await identityRegistry.connect(deployer).addAgent(tokenAgent.address); - await identityRegistry.connect(deployer).addAgent(token.address); + await identityRegistry.connect(deployer).addAgent(token.target); await identityRegistry .connect(tokenAgent) - .batchRegisterIdentity([aliceWallet.address, bobWallet.address], [aliceIdentity.address, bobIdentity.address], [42, 666]); + .batchRegisterIdentity([aliceWallet.address, bobWallet.address], [aliceIdentity.target, bobIdentity.target], [42, 666]); const claimForAlice = { - data: ethers.utils.hexlify(ethers.utils.toUtf8Bytes('Some claim public data.')), - issuer: claimIssuerContract.address, + data: ethers.hexlify(ethers.toUtf8Bytes('Some claim public data.')), + issuer: claimIssuerContract.target, topic: claimTopics[0], scheme: 1, - identity: aliceIdentity.address, + identity: aliceIdentity.target, signature: '', }; claimForAlice.signature = await claimIssuerSigningKey.signMessage( - ethers.utils.arrayify( - ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode(['address', 'uint256', 'bytes'], [claimForAlice.identity, claimForAlice.topic, claimForAlice.data]), + ethers.getBytes( + ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [claimForAlice.identity, claimForAlice.topic, claimForAlice.data]), ), ), ); @@ -157,17 +140,17 @@ export async function deployFullSuiteFixture() { .addClaim(claimForAlice.topic, claimForAlice.scheme, claimForAlice.issuer, claimForAlice.signature, claimForAlice.data, ''); const claimForBob = { - data: ethers.utils.hexlify(ethers.utils.toUtf8Bytes('Some claim public data.')), - issuer: claimIssuerContract.address, + data: ethers.hexlify(ethers.toUtf8Bytes('Some claim public data.')), + issuer: claimIssuerContract.target, topic: claimTopics[0], scheme: 1, - identity: bobIdentity.address, + identity: bobIdentity.target, signature: '', }; claimForBob.signature = await claimIssuerSigningKey.signMessage( - ethers.utils.arrayify( - ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode(['address', 'uint256', 'bytes'], [claimForBob.identity, claimForBob.topic, claimForBob.data]), + ethers.getBytes( + ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [claimForBob.identity, claimForBob.topic, claimForBob.data]), ), ), ); @@ -180,8 +163,8 @@ export async function deployFullSuiteFixture() { await token.connect(tokenAgent).mint(bobWallet.address, 500); await agentManager.connect(tokenAgent).addAgentAdmin(tokenAdmin.address); - await token.connect(deployer).addAgent(agentManager.address); - await identityRegistry.connect(deployer).addAgent(agentManager.address); + await token.connect(deployer).addAgent(agentManager.target); + await identityRegistry.connect(deployer).addAgent(agentManager.target); await token.connect(tokenAgent).unpause(); @@ -238,9 +221,8 @@ export async function deployFullSuiteFixture() { export async function deploySuiteWithModularCompliancesFixture() { const context = await loadFixture(deployFullSuiteFixture); - - const complianceProxy = await ethers.deployContract('ModularComplianceProxy', [context.authorities.trexImplementationAuthority.address]); - const compliance = await ethers.getContractAt('ModularCompliance', complianceProxy.address); + const complianceProxy = await ethers.deployContract('ModularComplianceProxy', [context.authorities.trexImplementationAuthority.target]); + const compliance = await ethers.getContractAt('ModularCompliance', complianceProxy.target); const complianceBeta = await ethers.deployContract('ModularCompliance'); await complianceBeta.init(); @@ -262,9 +244,9 @@ export async function deploySuiteWithModuleComplianceBoundToWallet() { await compliance.init(); const complianceModuleA = await ethers.deployContract('CountryAllowModule'); - await compliance.addModule(complianceModuleA.address); + await compliance.addModule(complianceModuleA.target); const complianceModuleB = await ethers.deployContract('CountryAllowModule'); - await compliance.addModule(complianceModuleB.address); + await compliance.addModule(complianceModuleB.target); await compliance.bindToken(context.accounts.charlieWallet.address); diff --git a/test/gateway.test.ts b/test/gateway.test.ts index 0c5113b6..24b962af 100644 --- a/test/gateway.test.ts +++ b/test/gateway.test.ts @@ -10,10 +10,10 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); - await expect(gateway.connect(context.accounts.anotherWallet).setFactory(context.factories.trexFactory.address)).to.be.revertedWith( + await expect(gateway.connect(context.accounts.anotherWallet).setFactory(context.factories.trexFactory.target)).to.be.revertedWith( 'Ownable: caller is not the owner', ); }); @@ -23,23 +23,23 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); - await expect(gateway.setFactory(ethers.constants.AddressZero)).to.be.revertedWithCustomError(gateway, 'ZeroAddress'); + await expect(gateway.setFactory(ethers.ZeroAddress)).to.be.revertedWithCustomError(gateway, 'ZeroAddress'); }); }); describe('if called with valid address', () => { it('should set Factory', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); - expect(await gateway.getFactory()).to.equal(ethers.constants.AddressZero); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); + expect(await gateway.getFactory()).to.equal(ethers.ZeroAddress); - const tx = await gateway.setFactory(context.factories.trexFactory.address); + const tx = await gateway.setFactory(context.factories.trexFactory.target); expect(tx).to.emit(gateway, 'FactorySet'); - expect(await gateway.getFactory()).to.equal(context.factories.trexFactory.address); + expect(await gateway.getFactory()).to.equal(context.factories.trexFactory.target); }); }); }); @@ -49,8 +49,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect(gateway.connect(context.accounts.anotherWallet).setPublicDeploymentStatus(true)).to.be.revertedWith( 'Ownable: caller is not the owner', @@ -62,8 +62,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect(gateway.setPublicDeploymentStatus(false)).to.be.revertedWithCustomError(gateway, 'PublicDeploymentAlreadyDisabled'); await gateway.setPublicDeploymentStatus(true); @@ -74,8 +74,8 @@ describe('TREXGateway', () => { it('should set new status', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); expect(await gateway.getPublicDeploymentStatus()).to.equal(false); const tx = await gateway.setPublicDeploymentStatus(true); @@ -90,8 +90,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect( gateway.connect(context.accounts.anotherWallet).transferFactoryOwnership(context.accounts.anotherWallet.address), @@ -102,8 +102,8 @@ describe('TREXGateway', () => { it('should transfer factory ownership', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const tx = await gateway.transferFactoryOwnership(context.accounts.deployer.address); expect(tx).to.emit(context.factories.trexFactory, 'OwnershipTransferred'); @@ -115,8 +115,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect(gateway.connect(context.accounts.anotherWallet).enableDeploymentFee(true)).to.be.revertedWith( 'Ownable: caller is not the owner', @@ -128,8 +128,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect(gateway.enableDeploymentFee(false)).to.be.revertedWithCustomError(gateway, 'DeploymentFeesAlreadyDisabled'); await gateway.enableDeploymentFee(true); @@ -140,8 +140,8 @@ describe('TREXGateway', () => { it('should set new status', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); expect(await gateway.isDeploymentFeeEnabled()).to.equal(false); const tx = await gateway.enableDeploymentFee(true); @@ -156,11 +156,11 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect( - gateway.connect(context.accounts.anotherWallet).setDeploymentFee(100, context.suite.token.address, context.accounts.anotherWallet.address), + gateway.connect(context.accounts.anotherWallet).setDeploymentFee(100, context.suite.token.target, context.accounts.anotherWallet.address), ).to.be.revertedWith('Ownable: caller is not the owner'); }); }); @@ -169,14 +169,14 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); - await expect(gateway.setDeploymentFee(100, ethers.constants.AddressZero, context.accounts.deployer.address)).to.be.revertedWithCustomError( + await expect(gateway.setDeploymentFee(100, ethers.ZeroAddress, context.accounts.deployer.address)).to.be.revertedWithCustomError( gateway, 'ZeroAddress', ); - await expect(gateway.setDeploymentFee(100, context.suite.token.address, ethers.constants.AddressZero)).to.be.revertedWithCustomError( + await expect(gateway.setDeploymentFee(100, context.suite.token.target, ethers.ZeroAddress)).to.be.revertedWithCustomError( gateway, 'ZeroAddress', ); @@ -186,14 +186,14 @@ describe('TREXGateway', () => { it('should set new fees structure', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); - const tx = await gateway.setDeploymentFee(100, context.suite.token.address, context.accounts.deployer.address); + const tx = await gateway.setDeploymentFee(100, context.suite.token.target, context.accounts.deployer.address); expect(tx).to.emit(gateway, 'DeploymentFeeSet'); const feeStructure = await gateway.getDeploymentFee(); expect(feeStructure.fee).to.equal(100); - expect(feeStructure.feeToken).to.equal(context.suite.token.address); + expect(feeStructure.feeToken).to.equal(context.suite.token.target); expect(feeStructure.feeCollector).to.equal(context.accounts.deployer.address); }); }); @@ -204,8 +204,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect( gateway.connect(context.accounts.anotherWallet).addDeployer(context.accounts.anotherWallet.address), @@ -217,8 +217,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await gateway.addDeployer(context.accounts.tokenAgent.address); await expect(gateway.addDeployer(context.accounts.tokenAgent.address)).to.be.revertedWithCustomError(gateway, 'DeployerAlreadyExists'); @@ -228,8 +228,8 @@ describe('TREXGateway', () => { it('should add new deployer', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); expect(await gateway.isDeployer(context.accounts.tokenAgent.address)).to.equal(false); const tx = await gateway.addDeployer(context.accounts.tokenAgent.address); @@ -243,8 +243,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await gateway.addAgent(context.accounts.tokenAgent.address); await gateway.addDeployer(context.accounts.tokenAgent.address); @@ -258,8 +258,8 @@ describe('TREXGateway', () => { it('should add new deployer', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); expect(await gateway.isDeployer(context.accounts.tokenAgent.address)).to.equal(false); await gateway.addAgent(context.accounts.tokenAgent.address); @@ -275,8 +275,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect( gateway.connect(context.accounts.anotherWallet).batchAddDeployer([context.accounts.anotherWallet.address]), @@ -288,8 +288,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await gateway.addDeployer(context.accounts.tokenAgent.address); const newDeployers = Array.from({ length: 9 }, () => ethers.Wallet.createRandom().address); @@ -302,8 +302,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const duplicateAddress = ethers.Wallet.createRandom().address; const newDeployers = Array.from({ length: 501 }, () => duplicateAddress); @@ -314,8 +314,8 @@ describe('TREXGateway', () => { it('should add 1 new deployer', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); expect(await gateway.isDeployer(context.accounts.tokenAgent.address)).to.equal(false); const tx = await gateway.batchAddDeployer([context.accounts.tokenAgent.address]); @@ -324,8 +324,8 @@ describe('TREXGateway', () => { }); it('should add 10 new deployers', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const newDeployers = Array.from({ length: 10 }, () => ethers.Wallet.createRandom().address); for (let i = 0; i < newDeployers.length; i += 1) { expect(await gateway.isDeployer(newDeployers[i])).to.equal(false); @@ -345,8 +345,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await gateway.addAgent(context.accounts.anotherWallet.address); await gateway.connect(context.accounts.anotherWallet).addDeployer(context.accounts.tokenAgent.address); @@ -363,8 +363,8 @@ describe('TREXGateway', () => { it('should add 1 new deployer', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await gateway.addAgent(context.accounts.anotherWallet.address); expect(await gateway.isDeployer(context.accounts.tokenAgent.address)).to.equal(false); @@ -374,8 +374,8 @@ describe('TREXGateway', () => { }); it('should add 10 new deployers', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const newDeployers = Array.from({ length: 10 }, () => ethers.Wallet.createRandom().address); for (let i = 0; i < newDeployers.length; i += 1) { expect(await gateway.isDeployer(newDeployers[i])).to.equal(false); @@ -397,8 +397,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect( gateway.connect(context.accounts.anotherWallet).removeDeployer(context.accounts.anotherWallet.address), @@ -410,8 +410,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect(gateway.removeDeployer(context.accounts.tokenAgent.address)).to.be.revertedWithCustomError(gateway, 'DeployerDoesNotExist'); }); @@ -420,8 +420,8 @@ describe('TREXGateway', () => { it('should remove deployer', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await gateway.addDeployer(context.accounts.tokenAgent.address); expect(await gateway.isDeployer(context.accounts.tokenAgent.address)).to.equal(true); @@ -437,8 +437,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect( gateway.connect(context.accounts.anotherWallet).batchRemoveDeployer([context.accounts.anotherWallet.address]), @@ -450,8 +450,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect(gateway.batchRemoveDeployer([context.accounts.tokenAgent.address])).to.be.revertedWithCustomError( gateway, @@ -463,8 +463,8 @@ describe('TREXGateway', () => { it('should remove deployer', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await gateway.addDeployer(context.accounts.tokenAgent.address); expect(await gateway.isDeployer(context.accounts.tokenAgent.address)).to.equal(true); @@ -477,8 +477,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const deployers = Array.from({ length: 9 }, () => ethers.Wallet.createRandom().address); await gateway.batchAddDeployer(deployers); @@ -494,8 +494,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const duplicateAddress = ethers.Wallet.createRandom().address; const deployers = Array.from({ length: 501 }, () => duplicateAddress); @@ -510,8 +510,8 @@ describe('TREXGateway', () => { it('should remove deployers', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const deployers = Array.from({ length: 10 }, () => ethers.Wallet.createRandom().address); await gateway.batchAddDeployer(deployers); @@ -533,8 +533,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect( gateway.connect(context.accounts.anotherWallet).applyFeeDiscount(context.accounts.anotherWallet.address, 5000), @@ -546,8 +546,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect(gateway.applyFeeDiscount(context.accounts.anotherWallet.address, 12000)).to.be.revertedWithCustomError( gateway, @@ -559,10 +559,10 @@ describe('TREXGateway', () => { it('should apply discount', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); - await gateway.setDeploymentFee(20000, context.suite.token.address, context.accounts.deployer.address); + await gateway.setDeploymentFee(20000, context.suite.token.target, context.accounts.deployer.address); expect(await gateway.calculateFee(context.accounts.bobWallet.address)).to.equal(20000); const tx = await gateway.applyFeeDiscount(context.accounts.bobWallet.address, 5000); expect(tx).to.emit(gateway, 'FeeDiscountApplied'); @@ -576,8 +576,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect( gateway.connect(context.accounts.anotherWallet).batchApplyFeeDiscount([context.accounts.anotherWallet.address], [5000]), @@ -589,8 +589,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect(gateway.batchApplyFeeDiscount([context.accounts.anotherWallet.address], [12000])).to.be.revertedWithCustomError( gateway, @@ -602,8 +602,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const duplicateAddress = ethers.Wallet.createRandom().address; const deployers = Array.from({ length: 501 }, () => duplicateAddress); @@ -616,10 +616,10 @@ describe('TREXGateway', () => { it('should apply discount', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); - await gateway.setDeploymentFee(20000, context.suite.token.address, context.accounts.deployer.address); + await gateway.setDeploymentFee(20000, context.suite.token.target, context.accounts.deployer.address); expect(await gateway.calculateFee(context.accounts.bobWallet.address)).to.equal(20000); const tx = await gateway.batchApplyFeeDiscount([context.accounts.bobWallet.address], [5000]); expect(tx).to.emit(gateway, 'FeeDiscountApplied'); @@ -632,8 +632,8 @@ describe('TREXGateway', () => { it('should revert the whole batch', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const deployers = Array.from({ length: 10 }, () => ethers.Wallet.createRandom().address); const discounts = Array.from({ length: 9 }, () => Math.floor(Math.random() * 10000)); discounts.push(12000); @@ -649,11 +649,11 @@ describe('TREXGateway', () => { it('should apply discounts to all deployers', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [ethers.constants.AddressZero, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [ethers.ZeroAddress, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const deploymentFee = 20000; - await gateway.setDeploymentFee(deploymentFee, context.suite.token.address, context.accounts.deployer.address); + await gateway.setDeploymentFee(deploymentFee, context.suite.token.target, context.accounts.deployer.address); const deployers = Array.from({ length: 10 }, () => ethers.Wallet.createRandom().address); const discounts = Array.from({ length: 10 }, () => 5000); @@ -679,8 +679,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect( gateway.connect(context.accounts.anotherWallet).deployTREXSuite( @@ -689,8 +689,8 @@ describe('TREXGateway', () => { name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -710,8 +710,8 @@ describe('TREXGateway', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, true], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, true], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await expect( gateway.connect(context.accounts.anotherWallet).deployTREXSuite( @@ -720,8 +720,8 @@ describe('TREXGateway', () => { name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -740,8 +740,8 @@ describe('TREXGateway', () => { it('should deploy a token for free', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, true], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, true], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const tx = await gateway.connect(context.accounts.anotherWallet).deployTREXSuite( { @@ -749,8 +749,8 @@ describe('TREXGateway', () => { name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -771,22 +771,22 @@ describe('TREXGateway', () => { it('should deploy a token for full fee', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, true], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, true], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const feeToken = await ethers.deployContract('TestERC20', ['FeeToken', 'FT']); await feeToken.mint(context.accounts.anotherWallet.address, 100000); - await gateway.setDeploymentFee(20000, feeToken.address, context.accounts.deployer.address); + await gateway.setDeploymentFee(20000, feeToken.target, context.accounts.deployer.address); await gateway.enableDeploymentFee(true); - await feeToken.connect(context.accounts.anotherWallet).approve(gateway.address, 20000); + await feeToken.connect(context.accounts.anotherWallet).approve(gateway.target, 20000); const tx = await gateway.connect(context.accounts.anotherWallet).deployTREXSuite( { owner: context.accounts.anotherWallet.address, name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -808,23 +808,23 @@ describe('TREXGateway', () => { it('should deploy a token for half fee', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, true], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, true], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const feeToken = await ethers.deployContract('TestERC20', ['FeeToken', 'FT']); await feeToken.mint(context.accounts.anotherWallet.address, 100000); - await gateway.setDeploymentFee(20000, feeToken.address, context.accounts.deployer.address); + await gateway.setDeploymentFee(20000, feeToken.target, context.accounts.deployer.address); await gateway.enableDeploymentFee(true); await gateway.applyFeeDiscount(context.accounts.anotherWallet.address, 5000); - await feeToken.connect(context.accounts.anotherWallet).approve(gateway.address, 20000); + await feeToken.connect(context.accounts.anotherWallet).approve(gateway.target, 20000); const tx = await gateway.connect(context.accounts.anotherWallet).deployTREXSuite( { owner: context.accounts.anotherWallet.address, name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -850,8 +850,8 @@ describe('TREXGateway', () => { it('should deploy', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await gateway.addDeployer(context.accounts.anotherWallet.address); const tx = gateway.connect(context.accounts.anotherWallet).deployTREXSuite( @@ -860,8 +860,8 @@ describe('TREXGateway', () => { name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -881,8 +881,8 @@ describe('TREXGateway', () => { it('should deploy', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await gateway.addDeployer(context.accounts.anotherWallet.address); @@ -892,8 +892,8 @@ describe('TREXGateway', () => { name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -914,23 +914,23 @@ describe('TREXGateway', () => { it('should deploy a token for full fee', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await gateway.addDeployer(context.accounts.anotherWallet.address); const feeToken = await ethers.deployContract('TestERC20', ['FeeToken', 'FT']); await feeToken.mint(context.accounts.anotherWallet.address, 100000); - await gateway.setDeploymentFee(20000, feeToken.address, context.accounts.deployer.address); + await gateway.setDeploymentFee(20000, feeToken.target, context.accounts.deployer.address); await gateway.enableDeploymentFee(true); - await feeToken.connect(context.accounts.anotherWallet).approve(gateway.address, 20000); + await feeToken.connect(context.accounts.anotherWallet).approve(gateway.target, 20000); const tx = await gateway.connect(context.accounts.anotherWallet).deployTREXSuite( { owner: context.accounts.anotherWallet.address, name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -952,24 +952,24 @@ describe('TREXGateway', () => { it('should deploy a token for half fee', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await gateway.addDeployer(context.accounts.anotherWallet.address); const feeToken = await ethers.deployContract('TestERC20', ['FeeToken', 'FT']); await feeToken.mint(context.accounts.anotherWallet.address, 100000); - await gateway.setDeploymentFee(20000, feeToken.address, context.accounts.deployer.address); + await gateway.setDeploymentFee(20000, feeToken.target, context.accounts.deployer.address); await gateway.enableDeploymentFee(true); await gateway.applyFeeDiscount(context.accounts.anotherWallet.address, 5000); - await feeToken.connect(context.accounts.anotherWallet).approve(gateway.address, 20000); + await feeToken.connect(context.accounts.anotherWallet).approve(gateway.target, 20000); const tx = await gateway.connect(context.accounts.anotherWallet).deployTREXSuite( { owner: context.accounts.anotherWallet.address, name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -991,24 +991,24 @@ describe('TREXGateway', () => { it('should deploy a token for free', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await gateway.addDeployer(context.accounts.anotherWallet.address); const feeToken = await ethers.deployContract('TestERC20', ['FeeToken', 'FT']); await feeToken.mint(context.accounts.anotherWallet.address, 100000); - await gateway.setDeploymentFee(20000, feeToken.address, context.accounts.deployer.address); + await gateway.setDeploymentFee(20000, feeToken.target, context.accounts.deployer.address); await gateway.enableDeploymentFee(true); await gateway.applyFeeDiscount(context.accounts.anotherWallet.address, 10000); - await feeToken.connect(context.accounts.anotherWallet).approve(gateway.address, 20000); + await feeToken.connect(context.accounts.anotherWallet).approve(gateway.target, 20000); const tx = await gateway.connect(context.accounts.anotherWallet).deployTREXSuite( { owner: context.accounts.anotherWallet.address, name: 'Token name', symbol: 'SYM', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -1035,8 +1035,8 @@ describe('TREXGateway', () => { it('should revert for batch deployment', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const tokenDetailsArray = []; const claimDetailsArray = []; @@ -1046,8 +1046,8 @@ describe('TREXGateway', () => { name: `Token name ${i}`, symbol: `SYM${i}`, decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -1070,8 +1070,8 @@ describe('TREXGateway', () => { it('should revert the whole batch', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, true], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, true], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const tokenDetailsArray = []; const claimDetailsArray = []; @@ -1081,8 +1081,8 @@ describe('TREXGateway', () => { name: `Token name ${i}`, symbol: `SYM${i}`, decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -1099,8 +1099,8 @@ describe('TREXGateway', () => { name: 'Token name behalf', symbol: 'SYM42', decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -1121,8 +1121,8 @@ describe('TREXGateway', () => { it('should revert the batch', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, true], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, true], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const tokenDetailsArray = []; const claimDetailsArray = []; @@ -1132,8 +1132,8 @@ describe('TREXGateway', () => { name: `Token name ${i}`, symbol: `SYM${i}`, decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -1155,8 +1155,8 @@ describe('TREXGateway', () => { it('should deploy tokens for free in a batch', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, true], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, true], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const tokenDetailsArray = []; const claimDetailsArray = []; @@ -1166,8 +1166,8 @@ describe('TREXGateway', () => { name: `Token name ${i}`, symbol: `SYM${i}`, decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -1193,14 +1193,14 @@ describe('TREXGateway', () => { it('should deploy tokens for full fee in a batch', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, true], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, true], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const feeToken = await ethers.deployContract('TestERC20', ['FeeToken', 'FT']); await feeToken.mint(context.accounts.anotherWallet.address, 500000); - await gateway.setDeploymentFee(20000, feeToken.address, context.accounts.deployer.address); + await gateway.setDeploymentFee(20000, feeToken.target, context.accounts.deployer.address); await gateway.enableDeploymentFee(true); - await feeToken.connect(context.accounts.anotherWallet).approve(gateway.address, 100000); + await feeToken.connect(context.accounts.anotherWallet).approve(gateway.target, 100000); const tokenDetailsArray = []; const claimDetailsArray = []; @@ -1210,8 +1210,8 @@ describe('TREXGateway', () => { name: `Token name ${i}`, symbol: `SYM${i}`, decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -1238,14 +1238,14 @@ describe('TREXGateway', () => { it('should deploy tokens for half fee in a batch', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, true], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, true], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); const feeToken = await ethers.deployContract('TestERC20', ['FeeToken', 'FT']); await feeToken.mint(context.accounts.anotherWallet.address, 500000); - await gateway.setDeploymentFee(20000, feeToken.address, context.accounts.deployer.address); + await gateway.setDeploymentFee(20000, feeToken.target, context.accounts.deployer.address); await gateway.enableDeploymentFee(true); await gateway.applyFeeDiscount(context.accounts.anotherWallet.address, 5000); - await feeToken.connect(context.accounts.anotherWallet).approve(gateway.address, 50000); + await feeToken.connect(context.accounts.anotherWallet).approve(gateway.target, 50000); const tokenDetailsArray = []; const claimDetailsArray = []; @@ -1255,8 +1255,8 @@ describe('TREXGateway', () => { name: `Token name ${i}`, symbol: `SYM${i}`, decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -1286,8 +1286,8 @@ describe('TREXGateway', () => { it('should deploy in batch', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await gateway.addDeployer(context.accounts.anotherWallet.address); const tokenDetailsArray = []; @@ -1298,8 +1298,8 @@ describe('TREXGateway', () => { name: `Token name ${i}`, symbol: `SYM${i}`, decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], @@ -1324,8 +1324,8 @@ describe('TREXGateway', () => { it('should deploy in batch', async () => { const context = await loadFixture(deployFullSuiteFixture); - const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.address, false], context.accounts.deployer); - await context.factories.trexFactory.transferOwnership(gateway.address); + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + await context.factories.trexFactory.transferOwnership(gateway.target); await gateway.addDeployer(context.accounts.anotherWallet.address); const tokenDetailsArray = []; @@ -1336,8 +1336,8 @@ describe('TREXGateway', () => { name: `Token name ${i}`, symbol: `SYM${i}`, decimals: 8, - irs: ethers.constants.AddressZero, - ONCHAINID: ethers.constants.AddressZero, + irs: ethers.ZeroAddress, + ONCHAINID: ethers.ZeroAddress, irAgents: [], tokenAgents: [], complianceModules: [], diff --git a/test/registries/identity-registry-storage.test.ts b/test/registries/identity-registry-storage.test.ts index 9fa0e63f..d08fa54a 100644 --- a/test/registries/identity-registry-storage.test.ts +++ b/test/registries/identity-registry-storage.test.ts @@ -26,7 +26,7 @@ describe('IdentityRegistryStorage', () => { } = await loadFixture(deployFullSuiteFixture); await expect( - identityRegistryStorage.connect(anotherWallet).addIdentityToStorage(charlieWallet.address, charlieIdentity.address, 42), + identityRegistryStorage.connect(anotherWallet).addIdentityToStorage(charlieWallet.address, charlieIdentity.target, 42), ).to.be.revertedWith('AgentRole: caller does not have the Agent role'); }); }); @@ -42,7 +42,7 @@ describe('IdentityRegistryStorage', () => { await identityRegistryStorage.addAgent(tokenAgent.address); await expect( - identityRegistryStorage.connect(tokenAgent).addIdentityToStorage(charlieWallet.address, ethers.constants.AddressZero, 42), + identityRegistryStorage.connect(tokenAgent).addIdentityToStorage(charlieWallet.address, ethers.ZeroAddress, 42), ).to.be.revertedWith('invalid argument - zero address'); }); }); @@ -58,7 +58,7 @@ describe('IdentityRegistryStorage', () => { await identityRegistryStorage.addAgent(tokenAgent.address); await expect( - identityRegistryStorage.connect(tokenAgent).addIdentityToStorage(ethers.constants.AddressZero, charlieIdentity.address, 42), + identityRegistryStorage.connect(tokenAgent).addIdentityToStorage(ethers.ZeroAddress, charlieIdentity.target, 42), ).to.be.revertedWith('invalid argument - zero address'); }); }); @@ -74,7 +74,7 @@ describe('IdentityRegistryStorage', () => { await identityRegistryStorage.addAgent(tokenAgent.address); await expect( - identityRegistryStorage.connect(tokenAgent).addIdentityToStorage(bobWallet.address, charlieIdentity.address, 42), + identityRegistryStorage.connect(tokenAgent).addIdentityToStorage(bobWallet.address, charlieIdentity.target, 42), ).to.be.revertedWith('address stored already'); }); }); @@ -91,7 +91,7 @@ describe('IdentityRegistryStorage', () => { } = await loadFixture(deployFullSuiteFixture); await expect( - identityRegistryStorage.connect(anotherWallet).modifyStoredIdentity(charlieWallet.address, charlieIdentity.address), + identityRegistryStorage.connect(anotherWallet).modifyStoredIdentity(charlieWallet.address, charlieIdentity.target), ).to.be.revertedWith('AgentRole: caller does not have the Agent role'); }); }); @@ -107,7 +107,7 @@ describe('IdentityRegistryStorage', () => { await identityRegistryStorage.addAgent(tokenAgent.address); await expect( - identityRegistryStorage.connect(tokenAgent).modifyStoredIdentity(charlieWallet.address, ethers.constants.AddressZero), + identityRegistryStorage.connect(tokenAgent).modifyStoredIdentity(charlieWallet.address, ethers.ZeroAddress), ).to.be.revertedWith('invalid argument - zero address'); }); }); @@ -123,7 +123,7 @@ describe('IdentityRegistryStorage', () => { await identityRegistryStorage.addAgent(tokenAgent.address); await expect( - identityRegistryStorage.connect(tokenAgent).modifyStoredIdentity(ethers.constants.AddressZero, charlieIdentity.address), + identityRegistryStorage.connect(tokenAgent).modifyStoredIdentity(ethers.ZeroAddress, charlieIdentity.target), ).to.be.revertedWith('invalid argument - zero address'); }); }); @@ -139,7 +139,7 @@ describe('IdentityRegistryStorage', () => { await identityRegistryStorage.addAgent(tokenAgent.address); await expect( - identityRegistryStorage.connect(tokenAgent).modifyStoredIdentity(charlieWallet.address, charlieIdentity.address), + identityRegistryStorage.connect(tokenAgent).modifyStoredIdentity(charlieWallet.address, charlieIdentity.target), ).to.be.revertedWith('address not stored yet'); }); }); @@ -170,7 +170,7 @@ describe('IdentityRegistryStorage', () => { await identityRegistryStorage.addAgent(tokenAgent.address); - await expect(identityRegistryStorage.connect(tokenAgent).modifyStoredInvestorCountry(ethers.constants.AddressZero, 42)).to.be.revertedWith( + await expect(identityRegistryStorage.connect(tokenAgent).modifyStoredInvestorCountry(ethers.ZeroAddress, 42)).to.be.revertedWith( 'invalid argument - zero address', ); }); @@ -217,7 +217,7 @@ describe('IdentityRegistryStorage', () => { await identityRegistryStorage.addAgent(tokenAgent.address); - await expect(identityRegistryStorage.connect(tokenAgent).removeIdentityFromStorage(ethers.constants.AddressZero)).to.be.revertedWith( + await expect(identityRegistryStorage.connect(tokenAgent).removeIdentityFromStorage(ethers.ZeroAddress)).to.be.revertedWith( 'invalid argument - zero address', ); }); @@ -249,7 +249,7 @@ describe('IdentityRegistryStorage', () => { identities: { charlieIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistryStorage.connect(anotherWallet).bindIdentityRegistry(charlieIdentity.address)).to.be.revertedWith( + await expect(identityRegistryStorage.connect(anotherWallet).bindIdentityRegistry(charlieIdentity.target)).to.be.revertedWith( 'Ownable: caller is not the owner', ); }); @@ -263,7 +263,7 @@ describe('IdentityRegistryStorage', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistryStorage.connect(deployer).bindIdentityRegistry(ethers.constants.AddressZero)).to.be.revertedWith( + await expect(identityRegistryStorage.connect(deployer).bindIdentityRegistry(ethers.ZeroAddress)).to.be.revertedWith( 'invalid argument - zero address', ); }); @@ -281,7 +281,7 @@ describe('IdentityRegistryStorage', () => { Array.from({ length: 299 }, () => identityRegistryStorage.connect(deployer).bindIdentityRegistry(ethers.Wallet.createRandom().address)), ); - await expect(identityRegistryStorage.connect(deployer).bindIdentityRegistry(charlieIdentity.address)).to.be.revertedWith( + await expect(identityRegistryStorage.connect(deployer).bindIdentityRegistry(charlieIdentity.target)).to.be.revertedWith( 'cannot bind more than 300 IR to 1 IRS', ); }); @@ -298,7 +298,7 @@ describe('IdentityRegistryStorage', () => { identities: { charlieIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistryStorage.connect(anotherWallet).unbindIdentityRegistry(charlieIdentity.address)).to.be.revertedWith( + await expect(identityRegistryStorage.connect(anotherWallet).unbindIdentityRegistry(charlieIdentity.target)).to.be.revertedWith( 'Ownable: caller is not the owner', ); }); @@ -312,7 +312,7 @@ describe('IdentityRegistryStorage', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistryStorage.connect(deployer).unbindIdentityRegistry(ethers.constants.AddressZero)).to.be.revertedWith( + await expect(identityRegistryStorage.connect(deployer).unbindIdentityRegistry(ethers.ZeroAddress)).to.be.revertedWith( 'invalid argument - zero address', ); }); @@ -325,9 +325,9 @@ describe('IdentityRegistryStorage', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await identityRegistryStorage.unbindIdentityRegistry(identityRegistry.address); + await identityRegistryStorage.unbindIdentityRegistry(identityRegistry.target); - await expect(identityRegistryStorage.connect(deployer).unbindIdentityRegistry(identityRegistry.address)).to.be.revertedWith( + await expect(identityRegistryStorage.connect(deployer).unbindIdentityRegistry(identityRegistry.target)).to.be.revertedWith( 'identity registry is not stored', ); }); @@ -341,16 +341,13 @@ describe('IdentityRegistryStorage', () => { identities: { charlieIdentity, bobIdentity }, } = await loadFixture(deployFullSuiteFixture); - await identityRegistryStorage.bindIdentityRegistry(charlieIdentity.address); - await identityRegistryStorage.bindIdentityRegistry(bobIdentity.address); + await identityRegistryStorage.bindIdentityRegistry(charlieIdentity.target); + await identityRegistryStorage.bindIdentityRegistry(bobIdentity.target); - const tx = await identityRegistryStorage.connect(deployer).unbindIdentityRegistry(charlieIdentity.address); - await expect(tx).to.emit(identityRegistryStorage, 'IdentityRegistryUnbound').withArgs(charlieIdentity.address); + const tx = await identityRegistryStorage.connect(deployer).unbindIdentityRegistry(charlieIdentity.target); + await expect(tx).to.emit(identityRegistryStorage, 'IdentityRegistryUnbound').withArgs(charlieIdentity.target); - await expect(identityRegistryStorage.linkedIdentityRegistries()).to.eventually.be.deep.equal([ - identityRegistry.address, - bobIdentity.address, - ]); + await expect(identityRegistryStorage.linkedIdentityRegistries()).to.eventually.be.deep.equal([identityRegistry.target, bobIdentity.target]); }); }); }); diff --git a/test/registries/identity-registry.test.ts b/test/registries/identity-registry.test.ts index aec1b251..304697a1 100644 --- a/test/registries/identity-registry.test.ts +++ b/test/registries/identity-registry.test.ts @@ -11,27 +11,27 @@ describe('IdentityRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect( - identityRegistry.connect(deployer).init(ethers.constants.AddressZero, ethers.constants.AddressZero, ethers.constants.AddressZero), - ).to.be.revertedWith('Initializable: contract is already initialized'); + await expect(identityRegistry.connect(deployer).init(ethers.ZeroAddress, ethers.ZeroAddress, ethers.ZeroAddress)).to.be.revertedWith( + 'Initializable: contract is already initialized', + ); }); it('should reject zero address for Trusted Issuers Registry', async () => { const identityRegistry = await ethers.deployContract('IdentityRegistry'); const address = ethers.Wallet.createRandom().address; - await expect(identityRegistry.init(ethers.constants.AddressZero, address, address)).to.be.revertedWith('invalid argument - zero address'); + await expect(identityRegistry.init(ethers.ZeroAddress, address, address)).to.be.revertedWith('invalid argument - zero address'); }); it('should reject zero address for Claim Topics Registry', async () => { const identityRegistry = await ethers.deployContract('IdentityRegistry'); const address = ethers.Wallet.createRandom().address; - await expect(identityRegistry.init(address, ethers.constants.AddressZero, address)).to.be.revertedWith('invalid argument - zero address'); + await expect(identityRegistry.init(address, ethers.ZeroAddress, address)).to.be.revertedWith('invalid argument - zero address'); }); it('should reject zero address for Identity Storage', async () => { const identityRegistry = await ethers.deployContract('IdentityRegistry'); const address = ethers.Wallet.createRandom().address; - await expect(identityRegistry.init(address, address, ethers.constants.AddressZero)).to.be.revertedWith('invalid argument - zero address'); + await expect(identityRegistry.init(address, address, ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); }); }); @@ -44,7 +44,7 @@ describe('IdentityRegistry', () => { identities: { bobIdentity, charlieIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistry.connect(anotherWallet).updateIdentity(bobIdentity.address, charlieIdentity.address)).to.be.revertedWith( + await expect(identityRegistry.connect(anotherWallet).updateIdentity(bobIdentity.target, charlieIdentity.target)).to.be.revertedWith( 'AgentRole: caller does not have the Agent role', ); }); @@ -60,7 +60,7 @@ describe('IdentityRegistry', () => { identities: { bobIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistry.connect(anotherWallet).updateCountry(bobIdentity.address, 100)).to.be.revertedWith( + await expect(identityRegistry.connect(anotherWallet).updateCountry(bobIdentity.target, 100)).to.be.revertedWith( 'AgentRole: caller does not have the Agent role', ); }); @@ -90,9 +90,9 @@ describe('IdentityRegistry', () => { accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect( - identityRegistry.connect(anotherWallet).registerIdentity(ethers.constants.AddressZero, ethers.constants.AddressZero, 0), - ).to.be.revertedWith('AgentRole: caller does not have the Agent role'); + await expect(identityRegistry.connect(anotherWallet).registerIdentity(ethers.ZeroAddress, ethers.ZeroAddress, 0)).to.be.revertedWith( + 'AgentRole: caller does not have the Agent role', + ); }); }); }); @@ -105,7 +105,7 @@ describe('IdentityRegistry', () => { accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistry.connect(anotherWallet).setIdentityRegistryStorage(ethers.constants.AddressZero)).to.be.revertedWith( + await expect(identityRegistry.connect(anotherWallet).setIdentityRegistryStorage(ethers.ZeroAddress)).to.be.revertedWith( 'Ownable: caller is not the owner', ); }); @@ -118,9 +118,9 @@ describe('IdentityRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - const tx = await identityRegistry.connect(deployer).setIdentityRegistryStorage(ethers.constants.AddressZero); - await expect(tx).to.emit(identityRegistry, 'IdentityStorageSet').withArgs(ethers.constants.AddressZero); - expect(await identityRegistry.identityStorage()).to.be.equal(ethers.constants.AddressZero); + const tx = await identityRegistry.connect(deployer).setIdentityRegistryStorage(ethers.ZeroAddress); + await expect(tx).to.emit(identityRegistry, 'IdentityStorageSet').withArgs(ethers.ZeroAddress); + expect(await identityRegistry.identityStorage()).to.be.equal(ethers.ZeroAddress); }); }); }); @@ -133,7 +133,7 @@ describe('IdentityRegistry', () => { accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistry.connect(anotherWallet).setClaimTopicsRegistry(ethers.constants.AddressZero)).to.be.revertedWith( + await expect(identityRegistry.connect(anotherWallet).setClaimTopicsRegistry(ethers.ZeroAddress)).to.be.revertedWith( 'Ownable: caller is not the owner', ); }); @@ -146,9 +146,9 @@ describe('IdentityRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - const tx = await identityRegistry.connect(deployer).setClaimTopicsRegistry(ethers.constants.AddressZero); - await expect(tx).to.emit(identityRegistry, 'ClaimTopicsRegistrySet').withArgs(ethers.constants.AddressZero); - expect(await identityRegistry.topicsRegistry()).to.be.equal(ethers.constants.AddressZero); + const tx = await identityRegistry.connect(deployer).setClaimTopicsRegistry(ethers.ZeroAddress); + await expect(tx).to.emit(identityRegistry, 'ClaimTopicsRegistrySet').withArgs(ethers.ZeroAddress); + expect(await identityRegistry.topicsRegistry()).to.be.equal(ethers.ZeroAddress); }); }); }); @@ -161,7 +161,7 @@ describe('IdentityRegistry', () => { accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistry.connect(anotherWallet).setTrustedIssuersRegistry(ethers.constants.AddressZero)).to.be.revertedWith( + await expect(identityRegistry.connect(anotherWallet).setTrustedIssuersRegistry(ethers.ZeroAddress)).to.be.revertedWith( 'Ownable: caller is not the owner', ); }); @@ -174,9 +174,9 @@ describe('IdentityRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - const tx = await identityRegistry.connect(deployer).setTrustedIssuersRegistry(ethers.constants.AddressZero); - await expect(tx).to.emit(identityRegistry, 'TrustedIssuersRegistrySet').withArgs(ethers.constants.AddressZero); - expect(await identityRegistry.issuersRegistry()).to.be.equal(ethers.constants.AddressZero); + const tx = await identityRegistry.connect(deployer).setTrustedIssuersRegistry(ethers.ZeroAddress); + await expect(tx).to.emit(identityRegistry, 'TrustedIssuersRegistrySet').withArgs(ethers.ZeroAddress); + expect(await identityRegistry.issuersRegistry()).to.be.equal(ethers.ZeroAddress); }); }); }); @@ -190,7 +190,7 @@ describe('IdentityRegistry', () => { identities: { charlieIdentity }, } = await loadFixture(deployFullSuiteFixture); - await identityRegistry.connect(tokenAgent).registerIdentity(charlieWallet.address, charlieIdentity.address, 0); + await identityRegistry.connect(tokenAgent).registerIdentity(charlieWallet.address, charlieIdentity.target, 0); await expect(identityRegistry.isVerified(charlieWallet.address)).to.eventually.be.false; @@ -248,13 +248,13 @@ describe('IdentityRegistry', () => { const trickyClaimIssuer = await ethers.deployContract('ClaimIssuerTrick'); const claimTopics = await claimTopicsRegistry.getClaimTopics(); - await trustedIssuersRegistry.removeTrustedIssuer(claimIssuerContract.address); - await trustedIssuersRegistry.addTrustedIssuer(trickyClaimIssuer.address, claimTopics); - await trustedIssuersRegistry.addTrustedIssuer(claimIssuerContract.address, claimTopics); + await trustedIssuersRegistry.removeTrustedIssuer(claimIssuerContract.target); + await trustedIssuersRegistry.addTrustedIssuer(trickyClaimIssuer.target, Array.from(claimTopics)); + await trustedIssuersRegistry.addTrustedIssuer(claimIssuerContract.target, Array.from(claimTopics)); const claimIds = await aliceIdentity.getClaimIdsByTopic(claimTopics[0]); const claim = await aliceIdentity.getClaim(claimIds[0]); await aliceIdentity.connect(aliceWallet).removeClaim(claimIds[0]); - await aliceIdentity.connect(aliceWallet).addClaim(claimTopics[0], 1, trickyClaimIssuer.address, '0x00', '0x00', ''); + await aliceIdentity.connect(aliceWallet).addClaim(claimTopics[0], 1, trickyClaimIssuer.target, '0x00', '0x00', ''); await aliceIdentity.connect(aliceWallet).addClaim(claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri); await expect(identityRegistry.isVerified(aliceWallet.address)).to.eventually.be.true; @@ -269,10 +269,10 @@ describe('IdentityRegistry', () => { const trickyClaimIssuer = await ethers.deployContract('ClaimIssuerTrick'); const claimTopics = await claimTopicsRegistry.getClaimTopics(); - await trustedIssuersRegistry.addTrustedIssuer(trickyClaimIssuer.address, claimTopics); + await trustedIssuersRegistry.addTrustedIssuer(trickyClaimIssuer.target, Array.from(claimTopics)); const claimIds = await aliceIdentity.getClaimIdsByTopic(claimTopics[0]); await aliceIdentity.connect(aliceWallet).removeClaim(claimIds[0]); - await aliceIdentity.connect(aliceWallet).addClaim(claimTopics[0], 1, trickyClaimIssuer.address, '0x00', '0x00', ''); + await aliceIdentity.connect(aliceWallet).addClaim(claimTopics[0], 1, trickyClaimIssuer.target, '0x00', '0x00', ''); await expect(identityRegistry.isVerified(aliceWallet.address)).to.eventually.be.false; }); diff --git a/test/registries/trusted-issuers-registry.test.ts b/test/registries/trusted-issuers-registry.test.ts index ac80e57b..1f523087 100644 --- a/test/registries/trusted-issuers-registry.test.ts +++ b/test/registries/trusted-issuers-registry.test.ts @@ -26,7 +26,7 @@ describe('TrustedIssuersRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect(trustedIssuersRegistry.connect(deployer).addTrustedIssuer(ethers.constants.AddressZero, [10])).to.be.revertedWith( + await expect(trustedIssuersRegistry.connect(deployer).addTrustedIssuer(ethers.ZeroAddress, [10])).to.be.revertedWith( 'invalid argument - zero address', ); }); @@ -39,11 +39,11 @@ describe('TrustedIssuersRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - const claimTopics = await trustedIssuersRegistry.getTrustedIssuerClaimTopics(claimIssuerContract.address); + const claimTopics = await trustedIssuersRegistry.getTrustedIssuerClaimTopics(claimIssuerContract.target); - await expect(trustedIssuersRegistry.connect(deployer).addTrustedIssuer(claimIssuerContract.address, claimTopics)).to.be.revertedWith( - 'trusted Issuer already exists', - ); + await expect( + trustedIssuersRegistry.connect(deployer).addTrustedIssuer(claimIssuerContract.target, Array.from(claimTopics)), + ).to.be.revertedWith('trusted Issuer already exists'); }); }); @@ -121,7 +121,7 @@ describe('TrustedIssuersRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect(trustedIssuersRegistry.connect(deployer).removeTrustedIssuer(ethers.constants.AddressZero)).to.be.revertedWith( + await expect(trustedIssuersRegistry.connect(deployer).removeTrustedIssuer(ethers.ZeroAddress)).to.be.revertedWith( 'invalid argument - zero address', ); }); @@ -156,7 +156,7 @@ describe('TrustedIssuersRegistry', () => { await expect(trustedIssuersRegistry.isTrustedIssuer(anotherWallet.address)).to.eventually.be.false; await expect(trustedIssuersRegistry.getTrustedIssuers()).to.eventually.deep.eq([ - claimIssuerContract.address, + claimIssuerContract.target, bobWallet.address, charlieWallet.address, ]); @@ -187,7 +187,7 @@ describe('TrustedIssuersRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect(trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(ethers.constants.AddressZero, [10])).to.be.revertedWith( + await expect(trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(ethers.ZeroAddress, [10])).to.be.revertedWith( 'invalid argument - zero address', ); }); @@ -215,7 +215,7 @@ describe('TrustedIssuersRegistry', () => { const claimTopics = Array.from({ length: 16 }, (_, i) => i); - await expect(trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(claimIssuerContract.address, claimTopics)).to.be.revertedWith( + await expect(trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(claimIssuerContract.target, claimTopics)).to.be.revertedWith( 'cannot have more than 15 claim topics', ); }); @@ -228,7 +228,7 @@ describe('TrustedIssuersRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect(trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(claimIssuerContract.address, [])).to.be.revertedWith( + await expect(trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(claimIssuerContract.target, [])).to.be.revertedWith( 'claim topics cannot be empty', ); }); @@ -241,15 +241,15 @@ describe('TrustedIssuersRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - const claimTopics = await trustedIssuersRegistry.getTrustedIssuerClaimTopics(claimIssuerContract.address); + const claimTopics = await trustedIssuersRegistry.getTrustedIssuerClaimTopics(claimIssuerContract.target); - const tx = await trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(claimIssuerContract.address, [66, 100]); - await expect(tx).to.emit(trustedIssuersRegistry, 'ClaimTopicsUpdated').withArgs(claimIssuerContract.address, [66, 100]); + const tx = await trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(claimIssuerContract.target, [66, 100]); + await expect(tx).to.emit(trustedIssuersRegistry, 'ClaimTopicsUpdated').withArgs(claimIssuerContract.target, [66, 100]); - await expect(trustedIssuersRegistry.hasClaimTopic(claimIssuerContract.address, 66)).to.eventually.be.true; - await expect(trustedIssuersRegistry.hasClaimTopic(claimIssuerContract.address, 100)).to.eventually.be.true; - await expect(trustedIssuersRegistry.hasClaimTopic(claimIssuerContract.address, claimTopics[0])).to.eventually.be.false; - await expect(trustedIssuersRegistry.getTrustedIssuerClaimTopics(claimIssuerContract.address)).to.eventually.deep.eq([66, 100]); + await expect(trustedIssuersRegistry.hasClaimTopic(claimIssuerContract.target, 66)).to.eventually.be.true; + await expect(trustedIssuersRegistry.hasClaimTopic(claimIssuerContract.target, 100)).to.eventually.be.true; + await expect(trustedIssuersRegistry.hasClaimTopic(claimIssuerContract.target, claimTopics[0])).to.eventually.be.false; + await expect(trustedIssuersRegistry.getTrustedIssuerClaimTopics(claimIssuerContract.target)).to.eventually.deep.eq([66, 100]); }); }); }); diff --git a/test/token/token-information.test.ts b/test/token/token-information.test.ts index c097bb9c..14ab953e 100644 --- a/test/token/token-information.test.ts +++ b/test/token/token-information.test.ts @@ -79,7 +79,7 @@ describe('Token - Information', () => { suite: { token }, accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(anotherWallet).setOnchainID(ethers.constants.AddressZero)).to.be.revertedWith('Ownable: caller is not the owner'); + await expect(token.connect(anotherWallet).setOnchainID(ethers.ZeroAddress)).to.be.revertedWith('Ownable: caller is not the owner'); }); }); @@ -88,11 +88,11 @@ describe('Token - Information', () => { const { suite: { token }, } = await loadFixture(deployFullSuiteFixture); - const tx = await token.setOnchainID(ethers.constants.AddressZero); + const tx = await token.setOnchainID(ethers.ZeroAddress); await expect(tx) .to.emit(token, 'UpdatedTokenInformation') - .withArgs(await token.name(), await token.symbol(), await token.decimals(), await token.version(), ethers.constants.AddressZero); - expect(await token.onchainID()).to.equal(ethers.constants.AddressZero); + .withArgs(await token.name(), await token.symbol(), await token.decimals(), await token.version(), ethers.ZeroAddress); + expect(await token.onchainID()).to.equal(ethers.ZeroAddress); }); }); }); @@ -104,9 +104,7 @@ describe('Token - Information', () => { suite: { token }, accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(anotherWallet).setIdentityRegistry(ethers.constants.AddressZero)).to.be.revertedWith( - 'Ownable: caller is not the owner', - ); + await expect(token.connect(anotherWallet).setIdentityRegistry(ethers.ZeroAddress)).to.be.revertedWith('Ownable: caller is not the owner'); }); }); }); @@ -118,7 +116,7 @@ describe('Token - Information', () => { accounts: { aliceWallet, bobWallet }, } = await loadFixture(deployFullSuiteFixture); - const balance = await token.balanceOf(aliceWallet.address).then(async (b) => b.add(await token.balanceOf(bobWallet.address))); + const balance = await token.balanceOf(aliceWallet.address).then(async (b) => b + (await token.balanceOf(bobWallet.address))); expect(await token.totalSupply()).to.equal(balance); }); }); @@ -130,7 +128,7 @@ describe('Token - Information', () => { suite: { token }, accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(anotherWallet).setCompliance(ethers.constants.AddressZero)).to.be.revertedWith('Ownable: caller is not the owner'); + await expect(token.connect(anotherWallet).setCompliance(ethers.ZeroAddress)).to.be.revertedWith('Ownable: caller is not the owner'); }); }); }); @@ -140,8 +138,8 @@ describe('Token - Information', () => { const { suite: { token, compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await token.setCompliance(compliance.address); - expect(await token.compliance()).to.equal(compliance.address); + await token.setCompliance(compliance.target); + expect(await token.compliance()).to.equal(compliance.target); }); }); diff --git a/test/token/token-recovery.test.ts b/test/token/token-recovery.test.ts index 94767d14..c58480e7 100644 --- a/test/token/token-recovery.test.ts +++ b/test/token/token-recovery.test.ts @@ -15,9 +15,9 @@ describe('Token - Recovery', () => { await bobIdentity .connect(bobWallet) - .addKey(ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['address'], [anotherWallet.address])), 1, 1); + .addKey(ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address'], [anotherWallet.address])), 1, 1); - await expect(token.connect(anotherWallet).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.address)).to.be.revertedWith( + await expect(token.connect(anotherWallet).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target)).to.be.revertedWith( 'AgentRole: caller does not have the Agent role', ); }); @@ -34,7 +34,7 @@ describe('Token - Recovery', () => { await token.connect(bobWallet).transfer(aliceWallet.address, await token.balanceOf(bobWallet.address)); - await expect(token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.address)).to.be.revertedWith( + await expect(token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target)).to.be.revertedWith( 'no tokens to recover', ); }); @@ -48,7 +48,7 @@ describe('Token - Recovery', () => { identities: { bobIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.address)).to.be.revertedWith( + await expect(token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target)).to.be.revertedWith( 'Recovery not possible', ); }); @@ -64,13 +64,13 @@ describe('Token - Recovery', () => { await bobIdentity .connect(bobWallet) - .addKey(ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['address'], [anotherWallet.address])), 1, 1); + .addKey(ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address'], [anotherWallet.address])), 1, 1); await token.connect(tokenAgent).setAddressFrozen(bobWallet.address, true); - const tx = await token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.address); + const tx = await token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target); await expect(token.isFrozen(anotherWallet.address)).to.be.eventually.true; - await expect(tx).to.emit(token, 'RecoverySuccess').withArgs(bobWallet.address, anotherWallet.address, bobIdentity.address); + await expect(tx).to.emit(token, 'RecoverySuccess').withArgs(bobWallet.address, anotherWallet.address, bobIdentity.target); await expect(tx).to.emit(token, 'AddressFrozen').withArgs(anotherWallet.address, true, tokenAgent.address); }); }); @@ -85,13 +85,13 @@ describe('Token - Recovery', () => { await bobIdentity .connect(bobWallet) - .addKey(ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['address'], [anotherWallet.address])), 1, 1); + .addKey(ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address'], [anotherWallet.address])), 1, 1); await token.connect(tokenAgent).freezePartialTokens(bobWallet.address, 50); - const tx = await token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.address); + const tx = await token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target); await expect(token.getFrozenTokens(anotherWallet.address)).to.be.eventually.eq(50); - await expect(tx).to.emit(token, 'RecoverySuccess').withArgs(bobWallet.address, anotherWallet.address, bobIdentity.address); + await expect(tx).to.emit(token, 'RecoverySuccess').withArgs(bobWallet.address, anotherWallet.address, bobIdentity.target); await expect(tx).to.emit(token, 'TokensFrozen').withArgs(anotherWallet.address, 50); }); }); diff --git a/test/token/token-transfer.test.ts b/test/token/token-transfer.test.ts index 0b4d1490..e9150904 100644 --- a/test/token/token-transfer.test.ts +++ b/test/token/token-transfer.test.ts @@ -99,7 +99,7 @@ describe('Token - Transfers', () => { const balance = await token.balanceOf(aliceWallet.address); - await expect(token.connect(aliceWallet).transfer(bobWallet.address, balance.add(1000))).to.be.revertedWith('Insufficient Balance'); + await expect(token.connect(aliceWallet).transfer(bobWallet.address, balance + 1000n)).to.be.revertedWith('Insufficient Balance'); }); }); @@ -111,7 +111,7 @@ describe('Token - Transfers', () => { } = await loadFixture(deployFullSuiteFixture); const balance = await token.balanceOf(aliceWallet.address); - await token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, balance.sub(100)); + await token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, balance - 100n); await expect(token.connect(aliceWallet).transfer(bobWallet.address, balance)).to.be.revertedWith('Insufficient Balance'); }); @@ -136,8 +136,8 @@ describe('Token - Transfers', () => { } = await loadFixture(deploySuiteWithModularCompliancesFixture); const complianceModuleA = await ethers.deployContract('CountryAllowModule'); - await compliance.addModule(complianceModuleA.address); - await token.setCompliance(compliance.address); + await compliance.addModule(complianceModuleA.target); + await token.setCompliance(compliance.target); await expect(token.connect(aliceWallet).transfer(bobWallet.address, 100)).to.be.revertedWith('Transfer not possible'); }); @@ -218,7 +218,7 @@ describe('Token - Transfers', () => { const balance = await token.balanceOf(aliceWallet.address); - await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, balance.add(1000))).to.be.revertedWith( + await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, balance + 1000n)).to.be.revertedWith( 'Insufficient Balance', ); }); @@ -232,7 +232,7 @@ describe('Token - Transfers', () => { } = await loadFixture(deployFullSuiteFixture); const balance = await token.balanceOf(aliceWallet.address); - await token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, balance.sub(100)); + await token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, balance - 100n); await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, balance)).to.be.revertedWith( 'Insufficient Balance', @@ -261,8 +261,8 @@ describe('Token - Transfers', () => { } = await loadFixture(deploySuiteWithModularCompliancesFixture); const complianceModuleA = await ethers.deployContract('CountryAllowModule'); - await compliance.addModule(complianceModuleA.address); - await token.setCompliance(compliance.address); + await compliance.addModule(complianceModuleA.target); + await token.setCompliance(compliance.target); await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWith( 'Transfer not possible', @@ -310,7 +310,7 @@ describe('Token - Transfers', () => { const balance = await token.balanceOf(aliceWallet.address); - await expect(token.connect(tokenAgent).forcedTransfer(aliceWallet.address, bobWallet.address, balance.add(1000))).to.be.revertedWith( + await expect(token.connect(tokenAgent).forcedTransfer(aliceWallet.address, bobWallet.address, balance + 1000n)).to.be.revertedWith( 'sender balance too low', ); }); @@ -337,8 +337,8 @@ describe('Token - Transfers', () => { } = await loadFixture(deploySuiteWithModularCompliancesFixture); const complianceModuleA = await ethers.deployContract('CountryAllowModule'); - await compliance.addModule(complianceModuleA.address); - await token.setCompliance(compliance.address); + await compliance.addModule(complianceModuleA.target); + await token.setCompliance(compliance.target); const tx = await token.connect(tokenAgent).forcedTransfer(aliceWallet.address, bobWallet.address, 100); await expect(tx).to.emit(token, 'Transfer').withArgs(aliceWallet.address, bobWallet.address, 100); @@ -353,11 +353,15 @@ describe('Token - Transfers', () => { } = await loadFixture(deployFullSuiteFixture); const balance = await token.balanceOf(aliceWallet.address); - await token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, balance.sub(100)); - - const tx = await token.connect(tokenAgent).forcedTransfer(aliceWallet.address, bobWallet.address, balance.sub(50)); - await expect(tx).to.emit(token, 'Transfer').withArgs(aliceWallet.address, bobWallet.address, balance.sub(50)); - await expect(tx).to.emit(token, 'TokensUnfrozen').withArgs(aliceWallet.address, balance.sub(150)); + await token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, balance - 100n); + + const tx = await token.connect(tokenAgent).forcedTransfer(aliceWallet.address, bobWallet.address, balance - 50n); + await expect(tx) + .to.emit(token, 'Transfer') + .withArgs(aliceWallet.address, bobWallet.address, balance - 50n); + await expect(tx) + .to.emit(token, 'TokensUnfrozen') + .withArgs(aliceWallet.address, balance - 150n); await expect(token.getFrozenTokens(aliceWallet.address)).to.be.eventually.equal(50); }); }); @@ -394,8 +398,8 @@ describe('Token - Transfers', () => { } = await loadFixture(deploySuiteWithModularCompliancesFixture); const complianceModuleA = await ethers.deployContract('CountryAllowModule'); - await compliance.addModule(complianceModuleA.address); - await token.setCompliance(compliance.address); + await compliance.addModule(complianceModuleA.target); + await token.setCompliance(compliance.target); await expect(token.connect(tokenAgent).mint(aliceWallet.address, 100)).to.be.revertedWith('Compliance not followed'); }); @@ -423,7 +427,7 @@ describe('Token - Transfers', () => { const balance = await token.balanceOf(aliceWallet.address); - await expect(token.connect(tokenAgent).burn(aliceWallet.address, balance.add(1000))).to.be.revertedWith('cannot burn more than balance'); + await expect(token.connect(tokenAgent).burn(aliceWallet.address, balance + 1000n)).to.be.revertedWith('cannot burn more than balance'); }); }); @@ -435,11 +439,15 @@ describe('Token - Transfers', () => { } = await loadFixture(deployFullSuiteFixture); const balance = await token.balanceOf(aliceWallet.address); - await token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, balance.sub(100)); - - const tx = await token.connect(tokenAgent).burn(aliceWallet.address, balance.sub(50)); - await expect(tx).to.emit(token, 'Transfer').withArgs(aliceWallet.address, ethers.constants.AddressZero, balance.sub(50)); - await expect(tx).to.emit(token, 'TokensUnfrozen').withArgs(aliceWallet.address, balance.sub(150)); + await token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, balance - 100n); + + const tx = await token.connect(tokenAgent).burn(aliceWallet.address, balance - 50n); + await expect(tx) + .to.emit(token, 'Transfer') + .withArgs(aliceWallet.address, ethers.ZeroAddress, balance - 50n); + await expect(tx) + .to.emit(token, 'TokensUnfrozen') + .withArgs(aliceWallet.address, balance - 150n); await expect(token.getFrozenTokens(aliceWallet.address)).to.be.eventually.equal(50); }); }); From 0fb608ad592e7e62bf74051897f8635ea8075792 Mon Sep 17 00:00:00 2001 From: aliarbak Date: Thu, 20 Jun 2024 13:36:15 +0300 Subject: [PATCH 17/55] Proxify DvA manager and implement token freeze logic (#204) * Proxify DvA manager and implement token freeze logic * Fix lint * Add initializer tests * Upgrade package version --- CHANGELOG.md | 7 ++ contracts/DVA/DVATransferManager.sol | 33 +++--- contracts/DVA/DVATransferManagerProxy.sol | 70 +++++++++++++ contracts/DVA/IDVATransferManager.sol | 4 +- index.d.ts | 4 +- index.js | 2 + package.json | 2 +- test/dva.test.ts | 122 ++++++++++++++-------- 8 files changed, 185 insertions(+), 59 deletions(-) create mode 100644 contracts/DVA/DVATransferManagerProxy.sol diff --git a/CHANGELOG.md b/CHANGELOG.md index 074ef788..78384da2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Change Log All notable changes to this project will be documented in this file. +## [4.1.5] + +### Update +- DvA Transfer Manager contract proxified +- The DvA manager contract freezes the tokens to be transferred instead of being a vault (so it must be a token agent) +- Only the token owner (rather than agents) can call setApprovalCriteria, as it is part of the main token settings. +- ## [4.1.4] ### Added diff --git a/contracts/DVA/DVATransferManager.sol b/contracts/DVA/DVATransferManager.sol index 0cf98a88..9d7ae290 100644 --- a/contracts/DVA/DVATransferManager.sol +++ b/contracts/DVA/DVATransferManager.sol @@ -65,8 +65,11 @@ pragma solidity 0.8.17; import "../roles/AgentRole.sol"; import "../token/IToken.sol"; import "./IDVATransferManager.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -contract DVATransferManager is IDVATransferManager { +contract DVATransferManager is IDVATransferManager, Initializable, OwnableUpgradeable, UUPSUpgradeable { // Mapping for token approval criteria mapping(address => ApprovalCriteria) private _approvalCriteria; @@ -77,7 +80,8 @@ contract DVATransferManager is IDVATransferManager { // nonce of the transaction allowing the creation of unique transferID uint256 private _txNonce; - constructor(){ + function initialize() external initializer { + __Ownable_init(); _txNonce = 0; } @@ -91,12 +95,12 @@ contract DVATransferManager is IDVATransferManager { bool sequentialApproval, address[] memory additionalApprovers ) external { - if (!AgentRole(tokenAddress).isAgent(msg.sender)) { - revert OnlyTokenAgentCanCall(tokenAddress); + if (AgentRole(tokenAddress).owner() != msg.sender) { + revert OnlyTokenOwnerCanCall(tokenAddress); } - if (!IToken(tokenAddress).identityRegistry().isVerified(address(this))) { - revert DVAManagerIsNotVerifiedForTheToken(tokenAddress); + if (!AgentRole(tokenAddress).isAgent(address(this))) { + revert DVAManagerIsNotAnAgentOfTheToken(tokenAddress); } bytes32 hash = keccak256( @@ -139,7 +143,7 @@ contract DVATransferManager is IDVATransferManager { revert RecipientIsNotVerified(tokenAddress, recipient); } - token.transferFrom(msg.sender, address(this), amount); + token.freezePartialTokens(msg.sender, amount); uint256 nonce = _txNonce++; bytes32 transferID = calculateTransferID(nonce, msg.sender, recipient, amount); @@ -214,7 +218,7 @@ contract DVATransferManager is IDVATransferManager { } transfer.status = TransferStatus.CANCELLED; - _transferTokensTo(transfer, transfer.sender); + IToken(transfer.tokenAddress).unfreezePartialTokens(transfer.sender, transfer.amount); emit TransferCancelled(transferID); } @@ -250,7 +254,7 @@ contract DVATransferManager is IDVATransferManager { } transfer.status = TransferStatus.REJECTED; - _transferTokensTo(transfer, transfer.sender); + IToken(transfer.tokenAddress).unfreezePartialTokens(transfer.sender, transfer.amount); emit TransferRejected(transferID, msg.sender); } @@ -371,7 +375,9 @@ contract DVATransferManager is IDVATransferManager { function _completeTransfer(bytes32 transferID, Transfer storage transfer) internal { transfer.status = TransferStatus.COMPLETED; - _transferTokensTo(transfer, transfer.recipient); + IToken token = IToken(transfer.tokenAddress); + token.unfreezePartialTokens(transfer.sender, transfer.amount); + token.transferFrom(transfer.sender, transfer.recipient, transfer.amount); emit TransferCompleted( transferID, transfer.tokenAddress, @@ -412,10 +418,6 @@ contract DVATransferManager is IDVATransferManager { } } - function _transferTokensTo(Transfer memory transfer, address to) internal { - IToken(transfer.tokenAddress).transfer(to, transfer.amount); - } - function _canApprove(Transfer memory transfer, Approver memory approver, address caller) internal view returns (bool) { return approver.wallet == caller || (approver.anyTokenAgent && approver.wallet == address(0) && AgentRole(transfer.tokenAddress).isAgent(caller)); @@ -434,6 +436,9 @@ contract DVATransferManager is IDVATransferManager { return transfer; } + // solhint-disable-next-line no-empty-blocks + function _authorizeUpgrade(address /*newImplementation*/) internal view override virtual onlyOwner { } + function _generateTransferSignatureHash(bytes32 transferID) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", transferID)); } diff --git a/contracts/DVA/DVATransferManagerProxy.sol b/contracts/DVA/DVATransferManagerProxy.sol new file mode 100644 index 00000000..ab76c0ca --- /dev/null +++ b/contracts/DVA/DVATransferManagerProxy.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: GPL-3.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2023, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +pragma solidity 0.8.17; + +import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + +contract DVATransferManagerProxy is ERC1967Proxy { + // solhint-disable-next-line no-empty-blocks + constructor(address implementation, bytes memory _data) ERC1967Proxy(implementation, _data) { } +} \ No newline at end of file diff --git a/contracts/DVA/IDVATransferManager.sol b/contracts/DVA/IDVATransferManager.sol index 4e9b26e8..6044dfb3 100644 --- a/contracts/DVA/IDVATransferManager.sol +++ b/contracts/DVA/IDVATransferManager.sol @@ -202,7 +202,7 @@ interface IDVATransferManager { bytes32 approvalCriteriaHash ); - error OnlyTokenAgentCanCall(address _tokenAddress); + error OnlyTokenOwnerCanCall(address _tokenAddress); error OnlyTransferSenderCanCall(bytes32 _transferID); @@ -210,7 +210,7 @@ interface IDVATransferManager { error RecipientIsNotVerified(address _tokenAddress, address _recipient); - error DVAManagerIsNotVerifiedForTheToken(address _tokenAddress); + error DVAManagerIsNotAnAgentOfTheToken(address _tokenAddress); error InvalidTransferID(bytes32 _transferID); diff --git a/index.d.ts b/index.d.ts index 5aa94f57..e7bdb048 100644 --- a/index.d.ts +++ b/index.d.ts @@ -6,7 +6,7 @@ type ContractJSON = { bytecode: string; deployedBytecode: string; linkReferences: any; -} +}; export namespace contracts { // Token @@ -52,6 +52,8 @@ export namespace contracts { export const DVDTransferManager: ContractJSON; // DVA export const DVATransferManager: ContractJSON; + + export const DVATransferManagerProxy: ContractJSON; // compliance export const MCStorage: ContractJSON; export const ModularCompliance: ContractJSON; diff --git a/index.js b/index.js index 5d2563ec..10792d99 100644 --- a/index.js +++ b/index.js @@ -52,6 +52,7 @@ const TREXGateway = require('./artifacts/contracts/factory/TREXGateway.sol/TREXG const DVDTransferManager = require('./artifacts/contracts/DVD/DVDTransferManager.sol/DVDTransferManager.json'); // DVA const DVATransferManager = require('./artifacts/contracts/DVA/DVATransferManager.sol/DVATransferManager.json'); +const DVATransferManagerProxy = require('./artifacts/contracts/DVA/DVATransferManagerProxy.sol/DVATransferManagerProxy.json'); const IDVATransferManager = require('./artifacts/contracts/DVA/IDVATransferManager.sol/IDVATransferManager.json'); // compliance const IModularCompliance = require('./artifacts/contracts/compliance/modular/IModularCompliance.sol/IModularCompliance.json'); @@ -118,6 +119,7 @@ module.exports = { DVDTransferManager, // DVA DVATransferManager, + DVATransferManagerProxy, // compliance MCStorage, ModularCompliance, diff --git a/package.json b/package.json index 0ef2ea2a..029ecf50 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tokenysolutions/t-rex", - "version": "4.1.4", + "version": "4.1.5", "description": "A fully compliant environment for the issuance and use of tokenized securities.", "main": "index.js", "directories": { diff --git a/test/dva.test.ts b/test/dva.test.ts index f21c20a0..56494c8e 100644 --- a/test/dva.test.ts +++ b/test/dva.test.ts @@ -1,6 +1,6 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { expect } from 'chai'; -import { ethers } from 'hardhat'; +import { ethers, upgrades } from 'hardhat'; import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; import { deployFullSuiteFixture } from './fixtures/deploy-full-suite.fixture'; @@ -9,8 +9,10 @@ describe('DVATransferManager', () => { async function deployFullSuiteWithTransferManager() { const context = await loadFixture(deployFullSuiteFixture); - const transferManager = await ethers.deployContract('DVATransferManager'); - + const implementation = await ethers.deployContract('DVATransferManager'); + const transferManagerProxy = await ethers.deployContract('DVATransferManagerProxy', [implementation.address, '0x']); + const transferManager = await ethers.getContractAt('DVATransferManager', transferManagerProxy.address); + await transferManager.initialize(); return { ...context, suite: { @@ -22,8 +24,7 @@ describe('DVATransferManager', () => { async function deployFullSuiteWithVerifiedTransferManager() { const context = await loadFixture(deployFullSuiteWithTransferManager); - const identity = await context.suite.identityRegistry.identity(context.accounts.aliceWallet.address); - await context.suite.identityRegistry.connect(context.accounts.tokenAgent).registerIdentity(context.suite.transferManager.address, identity, 0); + await context.suite.token.connect(context.accounts.deployer).addAgent(context.suite.transferManager.address); return context; } @@ -43,7 +44,7 @@ describe('DVATransferManager', () => { async function deployFullSuiteWithNonSequentialTransfer() { const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); await context.suite.transferManager - .connect(context.accounts.tokenAgent) + .connect(context.accounts.deployer) .setApprovalCriteria(context.suite.token.address, true, true, false, [context.accounts.charlieWallet.address]); await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.address, 100000); @@ -67,7 +68,7 @@ describe('DVATransferManager', () => { async function deployFullSuiteWithSequentialTransfer() { const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); await context.suite.transferManager - .connect(context.accounts.tokenAgent) + .connect(context.accounts.deployer) .setApprovalCriteria(context.suite.token.address, true, true, true, [context.accounts.charlieWallet.address]); await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.address, 100000); @@ -88,6 +89,27 @@ describe('DVATransferManager', () => { }; } + describe('.initialize', () => { + describe('when the contract is not initialized before', () => { + it('should initialize', async () => { + const context = await loadFixture(deployFullSuiteWithTransferManager); + + const implementation = await ethers.deployContract('DVATransferManager'); + const transferManagerProxy = await ethers.deployContract('DVATransferManagerProxy', [implementation.address, '0x']); + const transferManager = await ethers.getContractAt('DVATransferManager', transferManagerProxy.address); + await expect(transferManager.connect(context.accounts.deployer).initialize()).to.eventually.be.fulfilled; + await expect(transferManager.owner()).to.eventually.be.eq(context.accounts.deployer.address); + }); + }); + + describe('when the contract is already initialized', () => { + it('should revert', async () => { + const context = await loadFixture(deployFullSuiteWithTransferManager); + await expect(context.suite.transferManager.initialize()).to.eventually.be.rejectedWith('Initializable: contract is already initialized'); + }); + }); + }); + describe('.setApprovalCriteria', () => { describe('when sender is not a token agent', () => { it('should revert', async () => { @@ -97,34 +119,29 @@ describe('DVATransferManager', () => { context.suite.transferManager .connect(context.accounts.anotherWallet) .setApprovalCriteria(context.suite.token.address, false, true, true, []), - ).to.be.revertedWithCustomError(context.suite.transferManager, `OnlyTokenAgentCanCall`); + ).to.be.revertedWithCustomError(context.suite.transferManager, `OnlyTokenOwnerCanCall`); }); }); describe('when sender is a token agent', () => { - describe('when DVA Manager is not verified for the token', () => { + describe('when DVA Manager is not an agent of the token', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteWithTransferManager); await expect( - context.suite.transferManager - .connect(context.accounts.tokenAgent) - .setApprovalCriteria(context.suite.token.address, false, true, true, []), - ).to.be.revertedWithCustomError(context.suite.transferManager, `DVAManagerIsNotVerifiedForTheToken`); + context.suite.transferManager.connect(context.accounts.deployer).setApprovalCriteria(context.suite.token.address, false, true, true, []), + ).to.be.revertedWithCustomError(context.suite.transferManager, `DVAManagerIsNotAnAgentOfTheToken`); }); }); - describe('when DVA Manager is verified for the token', () => { + describe('when DVA Manager is an agent of the token', () => { describe('when token is not already registered', () => { it('should modify approval criteria', async () => { const context = await loadFixture(deployFullSuiteWithTransferManager); - const identity = await context.suite.identityRegistry.identity(context.accounts.aliceWallet.address); - await context.suite.identityRegistry - .connect(context.accounts.tokenAgent) - .registerIdentity(context.suite.transferManager.address, identity, 0); + await context.suite.token.connect(context.accounts.deployer).addAgent(context.suite.transferManager.address); const tx = context.suite.transferManager - .connect(context.accounts.tokenAgent) + .connect(context.accounts.deployer) .setApprovalCriteria(context.suite.token.address, true, true, true, [ context.accounts.anotherWallet.address, context.accounts.bobWallet.address, @@ -152,13 +169,10 @@ describe('DVATransferManager', () => { describe('when token is already registered', () => { it('should modify approval criteria', async () => { const context = await loadFixture(deployFullSuiteWithTransferManager); - const identity = await context.suite.identityRegistry.identity(context.accounts.aliceWallet.address); - await context.suite.identityRegistry - .connect(context.accounts.tokenAgent) - .registerIdentity(context.suite.transferManager.address, identity, 0); + await context.suite.token.connect(context.accounts.deployer).addAgent(context.suite.transferManager.address); await context.suite.transferManager - .connect(context.accounts.tokenAgent) + .connect(context.accounts.deployer) .setApprovalCriteria(context.suite.token.address, true, true, true, [ context.accounts.anotherWallet.address, context.accounts.bobWallet.address, @@ -167,7 +181,7 @@ describe('DVATransferManager', () => { const previousApprovalCriteria = await context.suite.transferManager.getApprovalCriteria(context.suite.token.address); const tx = await context.suite.transferManager - .connect(context.accounts.tokenAgent) + .connect(context.accounts.deployer) .setApprovalCriteria(context.suite.token.address, false, false, false, [context.accounts.davidWallet.address]); await tx.wait(); @@ -205,7 +219,7 @@ describe('DVATransferManager', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); await context.suite.transferManager - .connect(context.accounts.tokenAgent) + .connect(context.accounts.deployer) .setApprovalCriteria(context.suite.token.address, true, true, true, [ context.accounts.charlieWallet.address, context.accounts.anotherWallet.address, @@ -223,7 +237,7 @@ describe('DVATransferManager', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); await context.suite.transferManager - .connect(context.accounts.tokenAgent) + .connect(context.accounts.deployer) .setApprovalCriteria(context.suite.token.address, true, true, true, [ context.accounts.charlieWallet.address, context.accounts.anotherWallet.address, @@ -235,7 +249,7 @@ describe('DVATransferManager', () => { context.suite.transferManager .connect(context.accounts.aliceWallet) .initiateTransfer(context.suite.token.address, context.accounts.bobWallet.address, 100000), - ).to.be.revertedWith('Insufficient Balance'); + ).to.be.revertedWith('Amount exceeds available balance'); }); }); @@ -244,7 +258,7 @@ describe('DVATransferManager', () => { it('should initiate the transfer with recipient approver', async () => { const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); await context.suite.transferManager - .connect(context.accounts.tokenAgent) + .connect(context.accounts.deployer) .setApprovalCriteria(context.suite.token.address, true, false, true, []); await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.address, 100000); @@ -284,7 +298,7 @@ describe('DVATransferManager', () => { it('should initiate the transfer with token agent approver', async () => { const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); await context.suite.transferManager - .connect(context.accounts.tokenAgent) + .connect(context.accounts.deployer) .setApprovalCriteria(context.suite.token.address, false, true, true, []); await context.suite.token.connect(context.accounts.aliceWallet).approve(context.suite.transferManager.address, 100000); @@ -324,7 +338,7 @@ describe('DVATransferManager', () => { it('should initiate the transfer with token agent approver', async () => { const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); await context.suite.transferManager - .connect(context.accounts.tokenAgent) + .connect(context.accounts.deployer) .setApprovalCriteria(context.suite.token.address, false, false, true, [ context.accounts.charlieWallet.address, context.accounts.anotherWallet.address, @@ -368,7 +382,7 @@ describe('DVATransferManager', () => { it('should initiate the transfer with all approvers', async () => { const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); await context.suite.transferManager - .connect(context.accounts.tokenAgent) + .connect(context.accounts.deployer) .setApprovalCriteria(context.suite.token.address, true, true, true, [ context.accounts.charlieWallet.address, context.accounts.anotherWallet.address, @@ -412,10 +426,10 @@ describe('DVATransferManager', () => { expect(transfer.approvers[3]['approved']).to.be.false; const senderBalance = await context.suite.token.balanceOf(context.accounts.aliceWallet.address); - expect(senderBalance).to.be.eq(900); + expect(senderBalance).to.be.eq(1000); - const dvaBalance = await context.suite.token.balanceOf(context.suite.transferManager.address); - expect(dvaBalance).to.be.eq(100); + const frozenBalance = await context.suite.token.getFrozenTokens(context.accounts.aliceWallet.address); + expect(frozenBalance).to.be.eq(100); }); }); }); @@ -457,7 +471,7 @@ describe('DVATransferManager', () => { it('should reset approvers', async () => { const context = await loadFixture(deployFullSuiteWithNonSequentialTransfer); const modifyTx = await context.suite.transferManager - .connect(context.accounts.tokenAgent) + .connect(context.accounts.deployer) .setApprovalCriteria(context.suite.token.address, false, false, false, [context.accounts.davidWallet.address]); await modifyTx.wait(); @@ -478,7 +492,7 @@ describe('DVATransferManager', () => { it('should approve', async () => { const context = await loadFixture(deployFullSuiteWithNonSequentialTransfer); const modifyTx = await context.suite.transferManager - .connect(context.accounts.tokenAgent) + .connect(context.accounts.deployer) .setApprovalCriteria(context.suite.token.address, false, false, false, [context.accounts.davidWallet.address]); await modifyTx.wait(); @@ -651,7 +665,7 @@ describe('DVATransferManager', () => { it('should reset approvers', async () => { const context = await loadFixture(deployFullSuiteWithNonSequentialTransfer); const modifyTx = await context.suite.transferManager - .connect(context.accounts.tokenAgent) + .connect(context.accounts.deployer) .setApprovalCriteria(context.suite.token.address, false, false, false, [context.accounts.davidWallet.address]); await modifyTx.wait(); @@ -675,7 +689,7 @@ describe('DVATransferManager', () => { it('should approve', async () => { const context = await loadFixture(deployFullSuiteWithNonSequentialTransfer); const modifyTx = await context.suite.transferManager - .connect(context.accounts.tokenAgent) + .connect(context.accounts.deployer) .setApprovalCriteria(context.suite.token.address, false, false, false, [context.accounts.davidWallet.address]); await modifyTx.wait(); @@ -903,7 +917,7 @@ describe('DVATransferManager', () => { it('should reset approvers', async () => { const context = await loadFixture(deployFullSuiteWithNonSequentialTransfer); const modifyTx = await context.suite.transferManager - .connect(context.accounts.tokenAgent) + .connect(context.accounts.deployer) .setApprovalCriteria(context.suite.token.address, false, false, false, [context.accounts.davidWallet.address]); await modifyTx.wait(); @@ -924,7 +938,7 @@ describe('DVATransferManager', () => { it('should reject', async () => { const context = await loadFixture(deployFullSuiteWithNonSequentialTransfer); const modifyTx = await context.suite.transferManager - .connect(context.accounts.tokenAgent) + .connect(context.accounts.deployer) .setApprovalCriteria(context.suite.token.address, false, false, false, [context.accounts.davidWallet.address]); await modifyTx.wait(); @@ -947,6 +961,32 @@ describe('DVATransferManager', () => { }); }); + describe('.upgradeTo', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const context = await loadFixture(deployFullSuiteWithTransferManager); + await expect(context.suite.transferManager.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero)).to.revertedWith( + 'Ownable: caller is not the owner', + ); + }); + }); + + describe('when calling with owner account', () => { + it('should upgrade proxy', async () => { + // given + const context = await loadFixture(deployFullSuiteWithTransferManager); + const newImplementation = await ethers.deployContract('DVATransferManager'); + + // when + await context.suite.transferManager.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + + // then + const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.transferManager.address); + expect(implementationAddress).to.eq(newImplementation.address); + }); + }); + }); + describe('.getTransfer', () => { describe('when transfer does not exist', () => { it('should revert', async () => { From ab2ba7991bb2e28f21a7cfe8a71c99a3ab520e70 Mon Sep 17 00:00:00 2001 From: "ali.arbak" Date: Wed, 26 Jun 2024 15:39:16 +0300 Subject: [PATCH 18/55] =?UTF-8?q?=F0=9F=90=9B()=20Fix=20lint=20issues?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/compliances/module-conditional-transfer.test.ts | 6 +++--- test/compliances/module-exchange-monthly-limits.test.ts | 6 +++--- test/compliances/module-time-exchange-limits.test.ts | 6 +++--- test/compliances/module-time-transfer-limits.test.ts | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/test/compliances/module-conditional-transfer.test.ts b/test/compliances/module-conditional-transfer.test.ts index e4a6128b..275d9b42 100644 --- a/test/compliances/module-conditional-transfer.test.ts +++ b/test/compliances/module-conditional-transfer.test.ts @@ -96,9 +96,9 @@ describe('ConditionalTransferModule', () => { describe('when calling directly', () => { it('should revert', async () => { const context = await loadFixture(deployComplianceWithConditionalTransferModule); - await expect( - context.suite.conditionalTransferModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress), - ).to.revertedWith('Ownable: caller is not the owner'); + await expect(context.suite.conditionalTransferModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress)).to.revertedWith( + 'Ownable: caller is not the owner', + ); }); }); diff --git a/test/compliances/module-exchange-monthly-limits.test.ts b/test/compliances/module-exchange-monthly-limits.test.ts index ebaf75c3..f9388984 100644 --- a/test/compliances/module-exchange-monthly-limits.test.ts +++ b/test/compliances/module-exchange-monthly-limits.test.ts @@ -120,9 +120,9 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { describe('when calling directly', () => { it('should revert', async () => { const context = await loadFixture(deployExchangeMonthlyLimitsFixture); - await expect( - context.contracts.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress), - ).to.revertedWith('Ownable: caller is not the owner'); + await expect(context.contracts.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress)).to.revertedWith( + 'Ownable: caller is not the owner', + ); }); }); diff --git a/test/compliances/module-time-exchange-limits.test.ts b/test/compliances/module-time-exchange-limits.test.ts index 6f988d38..561b887c 100644 --- a/test/compliances/module-time-exchange-limits.test.ts +++ b/test/compliances/module-time-exchange-limits.test.ts @@ -106,9 +106,9 @@ describe('Compliance Module: TimeExchangeLimits', () => { describe('when calling directly', () => { it('should revert', async () => { const context = await loadFixture(deployTimeExchangeLimitsFixture); - await expect( - context.contracts.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress), - ).to.revertedWith('Ownable: caller is not the owner'); + await expect(context.contracts.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress)).to.revertedWith( + 'Ownable: caller is not the owner', + ); }); }); diff --git a/test/compliances/module-time-transfer-limits.test.ts b/test/compliances/module-time-transfer-limits.test.ts index ea8772d5..3506afac 100644 --- a/test/compliances/module-time-transfer-limits.test.ts +++ b/test/compliances/module-time-transfer-limits.test.ts @@ -106,9 +106,9 @@ describe('Compliance Module: TimeTransferLimits', () => { describe('when calling directly', () => { it('should revert', async () => { const context = await loadFixture(deployTimeTransferLimitsFixture); - await expect( - context.contracts.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress), - ).to.revertedWith('Ownable: caller is not the owner'); + await expect(context.contracts.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress)).to.revertedWith( + 'Ownable: caller is not the owner', + ); }); }); From 5ee976f7a537eef58b61a365080d8caedfb37905 Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Thu, 27 Jun 2024 14:06:43 +0200 Subject: [PATCH 19/55] =?UTF-8?q?=F0=9F=94=A7()=20TREX-122=20Update=20comp?= =?UTF-8?q?iler=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/DVA/DVATransferManager.sol | 2 +- contracts/DVA/DVATransferManagerProxy.sol | 2 +- contracts/DVA/IDVATransferManager.sol | 2 +- contracts/DVD/DVDTransferManager.sol | 2 +- contracts/_testContracts/MockContract.sol | 2 +- contracts/_testContracts/OIDImports.sol | 10 ---------- contracts/_testContracts/TestERC20.sol | 2 +- .../_testContracts/TestUpgradedCountryAllowModule.sol | 2 +- contracts/_testContracts/v_3_5_2/LegacyIA.sol | 2 +- contracts/_testContracts/v_3_5_2/LegacyProxy.sol | 2 +- .../_testContracts/v_3_5_2/LegacyToken_3_5_2.sol | 2 +- contracts/compliance/legacy/BasicCompliance.sol | 2 +- contracts/compliance/legacy/DefaultCompliance.sol | 2 +- contracts/compliance/legacy/ICompliance.sol | 2 +- .../compliance/legacy/features/ApproveTransfer.sol | 2 +- .../legacy/features/CountryRestrictions.sol | 2 +- .../legacy/features/CountryWhitelisting.sol | 2 +- .../compliance/legacy/features/DayMonthLimits.sol | 2 +- .../legacy/features/ExchangeMonthlyLimits.sol | 2 +- contracts/compliance/legacy/features/MaxBalance.sol | 2 +- contracts/compliance/legacy/features/SupplyLimit.sol | 2 +- .../compliance/legacy/test/ApproveTransferTest.sol | 2 +- .../legacy/test/CountryRestrictionsTest.sol | 2 +- .../legacy/test/CountryWhitelistingTest.sol | 2 +- .../compliance/legacy/test/DayMonthLimitsTest.sol | 2 +- .../legacy/test/ExchangeMonthlyLimitsTest.sol | 2 +- contracts/compliance/legacy/test/MaxBalanceTest.sol | 2 +- contracts/compliance/legacy/test/SupplyLimitTest.sol | 2 +- contracts/compliance/modular/IModularCompliance.sol | 2 +- contracts/compliance/modular/MCStorage.sol | 2 +- contracts/compliance/modular/ModularCompliance.sol | 2 +- .../compliance/modular/modules/AbstractModule.sol | 2 +- .../modular/modules/AbstractModuleUpgradeable.sol | 2 +- .../modular/modules/ConditionalTransferModule.sol | 2 +- .../compliance/modular/modules/CountryAllowModule.sol | 2 +- .../modular/modules/CountryRestrictModule.sol | 2 +- .../modular/modules/ExchangeMonthlyLimitsModule.sol | 2 +- contracts/compliance/modular/modules/IModule.sol | 2 +- .../compliance/modular/modules/MaxBalanceModule.sol | 2 +- contracts/compliance/modular/modules/ModuleProxy.sol | 2 +- .../compliance/modular/modules/SupplyLimitModule.sol | 2 +- .../modular/modules/TimeExchangeLimitsModule.sol | 2 +- .../modular/modules/TimeTransfersLimitsModule.sol | 2 +- .../compliance/modular/modules/TransferFeesModule.sol | 2 +- .../modular/modules/TransferRestrictModule.sol | 2 +- contracts/factory/ITREXFactory.sol | 2 +- contracts/factory/ITREXGateway.sol | 2 +- contracts/factory/TREXFactory.sol | 2 +- contracts/factory/TREXGateway.sol | 2 +- contracts/proxy/AbstractProxy.sol | 2 +- contracts/proxy/ClaimTopicsRegistryProxy.sol | 2 +- contracts/proxy/IdentityRegistryProxy.sol | 2 +- contracts/proxy/IdentityRegistryStorageProxy.sol | 2 +- contracts/proxy/ModularComplianceProxy.sol | 2 +- contracts/proxy/TokenProxy.sol | 2 +- contracts/proxy/TrustedIssuersRegistryProxy.sol | 2 +- contracts/proxy/authority/IAFactory.sol | 2 +- contracts/proxy/authority/IIAFactory.sol | 2 +- .../proxy/authority/ITREXImplementationAuthority.sol | 2 +- .../proxy/authority/TREXImplementationAuthority.sol | 2 +- contracts/proxy/interface/IProxy.sol | 2 +- .../registry/implementation/ClaimTopicsRegistry.sol | 2 +- .../registry/implementation/IdentityRegistry.sol | 2 +- .../implementation/IdentityRegistryStorage.sol | 2 +- .../implementation/TrustedIssuersRegistry.sol | 2 +- contracts/registry/interface/IClaimTopicsRegistry.sol | 2 +- contracts/registry/interface/IIdentityRegistry.sol | 2 +- .../registry/interface/IIdentityRegistryStorage.sol | 2 +- .../registry/interface/ITrustedIssuersRegistry.sol | 2 +- contracts/registry/storage/CTRStorage.sol | 2 +- contracts/registry/storage/IRSStorage.sol | 2 +- contracts/registry/storage/IRStorage.sol | 2 +- contracts/registry/storage/TIRStorage.sol | 2 +- contracts/roles/AgentRole.sol | 2 +- contracts/roles/AgentRoleUpgradeable.sol | 2 +- contracts/roles/Roles.sol | 2 +- contracts/roles/permissioning/agent/AgentManager.sol | 2 +- contracts/roles/permissioning/agent/AgentRoles.sol | 2 +- .../permissioning/agent/AgentRolesUpgradeable.sol | 2 +- contracts/roles/permissioning/owner/OwnerManager.sol | 2 +- contracts/roles/permissioning/owner/OwnerRoles.sol | 2 +- .../permissioning/owner/OwnerRolesUpgradeable.sol | 2 +- contracts/token/IToken.sol | 2 +- contracts/token/Token.sol | 2 +- contracts/token/TokenStorage.sol | 2 +- contracts/token/TokenStructs.sol | 2 +- hardhat.config.ts | 2 +- package-lock.json | 11 ++++++----- package.json | 2 +- 89 files changed, 93 insertions(+), 102 deletions(-) delete mode 100644 contracts/_testContracts/OIDImports.sol diff --git a/contracts/DVA/DVATransferManager.sol b/contracts/DVA/DVATransferManager.sol index 6d145900..d499cc0a 100644 --- a/contracts/DVA/DVATransferManager.sol +++ b/contracts/DVA/DVATransferManager.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../roles/AgentRole.sol"; import "../token/IToken.sol"; diff --git a/contracts/DVA/DVATransferManagerProxy.sol b/contracts/DVA/DVATransferManagerProxy.sol index ab76c0ca..2a441a9b 100644 --- a/contracts/DVA/DVATransferManagerProxy.sol +++ b/contracts/DVA/DVATransferManagerProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; diff --git a/contracts/DVA/IDVATransferManager.sol b/contracts/DVA/IDVATransferManager.sol index 125a3f30..5285ba38 100644 --- a/contracts/DVA/IDVATransferManager.sol +++ b/contracts/DVA/IDVATransferManager.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../roles/AgentRole.sol"; import "../token/IToken.sol"; diff --git a/contracts/DVD/DVDTransferManager.sol b/contracts/DVD/DVDTransferManager.sol index ff493e23..0cc5f657 100644 --- a/contracts/DVD/DVDTransferManager.sol +++ b/contracts/DVD/DVDTransferManager.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../roles/AgentRole.sol"; import "../token/IToken.sol"; diff --git a/contracts/_testContracts/MockContract.sol b/contracts/_testContracts/MockContract.sol index eaa50c41..1881e66f 100644 --- a/contracts/_testContracts/MockContract.sol +++ b/contracts/_testContracts/MockContract.sol @@ -1,4 +1,4 @@ -pragma solidity 0.8.17; +pragma solidity 0.8.26; contract MockContract { address _irRegistry; diff --git a/contracts/_testContracts/OIDImports.sol b/contracts/_testContracts/OIDImports.sol deleted file mode 100644 index f2e9b295..00000000 --- a/contracts/_testContracts/OIDImports.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.17; - -import "@onchain-id/solidity/contracts/ClaimIssuer.sol"; -import "@onchain-id/solidity/contracts/Identity.sol"; -import "@onchain-id/solidity/contracts/proxy/ImplementationAuthority.sol"; - -contract OIDImports { - -} diff --git a/contracts/_testContracts/TestERC20.sol b/contracts/_testContracts/TestERC20.sol index c8a28d7c..90ed59fe 100644 --- a/contracts/_testContracts/TestERC20.sol +++ b/contracts/_testContracts/TestERC20.sol @@ -58,7 +58,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/contracts/_testContracts/TestUpgradedCountryAllowModule.sol b/contracts/_testContracts/TestUpgradedCountryAllowModule.sol index 3a3316a7..76bb6fdb 100644 --- a/contracts/_testContracts/TestUpgradedCountryAllowModule.sol +++ b/contracts/_testContracts/TestUpgradedCountryAllowModule.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../compliance/modular/modules/CountryAllowModule.sol"; diff --git a/contracts/_testContracts/v_3_5_2/LegacyIA.sol b/contracts/_testContracts/v_3_5_2/LegacyIA.sol index 6a9c74ee..c362866a 100644 --- a/contracts/_testContracts/v_3_5_2/LegacyIA.sol +++ b/contracts/_testContracts/v_3_5_2/LegacyIA.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.17; +pragma solidity 0.8.26; abstract contract ContextLegacy { function _msgSender() internal view virtual returns (address) { diff --git a/contracts/_testContracts/v_3_5_2/LegacyProxy.sol b/contracts/_testContracts/v_3_5_2/LegacyProxy.sol index 2ed5fcbf..5e193918 100644 --- a/contracts/_testContracts/v_3_5_2/LegacyProxy.sol +++ b/contracts/_testContracts/v_3_5_2/LegacyProxy.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.17; +pragma solidity 0.8.26; interface IImplementationAuthorityLegacy { function getImplementation() external view returns (address); diff --git a/contracts/_testContracts/v_3_5_2/LegacyToken_3_5_2.sol b/contracts/_testContracts/v_3_5_2/LegacyToken_3_5_2.sol index 9cffad8c..dbc098fb 100644 --- a/contracts/_testContracts/v_3_5_2/LegacyToken_3_5_2.sol +++ b/contracts/_testContracts/v_3_5_2/LegacyToken_3_5_2.sol @@ -5,7 +5,7 @@ // File: @onchain-id/solidity/contracts/interface/IERC734Legacy.sol // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.17; +pragma solidity 0.8.26; /** * @dev interface of the ERC734 (Key Holder) standard as defined in the EIP. diff --git a/contracts/compliance/legacy/BasicCompliance.sol b/contracts/compliance/legacy/BasicCompliance.sol index ef54234f..09bcdb07 100644 --- a/contracts/compliance/legacy/BasicCompliance.sol +++ b/contracts/compliance/legacy/BasicCompliance.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../../roles/AgentRole.sol"; import "./ICompliance.sol"; diff --git a/contracts/compliance/legacy/DefaultCompliance.sol b/contracts/compliance/legacy/DefaultCompliance.sol index 5ab3a70d..b1ee3d68 100644 --- a/contracts/compliance/legacy/DefaultCompliance.sol +++ b/contracts/compliance/legacy/DefaultCompliance.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "./BasicCompliance.sol"; diff --git a/contracts/compliance/legacy/ICompliance.sol b/contracts/compliance/legacy/ICompliance.sol index cb99ae87..ddd68be4 100644 --- a/contracts/compliance/legacy/ICompliance.sol +++ b/contracts/compliance/legacy/ICompliance.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; interface ICompliance { /** diff --git a/contracts/compliance/legacy/features/ApproveTransfer.sol b/contracts/compliance/legacy/features/ApproveTransfer.sol index dbdf2f0d..bb1680ca 100644 --- a/contracts/compliance/legacy/features/ApproveTransfer.sol +++ b/contracts/compliance/legacy/features/ApproveTransfer.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../BasicCompliance.sol"; diff --git a/contracts/compliance/legacy/features/CountryRestrictions.sol b/contracts/compliance/legacy/features/CountryRestrictions.sol index 368f9356..36101b66 100644 --- a/contracts/compliance/legacy/features/CountryRestrictions.sol +++ b/contracts/compliance/legacy/features/CountryRestrictions.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../BasicCompliance.sol"; diff --git a/contracts/compliance/legacy/features/CountryWhitelisting.sol b/contracts/compliance/legacy/features/CountryWhitelisting.sol index 56e67889..473952df 100644 --- a/contracts/compliance/legacy/features/CountryWhitelisting.sol +++ b/contracts/compliance/legacy/features/CountryWhitelisting.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../BasicCompliance.sol"; diff --git a/contracts/compliance/legacy/features/DayMonthLimits.sol b/contracts/compliance/legacy/features/DayMonthLimits.sol index 78264e94..67f2566d 100644 --- a/contracts/compliance/legacy/features/DayMonthLimits.sol +++ b/contracts/compliance/legacy/features/DayMonthLimits.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../BasicCompliance.sol"; diff --git a/contracts/compliance/legacy/features/ExchangeMonthlyLimits.sol b/contracts/compliance/legacy/features/ExchangeMonthlyLimits.sol index 36bce9bb..77653c12 100644 --- a/contracts/compliance/legacy/features/ExchangeMonthlyLimits.sol +++ b/contracts/compliance/legacy/features/ExchangeMonthlyLimits.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../BasicCompliance.sol"; diff --git a/contracts/compliance/legacy/features/MaxBalance.sol b/contracts/compliance/legacy/features/MaxBalance.sol index 35f54b35..40e229a3 100644 --- a/contracts/compliance/legacy/features/MaxBalance.sol +++ b/contracts/compliance/legacy/features/MaxBalance.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../BasicCompliance.sol"; diff --git a/contracts/compliance/legacy/features/SupplyLimit.sol b/contracts/compliance/legacy/features/SupplyLimit.sol index e815fef6..8377ebab 100644 --- a/contracts/compliance/legacy/features/SupplyLimit.sol +++ b/contracts/compliance/legacy/features/SupplyLimit.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../BasicCompliance.sol"; diff --git a/contracts/compliance/legacy/test/ApproveTransferTest.sol b/contracts/compliance/legacy/test/ApproveTransferTest.sol index 26912450..4b39d26b 100644 --- a/contracts/compliance/legacy/test/ApproveTransferTest.sol +++ b/contracts/compliance/legacy/test/ApproveTransferTest.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../features/ApproveTransfer.sol"; diff --git a/contracts/compliance/legacy/test/CountryRestrictionsTest.sol b/contracts/compliance/legacy/test/CountryRestrictionsTest.sol index 68e3daf0..1355cc9e 100644 --- a/contracts/compliance/legacy/test/CountryRestrictionsTest.sol +++ b/contracts/compliance/legacy/test/CountryRestrictionsTest.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../features/CountryRestrictions.sol"; diff --git a/contracts/compliance/legacy/test/CountryWhitelistingTest.sol b/contracts/compliance/legacy/test/CountryWhitelistingTest.sol index 13653942..58d5b334 100644 --- a/contracts/compliance/legacy/test/CountryWhitelistingTest.sol +++ b/contracts/compliance/legacy/test/CountryWhitelistingTest.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../features/CountryWhitelisting.sol"; diff --git a/contracts/compliance/legacy/test/DayMonthLimitsTest.sol b/contracts/compliance/legacy/test/DayMonthLimitsTest.sol index 08f8a0b6..7a162ae0 100644 --- a/contracts/compliance/legacy/test/DayMonthLimitsTest.sol +++ b/contracts/compliance/legacy/test/DayMonthLimitsTest.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../features/DayMonthLimits.sol"; diff --git a/contracts/compliance/legacy/test/ExchangeMonthlyLimitsTest.sol b/contracts/compliance/legacy/test/ExchangeMonthlyLimitsTest.sol index e6699cda..992a69be 100644 --- a/contracts/compliance/legacy/test/ExchangeMonthlyLimitsTest.sol +++ b/contracts/compliance/legacy/test/ExchangeMonthlyLimitsTest.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../features/ExchangeMonthlyLimits.sol"; diff --git a/contracts/compliance/legacy/test/MaxBalanceTest.sol b/contracts/compliance/legacy/test/MaxBalanceTest.sol index 3d1b6516..e5967fb7 100644 --- a/contracts/compliance/legacy/test/MaxBalanceTest.sol +++ b/contracts/compliance/legacy/test/MaxBalanceTest.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../features/MaxBalance.sol"; diff --git a/contracts/compliance/legacy/test/SupplyLimitTest.sol b/contracts/compliance/legacy/test/SupplyLimitTest.sol index ef63372e..322a3272 100644 --- a/contracts/compliance/legacy/test/SupplyLimitTest.sol +++ b/contracts/compliance/legacy/test/SupplyLimitTest.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../features/SupplyLimit.sol"; diff --git a/contracts/compliance/modular/IModularCompliance.sol b/contracts/compliance/modular/IModularCompliance.sol index bc5769ef..91041382 100644 --- a/contracts/compliance/modular/IModularCompliance.sol +++ b/contracts/compliance/modular/IModularCompliance.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; interface IModularCompliance { diff --git a/contracts/compliance/modular/MCStorage.sol b/contracts/compliance/modular/MCStorage.sol index df160809..8337f04b 100644 --- a/contracts/compliance/modular/MCStorage.sol +++ b/contracts/compliance/modular/MCStorage.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; contract MCStorage { /// token linked to the compliance contract diff --git a/contracts/compliance/modular/ModularCompliance.sol b/contracts/compliance/modular/ModularCompliance.sol index 7dcca9ae..e9aac245 100644 --- a/contracts/compliance/modular/ModularCompliance.sol +++ b/contracts/compliance/modular/ModularCompliance.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/AbstractModule.sol b/contracts/compliance/modular/modules/AbstractModule.sol index f489062b..a67fc0e2 100644 --- a/contracts/compliance/modular/modules/AbstractModule.sol +++ b/contracts/compliance/modular/modules/AbstractModule.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "./IModule.sol"; diff --git a/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol index b142f92e..e4fb90a9 100644 --- a/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol +++ b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; diff --git a/contracts/compliance/modular/modules/ConditionalTransferModule.sol b/contracts/compliance/modular/modules/ConditionalTransferModule.sol index 803dbe07..9ceb3752 100644 --- a/contracts/compliance/modular/modules/ConditionalTransferModule.sol +++ b/contracts/compliance/modular/modules/ConditionalTransferModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/CountryAllowModule.sol b/contracts/compliance/modular/modules/CountryAllowModule.sol index 29446e26..64cc31d4 100644 --- a/contracts/compliance/modular/modules/CountryAllowModule.sol +++ b/contracts/compliance/modular/modules/CountryAllowModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/CountryRestrictModule.sol b/contracts/compliance/modular/modules/CountryRestrictModule.sol index edb789c4..a0ed62b7 100644 --- a/contracts/compliance/modular/modules/CountryRestrictModule.sol +++ b/contracts/compliance/modular/modules/CountryRestrictModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol b/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol index ebd4f273..ae7c53d7 100644 --- a/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol +++ b/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/IModule.sol b/contracts/compliance/modular/modules/IModule.sol index 83cac328..ee99de7f 100644 --- a/contracts/compliance/modular/modules/IModule.sol +++ b/contracts/compliance/modular/modules/IModule.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; interface IModule { /// events diff --git a/contracts/compliance/modular/modules/MaxBalanceModule.sol b/contracts/compliance/modular/modules/MaxBalanceModule.sol index fc5616a2..bee3a45a 100644 --- a/contracts/compliance/modular/modules/MaxBalanceModule.sol +++ b/contracts/compliance/modular/modules/MaxBalanceModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../IModularCompliance.sol"; diff --git a/contracts/compliance/modular/modules/ModuleProxy.sol b/contracts/compliance/modular/modules/ModuleProxy.sol index 32d921a4..cd8dfe9b 100644 --- a/contracts/compliance/modular/modules/ModuleProxy.sol +++ b/contracts/compliance/modular/modules/ModuleProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; diff --git a/contracts/compliance/modular/modules/SupplyLimitModule.sol b/contracts/compliance/modular/modules/SupplyLimitModule.sol index 1b4e83cc..c795820e 100644 --- a/contracts/compliance/modular/modules/SupplyLimitModule.sol +++ b/contracts/compliance/modular/modules/SupplyLimitModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity ^0.8.17; +pragma solidity ^0.8.26; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol b/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol index a591961b..d3db9f4b 100644 --- a/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol +++ b/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol b/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol index 18ef472e..5fec8323 100644 --- a/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol +++ b/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/TransferFeesModule.sol b/contracts/compliance/modular/modules/TransferFeesModule.sol index b1584ade..3632d1df 100644 --- a/contracts/compliance/modular/modules/TransferFeesModule.sol +++ b/contracts/compliance/modular/modules/TransferFeesModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/TransferRestrictModule.sol b/contracts/compliance/modular/modules/TransferRestrictModule.sol index 038c1137..0f7c2862 100644 --- a/contracts/compliance/modular/modules/TransferRestrictModule.sol +++ b/contracts/compliance/modular/modules/TransferRestrictModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity ^0.8.17; +pragma solidity ^0.8.26; import "./AbstractModuleUpgradeable.sol"; diff --git a/contracts/factory/ITREXFactory.sol b/contracts/factory/ITREXFactory.sol index 2064985b..deed9662 100644 --- a/contracts/factory/ITREXFactory.sol +++ b/contracts/factory/ITREXFactory.sol @@ -59,7 +59,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; interface ITREXFactory { diff --git a/contracts/factory/ITREXGateway.sol b/contracts/factory/ITREXGateway.sol index b7d1da92..90be51ee 100644 --- a/contracts/factory/ITREXGateway.sol +++ b/contracts/factory/ITREXGateway.sol @@ -59,7 +59,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "./ITREXFactory.sol"; diff --git a/contracts/factory/TREXFactory.sol b/contracts/factory/TREXFactory.sol index af8cc9f7..6fec4eb9 100644 --- a/contracts/factory/TREXFactory.sol +++ b/contracts/factory/TREXFactory.sol @@ -59,7 +59,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../roles/AgentRole.sol"; import "../token/IToken.sol"; diff --git a/contracts/factory/TREXGateway.sol b/contracts/factory/TREXGateway.sol index 847918fb..ae1e6d71 100644 --- a/contracts/factory/TREXGateway.sol +++ b/contracts/factory/TREXGateway.sol @@ -59,7 +59,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "./ITREXGateway.sol"; import "../roles/AgentRole.sol"; diff --git a/contracts/proxy/AbstractProxy.sol b/contracts/proxy/AbstractProxy.sol index 1844e7b4..b99c0aa4 100644 --- a/contracts/proxy/AbstractProxy.sol +++ b/contracts/proxy/AbstractProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "./interface/IProxy.sol"; import "./authority/ITREXImplementationAuthority.sol"; diff --git a/contracts/proxy/ClaimTopicsRegistryProxy.sol b/contracts/proxy/ClaimTopicsRegistryProxy.sol index 3d40661b..ec4c3935 100644 --- a/contracts/proxy/ClaimTopicsRegistryProxy.sol +++ b/contracts/proxy/ClaimTopicsRegistryProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "./AbstractProxy.sol"; diff --git a/contracts/proxy/IdentityRegistryProxy.sol b/contracts/proxy/IdentityRegistryProxy.sol index 372a9cd6..747c63e7 100644 --- a/contracts/proxy/IdentityRegistryProxy.sol +++ b/contracts/proxy/IdentityRegistryProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "./AbstractProxy.sol"; diff --git a/contracts/proxy/IdentityRegistryStorageProxy.sol b/contracts/proxy/IdentityRegistryStorageProxy.sol index 6402ee4c..13f8f443 100644 --- a/contracts/proxy/IdentityRegistryStorageProxy.sol +++ b/contracts/proxy/IdentityRegistryStorageProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "./AbstractProxy.sol"; diff --git a/contracts/proxy/ModularComplianceProxy.sol b/contracts/proxy/ModularComplianceProxy.sol index 2c0072a7..61244a45 100644 --- a/contracts/proxy/ModularComplianceProxy.sol +++ b/contracts/proxy/ModularComplianceProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "./AbstractProxy.sol"; diff --git a/contracts/proxy/TokenProxy.sol b/contracts/proxy/TokenProxy.sol index 0ce67fbd..98e8900e 100644 --- a/contracts/proxy/TokenProxy.sol +++ b/contracts/proxy/TokenProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "./AbstractProxy.sol"; diff --git a/contracts/proxy/TrustedIssuersRegistryProxy.sol b/contracts/proxy/TrustedIssuersRegistryProxy.sol index 866a8aa4..953e04e9 100644 --- a/contracts/proxy/TrustedIssuersRegistryProxy.sol +++ b/contracts/proxy/TrustedIssuersRegistryProxy.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "./AbstractProxy.sol"; diff --git a/contracts/proxy/authority/IAFactory.sol b/contracts/proxy/authority/IAFactory.sol index 8993ab86..c45b3b4d 100644 --- a/contracts/proxy/authority/IAFactory.sol +++ b/contracts/proxy/authority/IAFactory.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "./TREXImplementationAuthority.sol"; diff --git a/contracts/proxy/authority/IIAFactory.sol b/contracts/proxy/authority/IIAFactory.sol index 40d3ab45..c30cf8ba 100644 --- a/contracts/proxy/authority/IIAFactory.sol +++ b/contracts/proxy/authority/IIAFactory.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; interface IIAFactory { /// events diff --git a/contracts/proxy/authority/ITREXImplementationAuthority.sol b/contracts/proxy/authority/ITREXImplementationAuthority.sol index 38d967ca..4ea63098 100644 --- a/contracts/proxy/authority/ITREXImplementationAuthority.sol +++ b/contracts/proxy/authority/ITREXImplementationAuthority.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; interface ITREXImplementationAuthority { diff --git a/contracts/proxy/authority/TREXImplementationAuthority.sol b/contracts/proxy/authority/TREXImplementationAuthority.sol index 5aa3ce7e..cee3f546 100644 --- a/contracts/proxy/authority/TREXImplementationAuthority.sol +++ b/contracts/proxy/authority/TREXImplementationAuthority.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@openzeppelin/contracts/access/Ownable.sol"; import "./ITREXImplementationAuthority.sol"; diff --git a/contracts/proxy/interface/IProxy.sol b/contracts/proxy/interface/IProxy.sol index f7c64ba7..792cdb36 100644 --- a/contracts/proxy/interface/IProxy.sol +++ b/contracts/proxy/interface/IProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; interface IProxy { diff --git a/contracts/registry/implementation/ClaimTopicsRegistry.sol b/contracts/registry/implementation/ClaimTopicsRegistry.sol index 4a36931a..99cb60b7 100644 --- a/contracts/registry/implementation/ClaimTopicsRegistry.sol +++ b/contracts/registry/implementation/ClaimTopicsRegistry.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../storage/CTRStorage.sol"; diff --git a/contracts/registry/implementation/IdentityRegistry.sol b/contracts/registry/implementation/IdentityRegistry.sol index 877727b0..d6dc59e7 100644 --- a/contracts/registry/implementation/IdentityRegistry.sol +++ b/contracts/registry/implementation/IdentityRegistry.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; diff --git a/contracts/registry/implementation/IdentityRegistryStorage.sol b/contracts/registry/implementation/IdentityRegistryStorage.sol index 3e452788..c3ed2d79 100644 --- a/contracts/registry/implementation/IdentityRegistryStorage.sol +++ b/contracts/registry/implementation/IdentityRegistryStorage.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; diff --git a/contracts/registry/implementation/TrustedIssuersRegistry.sol b/contracts/registry/implementation/TrustedIssuersRegistry.sol index 46051773..e041f382 100644 --- a/contracts/registry/implementation/TrustedIssuersRegistry.sol +++ b/contracts/registry/implementation/TrustedIssuersRegistry.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; diff --git a/contracts/registry/interface/IClaimTopicsRegistry.sol b/contracts/registry/interface/IClaimTopicsRegistry.sol index 6268cf61..20ab309e 100644 --- a/contracts/registry/interface/IClaimTopicsRegistry.sol +++ b/contracts/registry/interface/IClaimTopicsRegistry.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; interface IClaimTopicsRegistry { /** diff --git a/contracts/registry/interface/IIdentityRegistry.sol b/contracts/registry/interface/IIdentityRegistry.sol index 44fec313..c7e25e2d 100644 --- a/contracts/registry/interface/IIdentityRegistry.sol +++ b/contracts/registry/interface/IIdentityRegistry.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "./ITrustedIssuersRegistry.sol"; import "./IClaimTopicsRegistry.sol"; diff --git a/contracts/registry/interface/IIdentityRegistryStorage.sol b/contracts/registry/interface/IIdentityRegistryStorage.sol index 26e2ff91..ae607408 100644 --- a/contracts/registry/interface/IIdentityRegistryStorage.sol +++ b/contracts/registry/interface/IIdentityRegistryStorage.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; diff --git a/contracts/registry/interface/ITrustedIssuersRegistry.sol b/contracts/registry/interface/ITrustedIssuersRegistry.sol index 498ff7b8..6ba19170 100644 --- a/contracts/registry/interface/ITrustedIssuersRegistry.sol +++ b/contracts/registry/interface/ITrustedIssuersRegistry.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; diff --git a/contracts/registry/storage/CTRStorage.sol b/contracts/registry/storage/CTRStorage.sol index 558b7f91..a4308c23 100644 --- a/contracts/registry/storage/CTRStorage.sol +++ b/contracts/registry/storage/CTRStorage.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; contract CTRStorage { /// @dev All required Claim Topics diff --git a/contracts/registry/storage/IRSStorage.sol b/contracts/registry/storage/IRSStorage.sol index a755f4a0..687fada7 100644 --- a/contracts/registry/storage/IRSStorage.sol +++ b/contracts/registry/storage/IRSStorage.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; diff --git a/contracts/registry/storage/IRStorage.sol b/contracts/registry/storage/IRStorage.sol index 05484531..edc8c024 100644 --- a/contracts/registry/storage/IRStorage.sol +++ b/contracts/registry/storage/IRStorage.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../interface/IClaimTopicsRegistry.sol"; import "../interface/ITrustedIssuersRegistry.sol"; diff --git a/contracts/registry/storage/TIRStorage.sol b/contracts/registry/storage/TIRStorage.sol index 8a0eaa99..976618e5 100644 --- a/contracts/registry/storage/TIRStorage.sol +++ b/contracts/registry/storage/TIRStorage.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; diff --git a/contracts/roles/AgentRole.sol b/contracts/roles/AgentRole.sol index cab3a735..ac25b9e5 100644 --- a/contracts/roles/AgentRole.sol +++ b/contracts/roles/AgentRole.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/contracts/roles/AgentRoleUpgradeable.sol b/contracts/roles/AgentRoleUpgradeable.sol index 7667247a..07c4493b 100644 --- a/contracts/roles/AgentRoleUpgradeable.sol +++ b/contracts/roles/AgentRoleUpgradeable.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; diff --git a/contracts/roles/Roles.sol b/contracts/roles/Roles.sol index 648431a5..53fb5b48 100644 --- a/contracts/roles/Roles.sol +++ b/contracts/roles/Roles.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; /** * @title Roles diff --git a/contracts/roles/permissioning/agent/AgentManager.sol b/contracts/roles/permissioning/agent/AgentManager.sol index f6ef7dd9..c7644e78 100644 --- a/contracts/roles/permissioning/agent/AgentManager.sol +++ b/contracts/roles/permissioning/agent/AgentManager.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; diff --git a/contracts/roles/permissioning/agent/AgentRoles.sol b/contracts/roles/permissioning/agent/AgentRoles.sol index ca7a86de..39290a58 100644 --- a/contracts/roles/permissioning/agent/AgentRoles.sol +++ b/contracts/roles/permissioning/agent/AgentRoles.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol b/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol index b60f624a..4e9014bb 100644 --- a/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol +++ b/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; diff --git a/contracts/roles/permissioning/owner/OwnerManager.sol b/contracts/roles/permissioning/owner/OwnerManager.sol index e2bcac83..a3531631 100644 --- a/contracts/roles/permissioning/owner/OwnerManager.sol +++ b/contracts/roles/permissioning/owner/OwnerManager.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../../../token/IToken.sol"; import "../../../registry/interface/IIdentityRegistry.sol"; diff --git a/contracts/roles/permissioning/owner/OwnerRoles.sol b/contracts/roles/permissioning/owner/OwnerRoles.sol index b82d71f8..7941de24 100644 --- a/contracts/roles/permissioning/owner/OwnerRoles.sol +++ b/contracts/roles/permissioning/owner/OwnerRoles.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol b/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol index 69702eba..7e2a2274 100644 --- a/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol +++ b/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; diff --git a/contracts/token/IToken.sol b/contracts/token/IToken.sol index ce7c1437..dd48f891 100644 --- a/contracts/token/IToken.sol +++ b/contracts/token/IToken.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../registry/interface/IIdentityRegistry.sol"; import "../compliance/modular/IModularCompliance.sol"; diff --git a/contracts/token/Token.sol b/contracts/token/Token.sol index 6b4b4ff2..ac2057c2 100755 --- a/contracts/token/Token.sol +++ b/contracts/token/Token.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "./IToken.sol"; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; diff --git a/contracts/token/TokenStorage.sol b/contracts/token/TokenStorage.sol index ff39a554..6f4a820b 100644 --- a/contracts/token/TokenStorage.sol +++ b/contracts/token/TokenStorage.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; import "../compliance/modular/IModularCompliance.sol"; import "../registry/interface/IIdentityRegistry.sol"; import "./TokenStructs.sol"; diff --git a/contracts/token/TokenStructs.sol b/contracts/token/TokenStructs.sol index e8032f6e..126f3cf5 100644 --- a/contracts/token/TokenStructs.sol +++ b/contracts/token/TokenStructs.sol @@ -62,7 +62,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.26; struct TokenRoles { bool disableMint; diff --git a/hardhat.config.ts b/hardhat.config.ts index a9e8ab6e..cfeeda44 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -8,7 +8,7 @@ import '@primitivefi/hardhat-dodoc'; const config: HardhatUserConfig = { solidity: { - version: '0.8.17', + version: '0.8.26', settings: { optimizer: { enabled: true, diff --git a/package-lock.json b/package-lock.json index 8eea4228..afbdad71 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@commitlint/cli": "^19.3.0", "@nomicfoundation/hardhat-toolbox": "^5.0.0", "@nomiclabs/hardhat-solhint": "^3.1.0", - "@onchain-id/solidity": "^2.2.1", + "@onchain-id/solidity": "^2.2.2-beta2", "@openzeppelin/contracts": "^4.8.3", "@openzeppelin/contracts-upgradeable": "^4.8.3", "@openzeppelin/hardhat-upgrades": "^3.1.0", @@ -2639,10 +2639,11 @@ } }, "node_modules/@onchain-id/solidity": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@onchain-id/solidity/-/solidity-2.2.1.tgz", - "integrity": "sha512-B54InT8yi89qlh9UVCARcfdQLVDP7Lef87B/Ww2Wn19oyEbPmlWho2EK1sgnrt/8Q0fGX/7y5rDnx3HPy28NTA==", - "dev": true + "version": "2.2.2-beta2", + "resolved": "https://registry.npmjs.org/@onchain-id/solidity/-/solidity-2.2.2-beta2.tgz", + "integrity": "sha512-g/T9bHIvXhdQKMsUDhRcyJ6y/qfXo2Pt/CmxizGzeXvqn9mLclxxnu5wJ/lKsPhswKPxpUaPD+i+TgKhKLi/gA==", + "dev": true, + "license": "ISC" }, "node_modules/@openzeppelin/contracts": { "version": "4.9.6", diff --git a/package.json b/package.json index eb89e5aa..4251eb2b 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "@commitlint/cli": "^19.3.0", "@nomicfoundation/hardhat-toolbox": "^5.0.0", "@nomiclabs/hardhat-solhint": "^3.1.0", - "@onchain-id/solidity": "^2.2.1", + "@onchain-id/solidity": "^2.2.2-beta2", "@openzeppelin/contracts": "^4.8.3", "@openzeppelin/contracts-upgradeable": "^4.8.3", "@openzeppelin/hardhat-upgrades": "^3.1.0", From 258b5315adfcaa06e9649d09583953581f3ee500 Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Fri, 28 Jun 2024 09:43:10 +0200 Subject: [PATCH 20/55] =?UTF-8?q?=E2=9C=85()=20TREX-122=20Update=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/compliances/module-transfer-restrict.test.ts | 8 ++++---- test/fixtures/deploy-full-suite.fixture.ts | 12 ++++++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/test/compliances/module-transfer-restrict.test.ts b/test/compliances/module-transfer-restrict.test.ts index 4c18dcfd..909963de 100644 --- a/test/compliances/module-transfer-restrict.test.ts +++ b/test/compliances/module-transfer-restrict.test.ts @@ -292,8 +292,8 @@ describe('Compliance Module: TransferRestrict', () => { it('should return true', async () => { const context = await loadFixture(deployTransferRestrictFullSuite); const to = context.accounts.anotherWallet.address; - const from = ethers.constants.AddressZero; - const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + const from = ethers.ZeroAddress; + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.target); expect(result).to.be.true; }); }); @@ -301,9 +301,9 @@ describe('Compliance Module: TransferRestrict', () => { describe('when recipient is the null address', () => { it('should return true', async () => { const context = await loadFixture(deployTransferRestrictFullSuite); - const to = ethers.constants.AddressZero; + const to = ethers.ZeroAddress; const from = context.accounts.aliceWallet.address; - const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.target); expect(result).to.be.true; }); }); diff --git a/test/fixtures/deploy-full-suite.fixture.ts b/test/fixtures/deploy-full-suite.fixture.ts index 46411712..6b299275 100644 --- a/test/fixtures/deploy-full-suite.fixture.ts +++ b/test/fixtures/deploy-full-suite.fixture.ts @@ -4,12 +4,20 @@ import OnchainID from '@onchain-id/solidity'; import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { IIdFactory } from '../../typechain-types'; + export async function deployIdentityProxy(implementationAuthority: Contract['target'], managementKey: string, signer: Signer) { const identity = await new ethers.ContractFactory(OnchainID.contracts.IdentityProxy.abi, OnchainID.contracts.IdentityProxy.bytecode, signer).deploy( implementationAuthority, managementKey, ); - return ethers.getContractAt('Identity', identity.target, signer); + return ethers.getContractAt(OnchainID.contracts.Identity.abi, identity.target, signer); +} + +export async function deployClaimIssuer(initialManagementKey: string, signer: Signer) { + const claimIssuer = await new ethers.ContractFactory(OnchainID.contracts.ClaimIssuer.abi, OnchainID.contracts.ClaimIssuer.bytecode, signer).deploy( + initialManagementKey + ); + return ethers.getContractAt(OnchainID.contracts.ClaimIssuer.abi, claimIssuer.target, signer); } export async function deployFullSuiteFixture() { @@ -98,7 +106,7 @@ export async function deployFullSuiteFixture() { const claimTopics = [ethers.keccak256(ethers.toUtf8Bytes('CLAIM_TOPIC'))]; await claimTopicsRegistry.connect(deployer).addClaimTopic(claimTopics[0]); - const claimIssuerContract = await ethers.deployContract('ClaimIssuer', [claimIssuer.address], claimIssuer); + const claimIssuerContract = await deployClaimIssuer(claimIssuer.address, claimIssuer); await claimIssuerContract .connect(claimIssuer) .addKey(ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address'], [claimIssuerSigningKey.address])), 3, 1); From fdec48929d273729959c4df34182e1179a9c457a Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Fri, 28 Jun 2024 10:47:45 +0200 Subject: [PATCH 21/55] Lint issues --- test/fixtures/deploy-full-suite.fixture.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/fixtures/deploy-full-suite.fixture.ts b/test/fixtures/deploy-full-suite.fixture.ts index 6b299275..6d3cafba 100644 --- a/test/fixtures/deploy-full-suite.fixture.ts +++ b/test/fixtures/deploy-full-suite.fixture.ts @@ -4,7 +4,6 @@ import OnchainID from '@onchain-id/solidity'; import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { IIdFactory } from '../../typechain-types'; - export async function deployIdentityProxy(implementationAuthority: Contract['target'], managementKey: string, signer: Signer) { const identity = await new ethers.ContractFactory(OnchainID.contracts.IdentityProxy.abi, OnchainID.contracts.IdentityProxy.bytecode, signer).deploy( implementationAuthority, @@ -15,7 +14,7 @@ export async function deployIdentityProxy(implementationAuthority: Contract['tar export async function deployClaimIssuer(initialManagementKey: string, signer: Signer) { const claimIssuer = await new ethers.ContractFactory(OnchainID.contracts.ClaimIssuer.abi, OnchainID.contracts.ClaimIssuer.bytecode, signer).deploy( - initialManagementKey + initialManagementKey, ); return ethers.getContractAt(OnchainID.contracts.ClaimIssuer.abi, claimIssuer.target, signer); } From 30819b4d9f674dfbd814e6918f154621d2ba4de5 Mon Sep 17 00:00:00 2001 From: joachimlebrun Date: Mon, 1 Jul 2024 19:40:52 +0800 Subject: [PATCH 22/55] =?UTF-8?q?=E2=9C=85(test)=20update=20dva=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/dva.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/dva.test.ts b/test/dva.test.ts index 9f53b04e..95aed026 100644 --- a/test/dva.test.ts +++ b/test/dva.test.ts @@ -10,9 +10,8 @@ describe('DVATransferManager', () => { const context = await loadFixture(deployFullSuiteFixture); const implementation = await ethers.deployContract('DVATransferManager'); - const transferManagerProxy = await ethers.deployContract('DVATransferManagerProxy', [implementation.target, '0x']); + const transferManagerProxy = await ethers.deployContract('DVATransferManagerProxy', [implementation.target, '0x8129fc1c']); const transferManager = await ethers.getContractAt('DVATransferManager', transferManagerProxy.target); - await transferManager.initialize(); return { ...context, suite: { From b5ace5e20bc095ca60632c61ab5346dbde64a6fd Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Fri, 28 Jun 2024 17:01:26 +0200 Subject: [PATCH 23/55] =?UTF-8?q?=E2=99=BB()=20TREX-132=20Custom=20Errors?= =?UTF-8?q?=20for=20zero=20address=20and=20roles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compliance/modular/ModularCompliance.sol | 15 +-- .../modular/modules/AbstractModule.sol | 5 +- .../modules/AbstractModuleUpgradeable.sol | 5 +- contracts/factory/TREXFactory.sol | 5 +- contracts/factory/TREXGateway.sol | 114 +++++++---------- .../libraries/errors/InvalidArgumentLib.sol | 75 +++++++++++ contracts/libraries/errors/RoleLib.sol | 97 +++++++++++++++ contracts/proxy/AbstractProxy.sol | 3 +- contracts/proxy/IdentityRegistryProxy.sol | 2 +- .../proxy/IdentityRegistryStorageProxy.sol | 2 +- contracts/proxy/TokenProxy.sol | 5 +- .../proxy/TrustedIssuersRegistryProxy.sol | 3 +- .../authority/TREXImplementationAuthority.sol | 5 +- .../implementation/IdentityRegistry.sol | 3 +- .../IdentityRegistryStorage.sol | 13 +- .../implementation/TrustedIssuersRegistry.sol | 8 +- contracts/roles/AgentRole.sol | 5 +- contracts/roles/AgentRoleUpgradeable.sol | 5 +- contracts/roles/Roles.sol | 9 +- .../permissioning/agent/AgentManager.sol | 39 +++--- .../roles/permissioning/agent/AgentRoles.sol | 3 +- .../agent/AgentRolesUpgradeable.sol | 3 +- .../permissioning/owner/OwnerManager.sol | 28 +++-- .../roles/permissioning/owner/OwnerRoles.sol | 3 +- .../owner/OwnerRolesUpgradeable.sol | 3 +- contracts/token/Token.sol | 13 +- hardhat.config.ts | 1 + test/agentManager.test.ts | 116 ++++++++++-------- test/agentRole.test.ts | 8 +- .../trex-implementation-authority.test.ts | 11 +- test/compliance.test.ts | 22 ++-- test/factory.test.ts | 2 +- test/gateway.test.ts | 12 +- .../identity-registry-storage.test.ts | 28 +++-- test/registries/identity-registry.test.ts | 6 +- .../trusted-issuers-registry.test.ts | 15 ++- test/token/token-information.test.ts | 4 +- 37 files changed, 447 insertions(+), 249 deletions(-) create mode 100644 contracts/libraries/errors/InvalidArgumentLib.sol create mode 100644 contracts/libraries/errors/RoleLib.sol diff --git a/contracts/compliance/modular/ModularCompliance.sol b/contracts/compliance/modular/ModularCompliance.sol index e9aac245..01a155ff 100644 --- a/contracts/compliance/modular/ModularCompliance.sol +++ b/contracts/compliance/modular/ModularCompliance.sol @@ -67,6 +67,7 @@ import "../../token/IToken.sol"; import "./IModularCompliance.sol"; import "./MCStorage.sol"; import "./modules/IModule.sol"; +import "../../libraries/errors/InvalidArgumentLib.sol"; contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage { @@ -91,7 +92,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage function bindToken(address _token) external override { require(owner() == msg.sender || (_tokenBound == address(0) && msg.sender == _token), "only owner or token can call"); - require(_token != address(0), "invalid argument - zero address"); + require(_token != address(0), InvalidArgumentLib.ZeroAddress()); _tokenBound = _token; emit TokenBound(_token); } @@ -102,7 +103,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage function unbindToken(address _token) external override { require(owner() == msg.sender || msg.sender == _token , "only owner or token can call"); require(_token == _tokenBound, "This token is not bound"); - require(_token != address(0), "invalid argument - zero address"); + require(_token != address(0), InvalidArgumentLib.ZeroAddress()); delete _tokenBound; emit TokenUnbound(_token); } @@ -111,7 +112,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage * @dev See {IModularCompliance-addModule}. */ function addModule(address _module) external override onlyOwner { - require(_module != address(0), "invalid argument - zero address"); + require(_module != address(0), InvalidArgumentLib.ZeroAddress()); require(!_moduleBound[_module], "module already bound"); require(_modules.length <= 24, "cannot add more than 25 modules"); IModule module = IModule(_module); @@ -129,7 +130,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage * @dev See {IModularCompliance-removeModule}. */ function removeModule(address _module) external override onlyOwner { - require(_module != address(0), "invalid argument - zero address"); + require(_module != address(0), InvalidArgumentLib.ZeroAddress()); require(_moduleBound[_module], "module not bound"); uint256 length = _modules.length; for (uint256 i = 0; i < length; i++) { @@ -151,7 +152,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage require( _from != address(0) && _to != address(0) - , "invalid argument - zero address"); + , InvalidArgumentLib.ZeroAddress()); require(_value > 0, "invalid argument - no value transfer"); uint256 length = _modules.length; for (uint256 i = 0; i < length; i++) { @@ -163,7 +164,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage * @dev See {IModularCompliance-created}. */ function created(address _to, uint256 _value) external onlyToken override { - require(_to != address(0), "invalid argument - zero address"); + require(_to != address(0), InvalidArgumentLib.ZeroAddress()); require(_value > 0, "invalid argument - no value mint"); uint256 length = _modules.length; for (uint256 i = 0; i < length; i++) { @@ -175,7 +176,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage * @dev See {IModularCompliance-destroyed}. */ function destroyed(address _from, uint256 _value) external onlyToken override { - require(_from != address(0), "invalid argument - zero address"); + require(_from != address(0), InvalidArgumentLib.ZeroAddress()); require(_value > 0, "invalid argument - no value burn"); uint256 length = _modules.length; for (uint256 i = 0; i < length; i++) { diff --git a/contracts/compliance/modular/modules/AbstractModule.sol b/contracts/compliance/modular/modules/AbstractModule.sol index a67fc0e2..71eb9950 100644 --- a/contracts/compliance/modular/modules/AbstractModule.sol +++ b/contracts/compliance/modular/modules/AbstractModule.sol @@ -63,6 +63,7 @@ pragma solidity 0.8.26; import "./IModule.sol"; +import "../../../libraries/errors/InvalidArgumentLib.sol"; abstract contract AbstractModule is IModule { @@ -89,7 +90,7 @@ abstract contract AbstractModule is IModule { * @dev See {IModule-bindCompliance}. */ function bindCompliance(address _compliance) external override { - require(_compliance != address(0), "invalid argument - zero address"); + require(_compliance != address(0), InvalidArgumentLib.ZeroAddress()); require(!_complianceBound[_compliance], "compliance already bound"); require(msg.sender == _compliance, "only compliance contract can call"); _complianceBound[_compliance] = true; @@ -100,7 +101,7 @@ abstract contract AbstractModule is IModule { * @dev See {IModule-unbindCompliance}. */ function unbindCompliance(address _compliance) external onlyComplianceCall override { - require(_compliance != address(0), "invalid argument - zero address"); + require(_compliance != address(0), InvalidArgumentLib.ZeroAddress()); require(msg.sender == _compliance, "only compliance contract can call"); _complianceBound[_compliance] = false; emit ComplianceUnbound(_compliance); diff --git a/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol index e4fb90a9..537a034b 100644 --- a/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol +++ b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol @@ -66,6 +66,7 @@ import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "./IModule.sol"; +import "../../../libraries/errors/InvalidArgumentLib.sol"; abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUpgradeable, UUPSUpgradeable { struct AbstractModuleStorage { @@ -100,7 +101,7 @@ abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUp */ function bindCompliance(address _compliance) external override { AbstractModuleStorage storage s = _getAbstractModuleStorage(); - require(_compliance != address(0), "invalid argument - zero address"); + require(_compliance != address(0), InvalidArgumentLib.ZeroAddress()); require(!s.complianceBound[_compliance], "compliance already bound"); require(msg.sender == _compliance, "only compliance contract can call"); s.complianceBound[_compliance] = true; @@ -112,7 +113,7 @@ abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUp */ function unbindCompliance(address _compliance) external onlyComplianceCall override { AbstractModuleStorage storage s = _getAbstractModuleStorage(); - require(_compliance != address(0), "invalid argument - zero address"); + require(_compliance != address(0), InvalidArgumentLib.ZeroAddress()); require(msg.sender == _compliance, "only compliance contract can call"); s.complianceBound[_compliance] = false; emit ComplianceUnbound(_compliance); diff --git a/contracts/factory/TREXFactory.sol b/contracts/factory/TREXFactory.sol index 6fec4eb9..25120d12 100644 --- a/contracts/factory/TREXFactory.sol +++ b/contracts/factory/TREXFactory.sol @@ -77,6 +77,7 @@ import "../proxy/TrustedIssuersRegistryProxy.sol"; import "../proxy/ModularComplianceProxy.sol"; import "./ITREXFactory.sol"; import "@onchain-id/solidity/contracts/factory/IIdFactory.sol"; +import "../libraries/errors/InvalidArgumentLib.sol"; contract TREXFactory is ITREXFactory, Ownable { @@ -208,7 +209,7 @@ contract TREXFactory is ITREXFactory, Ownable { * @dev See {ITREXFactory-setImplementationAuthority}. */ function setImplementationAuthority(address implementationAuthority_) public override onlyOwner { - require(implementationAuthority_ != address(0), "invalid argument - zero address"); + require(implementationAuthority_ != address(0), InvalidArgumentLib.ZeroAddress()); // should not be possible to set an implementation authority that is not complete require( (ITREXImplementationAuthority(implementationAuthority_)).getTokenImplementation() != address(0) @@ -226,7 +227,7 @@ contract TREXFactory is ITREXFactory, Ownable { * @dev See {ITREXFactory-setIdFactory}. */ function setIdFactory(address idFactory_) public override onlyOwner { - require(idFactory_ != address(0), "invalid argument - zero address"); + require(idFactory_ != address(0), InvalidArgumentLib.ZeroAddress()); _idFactory = idFactory_; emit IdFactorySet(idFactory_); } diff --git a/contracts/factory/TREXGateway.sol b/contracts/factory/TREXGateway.sol index ae1e6d71..901ea7ad 100644 --- a/contracts/factory/TREXGateway.sol +++ b/contracts/factory/TREXGateway.sol @@ -65,9 +65,8 @@ import "./ITREXGateway.sol"; import "../roles/AgentRole.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -/// A required parameter was set to the Zero address. -error ZeroAddress(); +import "../libraries/errors/InvalidArgumentLib.sol"; +import "../libraries/errors/RoleLib.sol"; /// The Public Deployment Status is already set properly error PublicDeploymentAlreadyEnabled(); @@ -96,9 +95,6 @@ error PublicCannotDeployOnBehalf(); /// Discount cannot be bigger than 10000 (100%) error DiscountOutOfRange(); -/// Only Owner or Agent can call -error OnlyAdminCall(); - /// Batch Size is too big, could run out of gas error BatchMaxLengthExceeded(uint16 lengthLimit); @@ -136,9 +132,8 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-setFactory}. */ function setFactory(address factory) external override onlyOwner { - if(factory == address(0)) { - revert ZeroAddress(); - } + require(factory != address(0), InvalidArgumentLib.ZeroAddress()); + _factory = factory; emit FactorySet(factory); } @@ -147,12 +142,12 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-setPublicDeploymentStatus}. */ function setPublicDeploymentStatus(bool _isEnabled) external override onlyOwner { - if(_isEnabled == _publicDeploymentStatus && _isEnabled == true) { - revert PublicDeploymentAlreadyEnabled(); - } - if(_isEnabled == _publicDeploymentStatus && _isEnabled == false) { + if(_isEnabled == _publicDeploymentStatus) { + if (_isEnabled) + revert PublicDeploymentAlreadyEnabled(); revert PublicDeploymentAlreadyDisabled(); } + _publicDeploymentStatus = _isEnabled; emit PublicDeploymentStatusSet(_isEnabled); } @@ -168,12 +163,12 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-enableDeploymentFee}. */ function enableDeploymentFee(bool _isEnabled) external override onlyOwner { - if(_isEnabled == _deploymentFeeEnabled && _isEnabled == true) { - revert DeploymentFeesAlreadyEnabled(); - } - if(_isEnabled == _deploymentFeeEnabled && _isEnabled == false) { + if(_isEnabled == _deploymentFeeEnabled) { + if (_isEnabled) + revert DeploymentFeesAlreadyEnabled(); revert DeploymentFeesAlreadyDisabled(); } + _deploymentFeeEnabled = _isEnabled; emit DeploymentFeeEnabled(_isEnabled); } @@ -182,9 +177,8 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-setDeploymentFee}. */ function setDeploymentFee(uint256 _fee, address _feeToken, address _feeCollector) external override onlyOwner { - if(_feeToken == address(0) || _feeCollector == address(0)) { - revert ZeroAddress(); - } + require(_feeToken != address(0) && _feeCollector != address(0), InvalidArgumentLib.ZeroAddress()); + _deploymentFee.fee = _fee; _deploymentFee.feeToken = _feeToken; _deploymentFee.feeCollector = _feeCollector; @@ -195,16 +189,12 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-batchAddDeployer}. */ function batchAddDeployer(address[] calldata deployers) external override { - if(!isAgent(msg.sender) && msg.sender != owner()) { - revert OnlyAdminCall(); - } - if(deployers.length > 500) { - revert BatchMaxLengthExceeded(500); - } + require(isAgent(msg.sender) || msg.sender == owner(), RoleLib.SenderIsNotAdmin()); + require(deployers.length <= 500, BatchMaxLengthExceeded(500)); + for (uint256 i = 0; i < deployers.length; i++) { - if(isDeployer(deployers[i])) { - revert DeployerAlreadyExists(deployers[i]); - } + require(!isDeployer(deployers[i]), DeployerAlreadyExists(deployers[i])); + _deployers[deployers[i]] = true; emit DeployerAdded(deployers[i]); } @@ -214,12 +204,9 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-addDeployer}. */ function addDeployer(address deployer) external override { - if(!isAgent(msg.sender) && msg.sender != owner()) { - revert OnlyAdminCall(); - } - if(isDeployer(deployer)) { - revert DeployerAlreadyExists(deployer); - } + require(isAgent(msg.sender) || msg.sender == owner(), RoleLib.SenderIsNotAdmin()); + require(!isDeployer(deployer), DeployerAlreadyExists(deployer)); + _deployers[deployer] = true; emit DeployerAdded(deployer); } @@ -228,16 +215,12 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-batchRemoveDeployer}. */ function batchRemoveDeployer(address[] calldata deployers) external override { - if(!isAgent(msg.sender) && msg.sender != owner()) { - revert OnlyAdminCall(); - } - if(deployers.length > 500) { - revert BatchMaxLengthExceeded(500); - } + require(isAgent(msg.sender) || msg.sender == owner(), RoleLib.SenderIsNotAdmin()); + require(deployers.length <= 500, BatchMaxLengthExceeded(500)); + for (uint256 i = 0; i < deployers.length; i++) { - if(!isDeployer(deployers[i])) { - revert DeployerDoesNotExist(deployers[i]); - } + require(isDeployer(deployers[i]), DeployerDoesNotExist(deployers[i])); + delete _deployers[deployers[i]]; emit DeployerRemoved(deployers[i]); } @@ -247,12 +230,9 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-removeDeployer}. */ function removeDeployer(address deployer) external override { - if(!isAgent(msg.sender) && msg.sender != owner()) { - revert OnlyAdminCall(); - } - if(!isDeployer(deployer)) { - revert DeployerDoesNotExist(deployer); - } + require(isAgent(msg.sender) || msg.sender == owner(), RoleLib.SenderIsNotAdmin()); + require(isDeployer(deployer), DeployerDoesNotExist(deployer)); + delete _deployers[deployer]; emit DeployerRemoved(deployer); } @@ -261,16 +241,12 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-batchApplyFeeDiscount}. */ function batchApplyFeeDiscount(address[] calldata deployers, uint16[] calldata discounts) external override { - if(!isAgent(msg.sender) && msg.sender != owner()) { - revert OnlyAdminCall(); - } - if(deployers.length > 500) { - revert BatchMaxLengthExceeded(500); - } + require(isAgent(msg.sender) || msg.sender == owner(), RoleLib.SenderIsNotAdmin()); + require(deployers.length <= 500, BatchMaxLengthExceeded(500)); + for (uint256 i = 0; i < deployers.length; i++) { - if(discounts[i] > 10000) { - revert DiscountOutOfRange(); - } + require(discounts[i] <= 10000, DiscountOutOfRange()); + _feeDiscount[deployers[i]] = discounts[i]; emit FeeDiscountApplied(deployers[i], discounts[i]); } @@ -280,12 +256,9 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-applyFeeDiscount}. */ function applyFeeDiscount(address deployer, uint16 discount) external override { - if(!isAgent(msg.sender) && msg.sender != owner()) { - revert OnlyAdminCall(); - } - if(discount > 10000) { - revert DiscountOutOfRange(); - } + require(isAgent(msg.sender) || msg.sender == owner(), RoleLib.SenderIsNotAdmin()); + require(discount <= 10000, DiscountOutOfRange()); + _feeDiscount[deployer] = discount; emit FeeDiscountApplied(deployer, discount); } @@ -297,9 +270,8 @@ contract TREXGateway is ITREXGateway, AgentRole { ITREXFactory.TokenDetails[] memory _tokenDetails, ITREXFactory.ClaimDetails[] memory _claimDetails) external override { - if(_tokenDetails.length > 5) { - revert BatchMaxLengthExceeded(5); - } + require(_tokenDetails.length <= 5, BatchMaxLengthExceeded(5)); + for (uint256 i = 0; i < _tokenDetails.length; i++) { deployTREXSuite(_tokenDetails[i], _claimDetails[i]); } @@ -338,14 +310,14 @@ contract TREXGateway is ITREXGateway, AgentRole { */ function deployTREXSuite(ITREXFactory.TokenDetails memory _tokenDetails, ITREXFactory.ClaimDetails memory _claimDetails) public override { - if(_publicDeploymentStatus == false && !isDeployer(msg.sender)) { + if(!_publicDeploymentStatus && !isDeployer(msg.sender)) { revert PublicDeploymentsNotAllowed(); } - if(_publicDeploymentStatus == true && msg.sender != _tokenDetails.owner && !isDeployer(msg.sender)) { + if(_publicDeploymentStatus && msg.sender != _tokenDetails.owner && !isDeployer(msg.sender)) { revert PublicCannotDeployOnBehalf(); } uint256 feeApplied = 0; - if(_deploymentFeeEnabled == true) { + if(_deploymentFeeEnabled) { if(_deploymentFee.fee > 0 && _feeDiscount[msg.sender] < 10000) { feeApplied = calculateFee(msg.sender); IERC20(_deploymentFee.feeToken).transferFrom( diff --git a/contracts/libraries/errors/InvalidArgumentLib.sol b/contracts/libraries/errors/InvalidArgumentLib.sol new file mode 100644 index 00000000..9638e074 --- /dev/null +++ b/contracts/libraries/errors/InvalidArgumentLib.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-3.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// + +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2023, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +pragma solidity 0.8.26; + + +library InvalidArgumentLib { + + /// @notice Thrown when the string passed is empty. + error EmptyString(); + + /// @notice Thrown when the address passed is the zero address. + error ZeroAddress(); +} + diff --git a/contracts/libraries/errors/RoleLib.sol b/contracts/libraries/errors/RoleLib.sol new file mode 100644 index 00000000..09fa086d --- /dev/null +++ b/contracts/libraries/errors/RoleLib.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-3.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// + +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2023, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +pragma solidity 0.8.26; + + +library RoleLib { + + error AccountAlreadyHasRole(); + + error AccountDoesNotHaveRole(); + + error SenderIsNotAdmin(); + + error SenderIsNotClaimRegistryManager(); + + error SenderIsNotComplianceManager(); + + error SenderIsNotComplianceSetter(); + + error SenderIsNotFreezer(); + + error SenderIsNotIssuersRegistryManager(); + + error SenderIsNotRecoveryAgent(); + + error SenderIsNotRegistryAddressSetter(); + + error SenderIsNotSupplyModifier(); + + error SenderIsNotTokenInformationManager(); + + error SenderIsNotTransferManager(); + + error SenderIsNotWhiteListManager(); + +} diff --git a/contracts/proxy/AbstractProxy.sol b/contracts/proxy/AbstractProxy.sol index b99c0aa4..fe20ce03 100644 --- a/contracts/proxy/AbstractProxy.sol +++ b/contracts/proxy/AbstractProxy.sol @@ -65,6 +65,7 @@ pragma solidity 0.8.26; import "./interface/IProxy.sol"; import "./authority/ITREXImplementationAuthority.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import "../libraries/errors/InvalidArgumentLib.sol"; abstract contract AbstractProxy is IProxy, Initializable { @@ -73,7 +74,7 @@ abstract contract AbstractProxy is IProxy, Initializable { */ function setImplementationAuthority(address _newImplementationAuthority) external override { require(msg.sender == getImplementationAuthority(), "only current implementationAuthority can call"); - require(_newImplementationAuthority != address(0), "invalid argument - zero address"); + require(_newImplementationAuthority != address(0), InvalidArgumentLib.ZeroAddress()); require( (ITREXImplementationAuthority(_newImplementationAuthority)).getTokenImplementation() != address(0) && (ITREXImplementationAuthority(_newImplementationAuthority)).getCTRImplementation() != address(0) diff --git a/contracts/proxy/IdentityRegistryProxy.sol b/contracts/proxy/IdentityRegistryProxy.sol index 747c63e7..22ecfb7b 100644 --- a/contracts/proxy/IdentityRegistryProxy.sol +++ b/contracts/proxy/IdentityRegistryProxy.sol @@ -77,7 +77,7 @@ contract IdentityRegistryProxy is AbstractProxy { && _trustedIssuersRegistry != address(0) && _claimTopicsRegistry != address(0) && _identityStorage != address(0) - , "invalid argument - zero address"); + , InvalidArgumentLib.ZeroAddress()); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); diff --git a/contracts/proxy/IdentityRegistryStorageProxy.sol b/contracts/proxy/IdentityRegistryStorageProxy.sol index 13f8f443..84d21621 100644 --- a/contracts/proxy/IdentityRegistryStorageProxy.sol +++ b/contracts/proxy/IdentityRegistryStorageProxy.sol @@ -67,7 +67,7 @@ import "./AbstractProxy.sol"; contract IdentityRegistryStorageProxy is AbstractProxy { constructor(address implementationAuthority) { - require(implementationAuthority != address(0), "invalid argument - zero address"); + require(implementationAuthority != address(0), InvalidArgumentLib.ZeroAddress()); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); diff --git a/contracts/proxy/TokenProxy.sol b/contracts/proxy/TokenProxy.sol index 98e8900e..a858df7d 100644 --- a/contracts/proxy/TokenProxy.sol +++ b/contracts/proxy/TokenProxy.sol @@ -63,6 +63,7 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; +import "../libraries/errors/InvalidArgumentLib.sol"; contract TokenProxy is AbstractProxy { @@ -80,11 +81,11 @@ contract TokenProxy is AbstractProxy { implementationAuthority != address(0) && _identityRegistry != address(0) && _compliance != address(0) - , "invalid argument - zero address"); + , InvalidArgumentLib.ZeroAddress()); require( keccak256(abi.encode(_name)) != keccak256(abi.encode("")) && keccak256(abi.encode(_symbol)) != keccak256(abi.encode("")) - , "invalid argument - empty string"); + , InvalidArgumentLib.EmptyString()); require(0 <= _decimals && _decimals <= 18, "decimals between 0 and 18"); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); diff --git a/contracts/proxy/TrustedIssuersRegistryProxy.sol b/contracts/proxy/TrustedIssuersRegistryProxy.sol index 953e04e9..0f0b8034 100644 --- a/contracts/proxy/TrustedIssuersRegistryProxy.sol +++ b/contracts/proxy/TrustedIssuersRegistryProxy.sol @@ -64,11 +64,12 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; +import "../libraries/errors/InvalidArgumentLib.sol"; contract TrustedIssuersRegistryProxy is AbstractProxy { constructor(address implementationAuthority) { - require(implementationAuthority != address(0), "invalid argument - zero address"); + require(implementationAuthority != address(0), InvalidArgumentLib.ZeroAddress()); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); diff --git a/contracts/proxy/authority/TREXImplementationAuthority.sol b/contracts/proxy/authority/TREXImplementationAuthority.sol index cee3f546..cfa4d012 100644 --- a/contracts/proxy/authority/TREXImplementationAuthority.sol +++ b/contracts/proxy/authority/TREXImplementationAuthority.sol @@ -68,6 +68,7 @@ import "../../token/IToken.sol"; import "../interface/IProxy.sol"; import "../../factory/ITREXFactory.sol"; import "./IIAFactory.sol"; +import "../../libraries/errors/InvalidArgumentLib.sol"; contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { @@ -159,7 +160,7 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { */ // solhint-disable-next-line code-complexity, function-max-lines function changeImplementationAuthority(address _token, address _newImplementationAuthority) external override { - require(_token != address(0), "invalid argument - zero address"); + require(_token != address(0), InvalidArgumentLib.ZeroAddress()); if(_newImplementationAuthority == address(0) && !isReferenceContract()){ revert("only reference contract can deploy new IAs");} @@ -291,7 +292,7 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { && _trex.mcImplementation != address(0) && _trex.tirImplementation != address(0) && _trex.tokenImplementation != address(0) - , "invalid argument - zero address"); + , InvalidArgumentLib.ZeroAddress()); _contracts[_versionToBytes(_version)] = _trex; emit TREXVersionAdded(_version, _trex); } diff --git a/contracts/registry/implementation/IdentityRegistry.sol b/contracts/registry/implementation/IdentityRegistry.sol index d6dc59e7..d7537873 100644 --- a/contracts/registry/implementation/IdentityRegistry.sol +++ b/contracts/registry/implementation/IdentityRegistry.sol @@ -71,6 +71,7 @@ import "../interface/IIdentityRegistry.sol"; import "../../roles/AgentRoleUpgradeable.sol"; import "../interface/IIdentityRegistryStorage.sol"; import "../storage/IRStorage.sol"; +import "../../libraries/errors/InvalidArgumentLib.sol"; contract IdentityRegistry is IIdentityRegistry, AgentRoleUpgradeable, IRStorage { @@ -93,7 +94,7 @@ contract IdentityRegistry is IIdentityRegistry, AgentRoleUpgradeable, IRStorage _trustedIssuersRegistry != address(0) && _claimTopicsRegistry != address(0) && _identityStorage != address(0) - , "invalid argument - zero address"); + , InvalidArgumentLib.ZeroAddress()); _tokenTopicsRegistry = IClaimTopicsRegistry(_claimTopicsRegistry); _tokenIssuersRegistry = ITrustedIssuersRegistry(_trustedIssuersRegistry); _tokenIdentityStorage = IIdentityRegistryStorage(_identityStorage); diff --git a/contracts/registry/implementation/IdentityRegistryStorage.sol b/contracts/registry/implementation/IdentityRegistryStorage.sol index c3ed2d79..acd722ea 100644 --- a/contracts/registry/implementation/IdentityRegistryStorage.sol +++ b/contracts/registry/implementation/IdentityRegistryStorage.sol @@ -67,6 +67,7 @@ import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; import "../../roles/AgentRoleUpgradeable.sol"; import "../interface/IIdentityRegistryStorage.sol"; import "../storage/IRSStorage.sol"; +import "../../libraries/errors/InvalidArgumentLib.sol"; contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeable, IRSStorage { @@ -85,7 +86,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab require( _userAddress != address(0) && address(_identity) != address(0) - , "invalid argument - zero address"); + , InvalidArgumentLib.ZeroAddress()); require(address(_identities[_userAddress].identityContract) == address(0), "address stored already"); _identities[_userAddress].identityContract = _identity; _identities[_userAddress].investorCountry = _country; @@ -99,7 +100,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab require( _userAddress != address(0) && address(_identity) != address(0) - , "invalid argument - zero address"); + , InvalidArgumentLib.ZeroAddress()); require(address(_identities[_userAddress].identityContract) != address(0), "address not stored yet"); IIdentity oldIdentity = _identities[_userAddress].identityContract; _identities[_userAddress].identityContract = _identity; @@ -110,7 +111,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab * @dev See {IIdentityRegistryStorage-modifyStoredInvestorCountry}. */ function modifyStoredInvestorCountry(address _userAddress, uint16 _country) external override onlyAgent { - require(_userAddress != address(0), "invalid argument - zero address"); + require(_userAddress != address(0), InvalidArgumentLib.ZeroAddress()); require(address(_identities[_userAddress].identityContract) != address(0), "address not stored yet"); _identities[_userAddress].investorCountry = _country; emit CountryModified(_userAddress, _country); @@ -120,7 +121,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab * @dev See {IIdentityRegistryStorage-removeIdentityFromStorage}. */ function removeIdentityFromStorage(address _userAddress) external override onlyAgent { - require(_userAddress != address(0), "invalid argument - zero address"); + require(_userAddress != address(0), InvalidArgumentLib.ZeroAddress()); require(address(_identities[_userAddress].identityContract) != address(0), "address not stored yet"); IIdentity oldIdentity = _identities[_userAddress].identityContract; delete _identities[_userAddress]; @@ -131,7 +132,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab * @dev See {IIdentityRegistryStorage-bindIdentityRegistry}. */ function bindIdentityRegistry(address _identityRegistry) external override { - require(_identityRegistry != address(0), "invalid argument - zero address"); + require(_identityRegistry != address(0), InvalidArgumentLib.ZeroAddress()); require(_identityRegistries.length < 300, "cannot bind more than 300 IR to 1 IRS"); addAgent(_identityRegistry); _identityRegistries.push(_identityRegistry); @@ -142,7 +143,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab * @dev See {IIdentityRegistryStorage-unbindIdentityRegistry}. */ function unbindIdentityRegistry(address _identityRegistry) external override { - require(_identityRegistry != address(0), "invalid argument - zero address"); + require(_identityRegistry != address(0), InvalidArgumentLib.ZeroAddress()); require(_identityRegistries.length > 0, "identity registry is not stored"); uint256 length = _identityRegistries.length; for (uint256 i = 0; i < length; i++) { diff --git a/contracts/registry/implementation/TrustedIssuersRegistry.sol b/contracts/registry/implementation/TrustedIssuersRegistry.sol index e041f382..267b8bcd 100644 --- a/contracts/registry/implementation/TrustedIssuersRegistry.sol +++ b/contracts/registry/implementation/TrustedIssuersRegistry.sol @@ -67,7 +67,7 @@ import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../interface/ITrustedIssuersRegistry.sol"; import "../storage/TIRStorage.sol"; - +import "../../libraries/errors/InvalidArgumentLib.sol"; contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, TIRStorage { @@ -79,7 +79,7 @@ contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, * @dev See {ITrustedIssuersRegistry-addTrustedIssuer}. */ function addTrustedIssuer(IClaimIssuer _trustedIssuer, uint256[] calldata _claimTopics) external override onlyOwner { - require(address(_trustedIssuer) != address(0), "invalid argument - zero address"); + require(address(_trustedIssuer) != address(0), InvalidArgumentLib.ZeroAddress()); require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length == 0, "trusted Issuer already exists"); require(_claimTopics.length > 0, "trusted claim topics cannot be empty"); require(_claimTopics.length <= 15, "cannot have more than 15 claim topics"); @@ -96,7 +96,7 @@ contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, * @dev See {ITrustedIssuersRegistry-removeTrustedIssuer}. */ function removeTrustedIssuer(IClaimIssuer _trustedIssuer) external override onlyOwner { - require(address(_trustedIssuer) != address(0), "invalid argument - zero address"); + require(address(_trustedIssuer) != address(0), InvalidArgumentLib.ZeroAddress()); require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length != 0, "NOT a trusted issuer"); uint256 length = _trustedIssuers.length; for (uint256 i = 0; i < length; i++) { @@ -129,7 +129,7 @@ contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, * @dev See {ITrustedIssuersRegistry-updateIssuerClaimTopics}. */ function updateIssuerClaimTopics(IClaimIssuer _trustedIssuer, uint256[] calldata _claimTopics) external override onlyOwner { - require(address(_trustedIssuer) != address(0), "invalid argument - zero address"); + require(address(_trustedIssuer) != address(0), InvalidArgumentLib.ZeroAddress()); require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length != 0, "NOT a trusted issuer"); require(_claimTopics.length <= 15, "cannot have more than 15 claim topics"); require(_claimTopics.length > 0, "claim topics cannot be empty"); diff --git a/contracts/roles/AgentRole.sol b/contracts/roles/AgentRole.sol index ac25b9e5..cbe11eff 100644 --- a/contracts/roles/AgentRole.sol +++ b/contracts/roles/AgentRole.sol @@ -66,6 +66,7 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts/access/Ownable.sol"; import "./Roles.sol"; +import "../libraries/errors/InvalidArgumentLib.sol"; contract AgentRole is Ownable { using Roles for Roles.Role; @@ -81,13 +82,13 @@ contract AgentRole is Ownable { } function addAgent(address _agent) public onlyOwner { - require(_agent != address(0), "invalid argument - zero address"); + require(_agent != address(0), InvalidArgumentLib.ZeroAddress()); _agents.add(_agent); emit AgentAdded(_agent); } function removeAgent(address _agent) public onlyOwner { - require(_agent != address(0), "invalid argument - zero address"); + require(_agent != address(0), InvalidArgumentLib.ZeroAddress()); _agents.remove(_agent); emit AgentRemoved(_agent); } diff --git a/contracts/roles/AgentRoleUpgradeable.sol b/contracts/roles/AgentRoleUpgradeable.sol index 07c4493b..08df264c 100644 --- a/contracts/roles/AgentRoleUpgradeable.sol +++ b/contracts/roles/AgentRoleUpgradeable.sol @@ -66,6 +66,7 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "./Roles.sol"; +import "../libraries/errors/InvalidArgumentLib.sol"; contract AgentRoleUpgradeable is OwnableUpgradeable { using Roles for Roles.Role; @@ -81,13 +82,13 @@ contract AgentRoleUpgradeable is OwnableUpgradeable { } function addAgent(address _agent) public onlyOwner { - require(_agent != address(0), "invalid argument - zero address"); + require(_agent != address(0), InvalidArgumentLib.ZeroAddress()); _agents.add(_agent); emit AgentAdded(_agent); } function removeAgent(address _agent) public onlyOwner { - require(_agent != address(0), "invalid argument - zero address"); + require(_agent != address(0), InvalidArgumentLib.ZeroAddress()); _agents.remove(_agent); emit AgentRemoved(_agent); } diff --git a/contracts/roles/Roles.sol b/contracts/roles/Roles.sol index 53fb5b48..edca53f2 100644 --- a/contracts/roles/Roles.sol +++ b/contracts/roles/Roles.sol @@ -63,6 +63,9 @@ pragma solidity 0.8.26; +import "../libraries/errors/InvalidArgumentLib.sol"; +import "../libraries/errors/RoleLib.sol"; + /** * @title Roles * @dev Library for managing addresses assigned to a Role. @@ -76,7 +79,7 @@ library Roles { * @dev Give an account access to this role. */ function add(Role storage role, address account) internal { - require(!has(role, account), "Roles: account already has role"); + require(!has(role, account), RoleLib.AccountAlreadyHasRole()); role.bearer[account] = true; } @@ -84,7 +87,7 @@ library Roles { * @dev Remove an account's access to this role. */ function remove(Role storage role, address account) internal { - require(has(role, account), "Roles: account does not have role"); + require(has(role, account), RoleLib.AccountDoesNotHaveRole()); role.bearer[account] = false; } @@ -93,7 +96,7 @@ library Roles { * @return bool */ function has(Role storage role, address account) internal view returns (bool) { - require(account != address(0), "Roles: account is the zero address"); + require(account != address(0), InvalidArgumentLib.ZeroAddress()); return role.bearer[account]; } } diff --git a/contracts/roles/permissioning/agent/AgentManager.sol b/contracts/roles/permissioning/agent/AgentManager.sol index c7644e78..c7c63fdc 100644 --- a/contracts/roles/permissioning/agent/AgentManager.sol +++ b/contracts/roles/permissioning/agent/AgentManager.sol @@ -68,6 +68,7 @@ import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; import "../../../token/IToken.sol"; import "../../../registry/interface/IIdentityRegistry.sol"; import "./AgentRoles.sol"; +import "../../../libraries/errors/RoleLib.sol"; contract AgentManager is AgentRoles { /// @dev the token managed by this AgentManager contract @@ -94,7 +95,7 @@ contract AgentManager is AgentRoles { require( isTransferManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - "Role: Sender is NOT Transfer Manager" + RoleLib.SenderIsNotTransferManager() ); token.forcedTransfer(_from, _to, _amount); } @@ -116,7 +117,7 @@ contract AgentManager is AgentRoles { require( isTransferManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - "Role: Sender is NOT Transfer Manager" + RoleLib.SenderIsNotTransferManager() ); token.batchForcedTransfer(_fromList, _toList, _amounts); } @@ -133,7 +134,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , "Role: Sender is NOT Freezer"); + , RoleLib.SenderIsNotFreezer()); token.pause(); } @@ -149,7 +150,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , "Role: Sender is NOT Freezer"); + , RoleLib.SenderIsNotFreezer()); token.unpause(); } @@ -169,7 +170,7 @@ contract AgentManager is AgentRoles { require( isSupplyModifier(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - "Role: Sender is NOT Supply Modifier" + RoleLib.SenderIsNotSupplyModifier() ); token.mint(_to, _amount); } @@ -190,7 +191,7 @@ contract AgentManager is AgentRoles { require( isSupplyModifier(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - "Role: Sender is NOT Supply Modifier" + RoleLib.SenderIsNotSupplyModifier() ); token.batchMint(_toList, _amounts); } @@ -212,7 +213,7 @@ contract AgentManager is AgentRoles { isSupplyModifier( address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , "Role: Sender is NOT Supply Modifier" + , RoleLib.SenderIsNotSupplyModifier() ); token.burn(_userAddress, _amount); } @@ -233,7 +234,7 @@ contract AgentManager is AgentRoles { require( isSupplyModifier(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , "Role: Sender is NOT Supply Modifier" + , RoleLib.SenderIsNotSupplyModifier() ); token.batchBurn(_userAddresses, _amounts); } @@ -254,7 +255,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , "Role: Sender is NOT Freezer"); + , RoleLib.SenderIsNotFreezer()); token.setAddressFrozen(_userAddress, _freeze); } @@ -274,7 +275,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , "Role: Sender is NOT Freezer"); + , RoleLib.SenderIsNotFreezer()); token.batchSetAddressFrozen(_userAddresses, _freeze); } @@ -294,7 +295,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , "Role: Sender is NOT Freezer"); + , RoleLib.SenderIsNotFreezer()); token.freezePartialTokens(_userAddress, _amount); } @@ -314,7 +315,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , "Role: Sender is NOT Freezer"); + , RoleLib.SenderIsNotFreezer()); token.batchFreezePartialTokens(_userAddresses, _amounts); } @@ -334,7 +335,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , "Role: Sender is NOT Freezer"); + , RoleLib.SenderIsNotFreezer()); token.unfreezePartialTokens(_userAddress, _amount); } @@ -354,7 +355,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , "Role: Sender is NOT Freezer"); + , RoleLib.SenderIsNotFreezer()); token.batchUnfreezePartialTokens(_userAddresses, _amounts); } @@ -375,7 +376,7 @@ contract AgentManager is AgentRoles { require( isRecoveryAgent(address(_managerOnchainID)) && _managerOnchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , "Role: Sender is NOT Recovery Agent" + , RoleLib.SenderIsNotRecoveryAgent() ); token.recoveryAddress(_lostWallet, _newWallet, _onchainID); } @@ -397,7 +398,7 @@ contract AgentManager is AgentRoles { require( isWhiteListManager(address(_managerOnchainID)) && _managerOnchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , "Role: Sender is NOT WhiteList Manager" + , RoleLib.SenderIsNotWhiteListManager() ); token.identityRegistry().registerIdentity(_userAddress, _onchainID, _country); } @@ -418,7 +419,7 @@ contract AgentManager is AgentRoles { require( isWhiteListManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , "Role: Sender is NOT WhiteList Manager" + , RoleLib.SenderIsNotWhiteListManager() ); token.identityRegistry().updateIdentity(_userAddress, _identity); } @@ -439,7 +440,7 @@ contract AgentManager is AgentRoles { require( isWhiteListManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , "Role: Sender is NOT WhiteList Manager" + , RoleLib.SenderIsNotWhiteListManager() ); token.identityRegistry().updateCountry(_userAddress, _country); } @@ -456,7 +457,7 @@ contract AgentManager is AgentRoles { require( isWhiteListManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , "Role: Sender is NOT WhiteList Manager" + , RoleLib.SenderIsNotWhiteListManager() ); token.identityRegistry().deleteIdentity(_userAddress); } diff --git a/contracts/roles/permissioning/agent/AgentRoles.sol b/contracts/roles/permissioning/agent/AgentRoles.sol index 39290a58..f08683b6 100644 --- a/contracts/roles/permissioning/agent/AgentRoles.sol +++ b/contracts/roles/permissioning/agent/AgentRoles.sol @@ -66,6 +66,7 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts/access/Ownable.sol"; import "../../Roles.sol"; +import "../../../libraries/errors/RoleLib.sol"; contract AgentRoles is Ownable { using Roles for Roles.Role; @@ -88,7 +89,7 @@ contract AgentRoles is Ownable { /// modifiers modifier onlyAdmin() { - require(owner() == msg.sender || isAgentAdmin(_msgSender()), "Role: Sender is NOT Admin"); + require(owner() == msg.sender || isAgentAdmin(_msgSender()), RoleLib.SenderIsNotAdmin()); _; } diff --git a/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol b/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol index 4e9014bb..cc709639 100644 --- a/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol +++ b/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol @@ -66,6 +66,7 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../../Roles.sol"; +import "../../../libraries/errors/RoleLib.sol"; contract AgentRolesUpgradeable is OwnableUpgradeable @@ -90,7 +91,7 @@ contract AgentRolesUpgradeable is OwnableUpgradeable /// modifiers modifier onlyAdmin() { - require(owner() == msg.sender || isAgentAdmin(_msgSender()), "Role: Sender is NOT Admin"); + require(owner() == msg.sender || isAgentAdmin(_msgSender()), RoleLib.SenderIsNotAdmin()); _; } diff --git a/contracts/roles/permissioning/owner/OwnerManager.sol b/contracts/roles/permissioning/owner/OwnerManager.sol index a3531631..c748e8fe 100644 --- a/contracts/roles/permissioning/owner/OwnerManager.sol +++ b/contracts/roles/permissioning/owner/OwnerManager.sol @@ -72,6 +72,7 @@ import "./OwnerRoles.sol"; import "../../AgentRole.sol"; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; +import "../../../libraries/errors/RoleLib.sol"; contract OwnerManager is OwnerRoles { /// @dev the token that is managed by this OwnerManager Contract @@ -104,7 +105,7 @@ contract OwnerManager is OwnerRoles { function callSetIdentityRegistry(address _identityRegistry, IIdentity _onchainID) external { require( isRegistryAddressSetter(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - "Role: Sender is NOT Registry Address Setter" + RoleLib.SenderIsNotRegistryAddressSetter() ); token.setIdentityRegistry(_identityRegistry); } @@ -120,7 +121,7 @@ contract OwnerManager is OwnerRoles { function callSetCompliance(address _compliance, IIdentity _onchainID) external { require( isComplianceSetter(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - "Role: Sender is NOT Compliance Setter" + RoleLib.SenderIsNotComplianceSetter() ); token.setCompliance(_compliance); } @@ -135,7 +136,8 @@ contract OwnerManager is OwnerRoles { function callComplianceFunction(bytes calldata callData, IIdentity _onchainID) external { require( isComplianceManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - "Role: Sender is NOT Compliance Manager"); + RoleLib.SenderIsNotComplianceManager() + ); address target = address(token.compliance()); // NOTE: Use assembly to call the interaction instead of a low level @@ -179,7 +181,7 @@ contract OwnerManager is OwnerRoles { function callSetTokenName(string calldata _name, IIdentity _onchainID) external { require( isTokenInfoManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - "Role: Sender is NOT Token Information Manager" + RoleLib.SenderIsNotTokenInformationManager() ); token.setName(_name); } @@ -195,7 +197,7 @@ contract OwnerManager is OwnerRoles { function callSetTokenSymbol(string calldata _symbol, IIdentity _onchainID) external { require( isTokenInfoManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - "Role: Sender is NOT Token Information Manager" + RoleLib.SenderIsNotTokenInformationManager() ); token.setSymbol(_symbol); } @@ -211,7 +213,7 @@ contract OwnerManager is OwnerRoles { function callSetTokenOnchainID(address _tokenOnchainID, IIdentity _onchainID) external { require( isTokenInfoManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - "Role: Sender is NOT Token Information Manager" + RoleLib.SenderIsNotTokenInformationManager() ); token.setOnchainID(_tokenOnchainID); } @@ -227,7 +229,7 @@ contract OwnerManager is OwnerRoles { function callSetClaimTopicsRegistry(address _claimTopicsRegistry, IIdentity _onchainID) external { require( isRegistryAddressSetter(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - "Role: Sender is NOT Registry Address Setter" + RoleLib.SenderIsNotRegistryAddressSetter() ); token.identityRegistry().setClaimTopicsRegistry(_claimTopicsRegistry); } @@ -243,7 +245,7 @@ contract OwnerManager is OwnerRoles { function callSetTrustedIssuersRegistry(address _trustedIssuersRegistry, IIdentity _onchainID) external { require( isRegistryAddressSetter(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - "Role: Sender is NOT Registry Address Setter" + RoleLib.SenderIsNotRegistryAddressSetter() ); token.identityRegistry().setTrustedIssuersRegistry(_trustedIssuersRegistry); } @@ -263,7 +265,7 @@ contract OwnerManager is OwnerRoles { ) external { require( isIssuersRegistryManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - "Role: Sender is NOT IssuersRegistryManager" + RoleLib.SenderIsNotIssuersRegistryManager() ); token.identityRegistry().issuersRegistry().addTrustedIssuer(_trustedIssuer, _claimTopics); } @@ -279,7 +281,7 @@ contract OwnerManager is OwnerRoles { function callRemoveTrustedIssuer(IClaimIssuer _trustedIssuer, IIdentity _onchainID) external { require( isIssuersRegistryManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - "Role: Sender is NOT IssuersRegistryManager" + RoleLib.SenderIsNotIssuersRegistryManager() ); token.identityRegistry().issuersRegistry().removeTrustedIssuer(_trustedIssuer); } @@ -299,7 +301,7 @@ contract OwnerManager is OwnerRoles { ) external { require( isIssuersRegistryManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - "Role: Sender is NOT IssuersRegistryManager" + RoleLib.SenderIsNotIssuersRegistryManager() ); token.identityRegistry().issuersRegistry().updateIssuerClaimTopics(_trustedIssuer, _claimTopics); } @@ -315,7 +317,7 @@ contract OwnerManager is OwnerRoles { function callAddClaimTopic(uint256 _claimTopic, IIdentity _onchainID) external { require( isClaimRegistryManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - "Role: Sender is NOT ClaimRegistryManager" + RoleLib.SenderIsNotClaimRegistryManager() ); token.identityRegistry().topicsRegistry().addClaimTopic(_claimTopic); } @@ -331,7 +333,7 @@ contract OwnerManager is OwnerRoles { function callRemoveClaimTopic(uint256 _claimTopic, IIdentity _onchainID) external { require( isClaimRegistryManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - "Role: Sender is NOT ClaimRegistryManager" + RoleLib.SenderIsNotClaimRegistryManager() ); token.identityRegistry().topicsRegistry().removeClaimTopic(_claimTopic); } diff --git a/contracts/roles/permissioning/owner/OwnerRoles.sol b/contracts/roles/permissioning/owner/OwnerRoles.sol index 7941de24..9560f8a9 100644 --- a/contracts/roles/permissioning/owner/OwnerRoles.sol +++ b/contracts/roles/permissioning/owner/OwnerRoles.sol @@ -66,6 +66,7 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts/access/Ownable.sol"; import "../../Roles.sol"; +import "../../../libraries/errors/RoleLib.sol"; contract OwnerRoles is Ownable { using Roles for Roles.Role; @@ -88,7 +89,7 @@ contract OwnerRoles is Ownable { /// modifiers modifier onlyAdmin() { - require(owner() == msg.sender || isOwnerAdmin(_msgSender()), "Role: Sender is NOT Admin"); + require(owner() == msg.sender || isOwnerAdmin(_msgSender()), RoleLib.SenderIsNotAdmin()); _; } diff --git a/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol b/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol index 7e2a2274..e3782be1 100644 --- a/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol +++ b/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol @@ -66,6 +66,7 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../../Roles.sol"; +import "../../../libraries/errors/RoleLib.sol"; contract OwnerRolesUpgradeable is OwnableUpgradeable @@ -90,7 +91,7 @@ contract OwnerRolesUpgradeable is OwnableUpgradeable /// modifiers modifier onlyAdmin() { - require(owner() == msg.sender || isOwnerAdmin(_msgSender()), "Role: Sender is NOT Admin"); + require(owner() == msg.sender || isOwnerAdmin(_msgSender()), RoleLib.SenderIsNotAdmin()); _; } diff --git a/contracts/token/Token.sol b/contracts/token/Token.sol index ac2057c2..f50dca49 100755 --- a/contracts/token/Token.sol +++ b/contracts/token/Token.sol @@ -67,13 +67,18 @@ import "./IToken.sol"; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; import "./TokenStorage.sol"; import "../roles/AgentRoleUpgradeable.sol"; +import "../libraries/errors/InvalidArgumentLib.sol"; contract Token is IToken, AgentRoleUpgradeable, TokenStorage { + /// errors + error AddressNotAgent(address agent); error AgentNotAuthorized(address agent, string reason); + //error InvalidArgumentEmptyString(); + /// modifiers /// @dev Modifier to make a function callable only when the contract is not paused. @@ -118,11 +123,11 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { require( _identityRegistry != address(0) && _compliance != address(0) - , "invalid argument - zero address"); + , InvalidArgumentLib.ZeroAddress()); require( keccak256(abi.encode(_name)) != keccak256(abi.encode("")) && keccak256(abi.encode(_symbol)) != keccak256(abi.encode("")) - , "invalid argument - empty string"); + , InvalidArgumentLib.EmptyString()); require(0 <= _decimals && _decimals <= 18, "decimals between 0 and 18"); __Ownable_init(); _tokenName = _name; @@ -163,7 +168,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-setName}. */ function setName(string calldata _name) external override onlyOwner { - require(keccak256(abi.encode(_name)) != keccak256(abi.encode("")), "invalid argument - empty string"); + require(keccak256(abi.encode(_name)) != keccak256(abi.encode("")), InvalidArgumentLib.EmptyString()); _tokenName = _name; emit UpdatedTokenInformation(_tokenName, _tokenSymbol, _tokenDecimals, _TOKEN_VERSION, _tokenOnchainID); } @@ -172,7 +177,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-setSymbol}. */ function setSymbol(string calldata _symbol) external override onlyOwner { - require(keccak256(abi.encode(_symbol)) != keccak256(abi.encode("")), "invalid argument - empty string"); + require(keccak256(abi.encode(_symbol)) != keccak256(abi.encode("")), InvalidArgumentLib.EmptyString()); _tokenSymbol = _symbol; emit UpdatedTokenInformation(_tokenName, _tokenSymbol, _tokenDecimals, _TOKEN_VERSION, _tokenOnchainID); } diff --git a/hardhat.config.ts b/hardhat.config.ts index cfeeda44..e86b1ea8 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -14,6 +14,7 @@ const config: HardhatUserConfig = { enabled: true, runs: 200, }, + viaIR: true }, }, gasReporter: { diff --git a/test/agentManager.test.ts b/test/agentManager.test.ts index 6c9839c4..685b9b95 100644 --- a/test/agentManager.test.ts +++ b/test/agentManager.test.ts @@ -2,6 +2,7 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { expect } from 'chai'; import { ethers } from 'hardhat'; import { deployFullSuiteFixture } from './fixtures/deploy-full-suite.fixture'; +import { agent } from '../typechain-types/contracts/roles/permissioning'; describe('AgentManager', () => { describe('.callForceTransfer', () => { @@ -15,7 +16,7 @@ describe('AgentManager', () => { await expect( agentManager.connect(aliceWallet).callForcedTransfer(aliceWallet.address, bobWallet.address, 200, aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT Transfer Manager'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotTransferManager'); }); }); @@ -31,7 +32,7 @@ describe('AgentManager', () => { await expect( agentManager.connect(anotherWallet).callForcedTransfer(aliceWallet.address, bobWallet.address, 200, aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT Transfer Manager'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotTransferManager'); }); }); @@ -72,7 +73,7 @@ describe('AgentManager', () => { [200, 200], aliceIdentity.target, ), - ).to.be.revertedWith('Role: Sender is NOT Transfer Manager'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotTransferManager'); }); }); @@ -95,7 +96,7 @@ describe('AgentManager', () => { [200, 200], aliceIdentity.target, ), - ).to.be.revertedWith('Role: Sender is NOT Transfer Manager'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotTransferManager'); }); }); @@ -133,7 +134,7 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callPause(aliceIdentity.target)).to.be.revertedWith('Role: Sender is NOT Freezer'); + await expect(agentManager.connect(aliceWallet).callPause(aliceIdentity.target)).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); }); }); @@ -147,7 +148,7 @@ describe('AgentManager', () => { await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - await expect(agentManager.connect(anotherWallet).callPause(aliceIdentity.target)).to.be.revertedWith('Role: Sender is NOT Freezer'); + await expect(agentManager.connect(anotherWallet).callPause(aliceIdentity.target)).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); }); }); @@ -178,7 +179,7 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callUnpause(aliceIdentity.target)).to.be.revertedWith('Role: Sender is NOT Freezer'); + await expect(agentManager.connect(aliceWallet).callUnpause(aliceIdentity.target)).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); }); }); @@ -192,7 +193,7 @@ describe('AgentManager', () => { await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - await expect(agentManager.connect(anotherWallet).callUnpause(aliceIdentity.target)).to.be.revertedWith('Role: Sender is NOT Freezer'); + await expect(agentManager.connect(anotherWallet).callUnpause(aliceIdentity.target)).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); }); }); @@ -224,8 +225,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callMint(bobWallet.address, 1000, aliceIdentity.target)).to.be.revertedWith( - 'Role: Sender is NOT Supply Modifier', + await expect(agentManager.connect(aliceWallet).callMint(bobWallet.address, 1000, aliceIdentity.target)).to.be.revertedWithCustomError( + agentManager, + 'SenderIsNotSupplyModifier', ); }); }); @@ -240,8 +242,9 @@ describe('AgentManager', () => { await agentManager.connect(tokenAdmin).addSupplyModifier(aliceIdentity.target); - await expect(agentManager.connect(anotherWallet).callMint(bobWallet.address, 1000, aliceIdentity.target)).to.be.revertedWith( - 'Role: Sender is NOT Supply Modifier', + await expect(agentManager.connect(anotherWallet).callMint(bobWallet.address, 1000, aliceIdentity.target)).to.be.revertedWithCustomError( + agentManager, + 'SenderIsNotSupplyModifier', ); }); }); @@ -274,7 +277,7 @@ describe('AgentManager', () => { await expect( agentManager.connect(aliceWallet).callBatchMint([bobWallet.address, aliceWallet.address], [1000, 500], aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT Supply Modifier'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotSupplyModifier'); }); }); @@ -290,7 +293,7 @@ describe('AgentManager', () => { await expect( agentManager.connect(anotherWallet).callBatchMint([bobWallet.address, aliceWallet.address], [1000, 500], aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT Supply Modifier'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotSupplyModifier'); }); }); @@ -323,8 +326,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callBurn(bobWallet.address, 1000, aliceIdentity.target)).to.be.revertedWith( - 'Role: Sender is NOT Supply Modifier', + await expect(agentManager.connect(aliceWallet).callBurn(bobWallet.address, 1000, aliceIdentity.target)).to.be.revertedWithCustomError( + agentManager, + 'SenderIsNotSupplyModifier', ); }); }); @@ -339,8 +343,9 @@ describe('AgentManager', () => { await agentManager.connect(tokenAdmin).addSupplyModifier(bobIdentity.target); - await expect(agentManager.connect(anotherWallet).callBurn(bobWallet.address, 200, bobIdentity.target)).to.be.revertedWith( - 'Role: Sender is NOT Supply Modifier', + await expect(agentManager.connect(anotherWallet).callBurn(bobWallet.address, 200, bobIdentity.target)).to.be.revertedWithCustomError( + agentManager, + 'SenderIsNotSupplyModifier', ); }); }); @@ -373,7 +378,7 @@ describe('AgentManager', () => { await expect( agentManager.connect(aliceWallet).callBatchBurn([bobWallet.address, aliceWallet.address], [500, 1000], aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT Supply Modifier'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotSupplyModifier'); }); }); @@ -389,7 +394,7 @@ describe('AgentManager', () => { await expect( agentManager.connect(anotherWallet).callBatchBurn([bobWallet.address, aliceWallet.address], [500, 100], aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT Supply Modifier'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotSupplyModifier'); }); }); @@ -422,8 +427,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callSetAddressFrozen(aliceIdentity.target, true, aliceIdentity.target)).to.be.revertedWith( - 'Role: Sender is NOT Freezer', + await expect(agentManager.connect(aliceWallet).callSetAddressFrozen(aliceIdentity.target, true, aliceIdentity.target)).to.be.revertedWithCustomError( + agentManager, + 'SenderIsNotFreezer', ); }); }); @@ -438,8 +444,9 @@ describe('AgentManager', () => { await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - await expect(agentManager.connect(anotherWallet).callSetAddressFrozen(aliceIdentity.target, true, aliceIdentity.target)).to.be.revertedWith( - 'Role: Sender is NOT Freezer', + await expect(agentManager.connect(anotherWallet).callSetAddressFrozen(aliceIdentity.target, true, aliceIdentity.target)).to.be.revertedWithCustomError( + agentManager, + 'SenderIsNotFreezer', ); }); }); @@ -473,7 +480,7 @@ describe('AgentManager', () => { await expect( agentManager.connect(aliceWallet).callBatchSetAddressFrozen([aliceIdentity.target, bobWallet.address], [true, false], aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT Freezer'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); }); }); @@ -491,7 +498,7 @@ describe('AgentManager', () => { agentManager .connect(anotherWallet) .callBatchSetAddressFrozen([aliceIdentity.target, bobWallet.address], [true, false], aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT Freezer'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); }); }); @@ -524,8 +531,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callFreezePartialTokens(aliceIdentity.target, 100, aliceIdentity.target)).to.be.revertedWith( - 'Role: Sender is NOT Freezer', + await expect(agentManager.connect(aliceWallet).callFreezePartialTokens(aliceIdentity.target, 100, aliceIdentity.target)).to.be.revertedWithCustomError( + agentManager, + 'SenderIsNotFreezer', ); }); }); @@ -540,8 +548,9 @@ describe('AgentManager', () => { await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - await expect(agentManager.connect(anotherWallet).callFreezePartialTokens(aliceIdentity.target, 100, aliceIdentity.target)).to.be.revertedWith( - 'Role: Sender is NOT Freezer', + await expect(agentManager.connect(anotherWallet).callFreezePartialTokens(aliceIdentity.target, 100, aliceIdentity.target)).to.be.revertedWithCustomError( + agentManager, + 'SenderIsNotFreezer', ); }); }); @@ -574,7 +583,7 @@ describe('AgentManager', () => { await expect( agentManager.connect(aliceWallet).callBatchFreezePartialTokens([aliceWallet.address, bobWallet.address], [100, 200], aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT Freezer'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); }); }); @@ -592,7 +601,7 @@ describe('AgentManager', () => { agentManager .connect(anotherWallet) .callBatchFreezePartialTokens([aliceWallet.address, bobWallet.address], [100, 200], aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT Freezer'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); }); }); @@ -625,8 +634,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callUnfreezePartialTokens(aliceIdentity.target, 100, aliceIdentity.target)).to.be.revertedWith( - 'Role: Sender is NOT Freezer', + await expect(agentManager.connect(aliceWallet).callUnfreezePartialTokens(aliceIdentity.target, 100, aliceIdentity.target)).to.be.revertedWithCustomError( + agentManager, + 'SenderIsNotFreezer', ); }); }); @@ -643,7 +653,7 @@ describe('AgentManager', () => { await expect( agentManager.connect(anotherWallet).callUnfreezePartialTokens(aliceIdentity.target, 100, aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT Freezer'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); }); }); @@ -679,7 +689,7 @@ describe('AgentManager', () => { agentManager .connect(aliceWallet) .callBatchUnfreezePartialTokens([aliceWallet.address, bobWallet.address], [100, 200], aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT Freezer'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); }); }); @@ -697,7 +707,7 @@ describe('AgentManager', () => { agentManager .connect(anotherWallet) .callBatchUnfreezePartialTokens([aliceWallet.address, bobWallet.address], [100, 200], aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT Freezer'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); }); }); @@ -734,7 +744,7 @@ describe('AgentManager', () => { await expect( agentManager.connect(aliceWallet).callRecoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target, aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT Recovery Agent'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotRecoveryAgent'); }); }); @@ -750,7 +760,7 @@ describe('AgentManager', () => { await expect( agentManager.connect(anotherWallet).callRecoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target, aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT Recovery Agent'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotRecoveryAgent'); }); }); @@ -787,7 +797,7 @@ describe('AgentManager', () => { await expect( agentManager.connect(aliceWallet).callRegisterIdentity(bobWallet.address, bobIdentity.target, 42, aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT WhiteList Manager'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotWhiteListManager'); }); }); @@ -803,7 +813,7 @@ describe('AgentManager', () => { await expect( agentManager.connect(bobWallet).callRegisterIdentity(bobWallet.address, bobIdentity.target, 42, aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT WhiteList Manager'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotWhiteListManager'); }); }); @@ -839,7 +849,7 @@ describe('AgentManager', () => { await expect( agentManager.connect(aliceWallet).callUpdateIdentity(bobWallet.address, bobIdentity.target, aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT WhiteList Manager'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotWhiteListManager'); }); }); @@ -855,7 +865,7 @@ describe('AgentManager', () => { await expect( agentManager.connect(bobWallet).callUpdateIdentity(bobWallet.address, bobIdentity.target, aliceIdentity.target), - ).to.be.revertedWith('Role: Sender is NOT WhiteList Manager'); + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotWhiteListManager'); }); }); @@ -885,8 +895,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callUpdateCountry(bobWallet.address, 100, aliceIdentity.target)).to.be.revertedWith( - 'Role: Sender is NOT WhiteList Manager', + await expect(agentManager.connect(aliceWallet).callUpdateCountry(bobWallet.address, 100, aliceIdentity.target)).to.be.revertedWithCustomError( + agentManager, + 'SenderIsNotWhiteListManager', ); }); }); @@ -901,8 +912,9 @@ describe('AgentManager', () => { await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.target); - await expect(agentManager.connect(bobWallet).callUpdateCountry(bobWallet.address, 100, aliceIdentity.target)).to.be.revertedWith( - 'Role: Sender is NOT WhiteList Manager', + await expect(agentManager.connect(bobWallet).callUpdateCountry(bobWallet.address, 100, aliceIdentity.target)).to.be.revertedWithCustomError( + agentManager, + 'SenderIsNotWhiteListManager', ); }); }); @@ -933,8 +945,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callDeleteIdentity(bobWallet.address, aliceIdentity.target)).to.be.revertedWith( - 'Role: Sender is NOT WhiteList Manager', + await expect(agentManager.connect(aliceWallet).callDeleteIdentity(bobWallet.address, aliceIdentity.target)).to.be.revertedWithCustomError( + agentManager, + 'SenderIsNotWhiteListManager', ); }); }); @@ -949,8 +962,9 @@ describe('AgentManager', () => { await agentManager.connect(tokenAdmin).addWhiteListManager(aliceIdentity.target); - await expect(agentManager.connect(bobWallet).callDeleteIdentity(bobWallet.address, aliceIdentity.target)).to.be.revertedWith( - 'Role: Sender is NOT WhiteList Manager', + await expect(agentManager.connect(bobWallet).callDeleteIdentity(bobWallet.address, aliceIdentity.target)).to.be.revertedWithCustomError( + agentManager, + 'SenderIsNotWhiteListManager', ); }); }); diff --git a/test/agentRole.test.ts b/test/agentRole.test.ts index b1dc465d..8c3a482e 100644 --- a/test/agentRole.test.ts +++ b/test/agentRole.test.ts @@ -40,7 +40,7 @@ describe('AgentRole', () => { contracts: { agentRole }, } = await loadFixture(deployAgentFixture); - await expect(agentRole.connect(ownerWallet).addAgent(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); + await expect(agentRole.connect(ownerWallet).addAgent(ethers.ZeroAddress)).to.be.revertedWithCustomError(agentRole, 'ZeroAddress'); }); }); @@ -53,7 +53,7 @@ describe('AgentRole', () => { } = await loadFixture(deployAgentFixture); await agentRole.connect(ownerWallet).addAgent(aliceWallet.address); - await expect(agentRole.connect(ownerWallet).addAgent(aliceWallet.address)).to.be.revertedWith('Roles: account already has role'); + await expect(agentRole.connect(ownerWallet).addAgent(aliceWallet.address)).to.be.revertedWithCustomError(agentRole, 'AccountAlreadyHasRole'); }); }); @@ -93,7 +93,7 @@ describe('AgentRole', () => { contracts: { agentRole }, } = await loadFixture(deployAgentFixture); - await expect(agentRole.connect(ownerWallet).removeAgent(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); + await expect(agentRole.connect(ownerWallet).removeAgent(ethers.ZeroAddress)).to.be.revertedWithCustomError(agentRole, 'ZeroAddress'); }); }); @@ -105,7 +105,7 @@ describe('AgentRole', () => { contracts: { agentRole }, } = await loadFixture(deployAgentFixture); - await expect(agentRole.connect(ownerWallet).removeAgent(aliceWallet.address)).to.be.revertedWith('Roles: account does not have role'); + await expect(agentRole.connect(ownerWallet).removeAgent(aliceWallet.address)).to.be.revertedWithCustomError(agentRole, 'AccountDoesNotHaveRole'); }); }); diff --git a/test/authorities/trex-implementation-authority.test.ts b/test/authorities/trex-implementation-authority.test.ts index cb5dc35b..f79dabf2 100644 --- a/test/authorities/trex-implementation-authority.test.ts +++ b/test/authorities/trex-implementation-authority.test.ts @@ -3,6 +3,7 @@ import { expect } from 'chai'; import { ethers } from 'hardhat'; import { deployFullSuiteFixture } from '../fixtures/deploy-full-suite.fixture'; +import { compliance } from '../../typechain-types/contracts'; describe('TrexImplementationAuthority', () => { describe('.setTREXFactory()', () => { @@ -307,8 +308,9 @@ describe('TrexImplementationAuthority', () => { mcImplementation: implementations.modularComplianceImplementation.target, }; - await expect(trexImplementationAuthority.addTREXVersion(versionStruct, contractsStruct)).to.be.revertedWith( - 'invalid argument - zero address', + await expect(trexImplementationAuthority.addTREXVersion(versionStruct, contractsStruct)).to.be.revertedWithCustomError( + trexImplementationAuthority, + 'ZeroAddress' ); }); }); @@ -379,8 +381,9 @@ describe('TrexImplementationAuthority', () => { authorities: { trexImplementationAuthority }, } = await loadFixture(deployFullSuiteFixture); - await expect(trexImplementationAuthority.changeImplementationAuthority(ethers.ZeroAddress, anotherWallet.address)).to.be.revertedWith( - 'invalid argument - zero address', + await expect(trexImplementationAuthority.changeImplementationAuthority(ethers.ZeroAddress, anotherWallet.address)).to.be.revertedWithCustomError( + trexImplementationAuthority, + 'ZeroAddress' ); }); }); diff --git a/test/compliance.test.ts b/test/compliance.test.ts index fef5f9a5..d904e53f 100644 --- a/test/compliance.test.ts +++ b/test/compliance.test.ts @@ -76,7 +76,7 @@ describe('ModularCompliance', () => { const compliance = await ethers.deployContract('ModularCompliance', deployer); await compliance.init(); - await expect(compliance.bindToken(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); + await expect(compliance.bindToken(ethers.ZeroAddress)).to.be.revertedWithCustomError(compliance, 'ZeroAddress'); }); }); }); @@ -101,7 +101,7 @@ describe('ModularCompliance', () => { suite: { compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.unbindToken(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); + await expect(compliance.unbindToken(ethers.ZeroAddress)).to.be.revertedWithCustomError(compliance, 'ZeroAddress'); }); }); @@ -157,7 +157,7 @@ describe('ModularCompliance', () => { suite: { compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.addModule(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); + await expect(compliance.addModule(ethers.ZeroAddress)).to.be.revertedWithCustomError(compliance, 'ZeroAddress'); }); }); @@ -259,7 +259,7 @@ describe('ModularCompliance', () => { suite: { compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.removeModule(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); + await expect(compliance.removeModule(ethers.ZeroAddress)).to.be.revertedWithCustomError(compliance, 'ZeroAddress'); }); }); @@ -319,8 +319,9 @@ describe('ModularCompliance', () => { accounts: { bobWallet, charlieWallet }, } = await loadFixture(deploySuiteWithModuleComplianceBoundToWallet); - await expect(compliance.connect(charlieWallet).transferred(ethers.ZeroAddress, bobWallet.address, 10)).to.be.revertedWith( - 'invalid argument - zero address', + await expect(compliance.connect(charlieWallet).transferred(ethers.ZeroAddress, bobWallet.address, 10)).to.be.revertedWithCustomError( + compliance, + 'ZeroAddress' ); }); }); @@ -332,8 +333,9 @@ describe('ModularCompliance', () => { accounts: { charlieWallet, aliceWallet }, } = await loadFixture(deploySuiteWithModuleComplianceBoundToWallet); - await expect(compliance.connect(charlieWallet).transferred(aliceWallet.address, ethers.ZeroAddress, 10)).to.be.revertedWith( - 'invalid argument - zero address', + await expect(compliance.connect(charlieWallet).transferred(aliceWallet.address, ethers.ZeroAddress, 10)).to.be.revertedWithCustomError( + compliance, + 'ZeroAddress' ); }); }); @@ -386,7 +388,7 @@ describe('ModularCompliance', () => { accounts: { charlieWallet }, } = await loadFixture(deploySuiteWithModuleComplianceBoundToWallet); - await expect(compliance.connect(charlieWallet).created(ethers.ZeroAddress, 10)).to.be.revertedWith('invalid argument - zero address'); + await expect(compliance.connect(charlieWallet).created(ethers.ZeroAddress, 10)).to.be.revertedWithCustomError(compliance, 'ZeroAddress'); }); }); @@ -436,7 +438,7 @@ describe('ModularCompliance', () => { accounts: { charlieWallet }, } = await loadFixture(deploySuiteWithModuleComplianceBoundToWallet); - await expect(compliance.connect(charlieWallet).destroyed(ethers.ZeroAddress, 10)).to.be.revertedWith('invalid argument - zero address'); + await expect(compliance.connect(charlieWallet).destroyed(ethers.ZeroAddress, 10)).to.be.revertedWithCustomError(compliance, 'ZeroAddress'); }); }); diff --git a/test/factory.test.ts b/test/factory.test.ts index e126a847..4f1aa31e 100644 --- a/test/factory.test.ts +++ b/test/factory.test.ts @@ -383,7 +383,7 @@ describe('TREXFactory', () => { factories: { trexFactory }, } = await loadFixture(deployFullSuiteFixture); - await expect(trexFactory.connect(deployer).setIdFactory(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); + await expect(trexFactory.connect(deployer).setIdFactory(ethers.ZeroAddress)).to.be.revertedWithCustomError(trexFactory, 'ZeroAddress'); }); }); describe('when try to input a valid address', () => { diff --git a/test/gateway.test.ts b/test/gateway.test.ts index 24b962af..b2d27553 100644 --- a/test/gateway.test.ts +++ b/test/gateway.test.ts @@ -209,7 +209,7 @@ describe('TREXGateway', () => { await expect( gateway.connect(context.accounts.anotherWallet).addDeployer(context.accounts.anotherWallet.address), - ).to.be.revertedWithCustomError(gateway, 'OnlyAdminCall'); + ).to.be.revertedWithCustomError(gateway, 'SenderIsNotAdmin'); }); }); describe('when called by owner', () => { @@ -280,7 +280,7 @@ describe('TREXGateway', () => { await expect( gateway.connect(context.accounts.anotherWallet).batchAddDeployer([context.accounts.anotherWallet.address]), - ).to.be.revertedWithCustomError(gateway, 'OnlyAdminCall'); + ).to.be.revertedWithCustomError(gateway, 'SenderIsNotAdmin'); }); }); describe('when called by owner', () => { @@ -402,7 +402,7 @@ describe('TREXGateway', () => { await expect( gateway.connect(context.accounts.anotherWallet).removeDeployer(context.accounts.anotherWallet.address), - ).to.be.revertedWithCustomError(gateway, 'OnlyAdminCall'); + ).to.be.revertedWithCustomError(gateway, 'SenderIsNotAdmin'); }); }); describe('when called by owner', () => { @@ -442,7 +442,7 @@ describe('TREXGateway', () => { await expect( gateway.connect(context.accounts.anotherWallet).batchRemoveDeployer([context.accounts.anotherWallet.address]), - ).to.be.revertedWithCustomError(gateway, 'OnlyAdminCall'); + ).to.be.revertedWithCustomError(gateway, 'SenderIsNotAdmin'); }); }); describe('when called by owner', () => { @@ -538,7 +538,7 @@ describe('TREXGateway', () => { await expect( gateway.connect(context.accounts.anotherWallet).applyFeeDiscount(context.accounts.anotherWallet.address, 5000), - ).to.be.revertedWithCustomError(gateway, 'OnlyAdminCall'); + ).to.be.revertedWithCustomError(gateway, 'SenderIsNotAdmin'); }); }); describe('when called by owner', () => { @@ -581,7 +581,7 @@ describe('TREXGateway', () => { await expect( gateway.connect(context.accounts.anotherWallet).batchApplyFeeDiscount([context.accounts.anotherWallet.address], [5000]), - ).to.be.revertedWithCustomError(gateway, 'OnlyAdminCall'); + ).to.be.revertedWithCustomError(gateway, 'SenderIsNotAdmin'); }); }); describe('when called by owner', () => { diff --git a/test/registries/identity-registry-storage.test.ts b/test/registries/identity-registry-storage.test.ts index d08fa54a..78317de4 100644 --- a/test/registries/identity-registry-storage.test.ts +++ b/test/registries/identity-registry-storage.test.ts @@ -43,7 +43,7 @@ describe('IdentityRegistryStorage', () => { await expect( identityRegistryStorage.connect(tokenAgent).addIdentityToStorage(charlieWallet.address, ethers.ZeroAddress, 42), - ).to.be.revertedWith('invalid argument - zero address'); + ).to.be.revertedWithCustomError(identityRegistryStorage, 'ZeroAddress'); }); }); @@ -59,7 +59,7 @@ describe('IdentityRegistryStorage', () => { await expect( identityRegistryStorage.connect(tokenAgent).addIdentityToStorage(ethers.ZeroAddress, charlieIdentity.target, 42), - ).to.be.revertedWith('invalid argument - zero address'); + ).to.be.revertedWithCustomError(identityRegistryStorage, 'ZeroAddress'); }); }); @@ -108,7 +108,7 @@ describe('IdentityRegistryStorage', () => { await expect( identityRegistryStorage.connect(tokenAgent).modifyStoredIdentity(charlieWallet.address, ethers.ZeroAddress), - ).to.be.revertedWith('invalid argument - zero address'); + ).to.be.revertedWithCustomError(identityRegistryStorage, 'ZeroAddress'); }); }); @@ -124,7 +124,7 @@ describe('IdentityRegistryStorage', () => { await expect( identityRegistryStorage.connect(tokenAgent).modifyStoredIdentity(ethers.ZeroAddress, charlieIdentity.target), - ).to.be.revertedWith('invalid argument - zero address'); + ).to.be.revertedWithCustomError(identityRegistryStorage, 'ZeroAddress'); }); }); @@ -170,8 +170,9 @@ describe('IdentityRegistryStorage', () => { await identityRegistryStorage.addAgent(tokenAgent.address); - await expect(identityRegistryStorage.connect(tokenAgent).modifyStoredInvestorCountry(ethers.ZeroAddress, 42)).to.be.revertedWith( - 'invalid argument - zero address', + await expect(identityRegistryStorage.connect(tokenAgent).modifyStoredInvestorCountry(ethers.ZeroAddress, 42)).to.be.revertedWithCustomError( + identityRegistryStorage, + 'ZeroAddress', ); }); }); @@ -217,8 +218,9 @@ describe('IdentityRegistryStorage', () => { await identityRegistryStorage.addAgent(tokenAgent.address); - await expect(identityRegistryStorage.connect(tokenAgent).removeIdentityFromStorage(ethers.ZeroAddress)).to.be.revertedWith( - 'invalid argument - zero address', + await expect(identityRegistryStorage.connect(tokenAgent).removeIdentityFromStorage(ethers.ZeroAddress)).to.be.revertedWithCustomError( + identityRegistryStorage, + 'ZeroAddress', ); }); }); @@ -263,8 +265,9 @@ describe('IdentityRegistryStorage', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistryStorage.connect(deployer).bindIdentityRegistry(ethers.ZeroAddress)).to.be.revertedWith( - 'invalid argument - zero address', + await expect(identityRegistryStorage.connect(deployer).bindIdentityRegistry(ethers.ZeroAddress)).to.be.revertedWithCustomError( + identityRegistryStorage, + 'ZeroAddress', ); }); }); @@ -312,8 +315,9 @@ describe('IdentityRegistryStorage', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistryStorage.connect(deployer).unbindIdentityRegistry(ethers.ZeroAddress)).to.be.revertedWith( - 'invalid argument - zero address', + await expect(identityRegistryStorage.connect(deployer).unbindIdentityRegistry(ethers.ZeroAddress)).to.be.revertedWithCustomError( + identityRegistryStorage, + 'ZeroAddress', ); }); }); diff --git a/test/registries/identity-registry.test.ts b/test/registries/identity-registry.test.ts index 304697a1..91d1e6e0 100644 --- a/test/registries/identity-registry.test.ts +++ b/test/registries/identity-registry.test.ts @@ -19,19 +19,19 @@ describe('IdentityRegistry', () => { it('should reject zero address for Trusted Issuers Registry', async () => { const identityRegistry = await ethers.deployContract('IdentityRegistry'); const address = ethers.Wallet.createRandom().address; - await expect(identityRegistry.init(ethers.ZeroAddress, address, address)).to.be.revertedWith('invalid argument - zero address'); + await expect(identityRegistry.init(ethers.ZeroAddress, address, address)).to.be.revertedWithCustomError(identityRegistry, 'ZeroAddress'); }); it('should reject zero address for Claim Topics Registry', async () => { const identityRegistry = await ethers.deployContract('IdentityRegistry'); const address = ethers.Wallet.createRandom().address; - await expect(identityRegistry.init(address, ethers.ZeroAddress, address)).to.be.revertedWith('invalid argument - zero address'); + await expect(identityRegistry.init(address, ethers.ZeroAddress, address)).to.be.revertedWithCustomError(identityRegistry, 'ZeroAddress'); }); it('should reject zero address for Identity Storage', async () => { const identityRegistry = await ethers.deployContract('IdentityRegistry'); const address = ethers.Wallet.createRandom().address; - await expect(identityRegistry.init(address, address, ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); + await expect(identityRegistry.init(address, address, ethers.ZeroAddress)).to.be.revertedWithCustomError(identityRegistry, 'ZeroAddress'); }); }); diff --git a/test/registries/trusted-issuers-registry.test.ts b/test/registries/trusted-issuers-registry.test.ts index 1f523087..7431daf2 100644 --- a/test/registries/trusted-issuers-registry.test.ts +++ b/test/registries/trusted-issuers-registry.test.ts @@ -26,8 +26,9 @@ describe('TrustedIssuersRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect(trustedIssuersRegistry.connect(deployer).addTrustedIssuer(ethers.ZeroAddress, [10])).to.be.revertedWith( - 'invalid argument - zero address', + await expect(trustedIssuersRegistry.connect(deployer).addTrustedIssuer(ethers.ZeroAddress, [10])).to.be.revertedWithCustomError( + trustedIssuersRegistry, + 'ZeroAddress', ); }); }); @@ -121,8 +122,9 @@ describe('TrustedIssuersRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect(trustedIssuersRegistry.connect(deployer).removeTrustedIssuer(ethers.ZeroAddress)).to.be.revertedWith( - 'invalid argument - zero address', + await expect(trustedIssuersRegistry.connect(deployer).removeTrustedIssuer(ethers.ZeroAddress)).to.be.revertedWithCustomError( + trustedIssuersRegistry, + 'ZeroAddress' ); }); }); @@ -187,8 +189,9 @@ describe('TrustedIssuersRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect(trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(ethers.ZeroAddress, [10])).to.be.revertedWith( - 'invalid argument - zero address', + await expect(trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(ethers.ZeroAddress, [10])).to.be.revertedWithCustomError( + trustedIssuersRegistry, + 'ZeroAddress' ); }); }); diff --git a/test/token/token-information.test.ts b/test/token/token-information.test.ts index ee23ecca..105a289f 100644 --- a/test/token/token-information.test.ts +++ b/test/token/token-information.test.ts @@ -21,7 +21,7 @@ describe('Token - Information', () => { const { suite: { token }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.setName('')).to.be.revertedWith('invalid argument - empty string'); + await expect(token.setName('')).to.be.revertedWithCustomError(token, 'EmptyString'); }); }); @@ -55,7 +55,7 @@ describe('Token - Information', () => { const { suite: { token }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.setSymbol('')).to.be.revertedWith('invalid argument - empty string'); + await expect(token.setSymbol('')).to.be.revertedWithCustomError(token, 'EmptyString'); }); }); From 0a47bb7b6f8468e034c95021450aa01bc4007987 Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Wed, 3 Jul 2024 11:50:50 +0200 Subject: [PATCH 24/55] =?UTF-8?q?=E2=99=BB()=20TREX-132=20Custom=20Errors?= =?UTF-8?q?=20contd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .solhint.json | 2 +- contracts/DVD/DVDTransferManager.sol | 65 ++++-- .../compliance/modular/ModularCompliance.sol | 53 ++--- .../modular/modules/AbstractModule.sol | 11 +- .../modules/AbstractModuleUpgradeable.sol | 12 +- .../modules/ConditionalTransferModule.sol | 6 +- .../modular/modules/CountryRestrictModule.sol | 21 +- .../modular/modules/MaxBalanceModule.sol | 4 +- .../modular/modules/TransferFeesModule.sol | 6 +- contracts/libraries/errors/CommonLib.sol | 120 +++++++++++ contracts/libraries/errors/ComplianceLib.sol | 79 +++++++ .../libraries/errors/InvalidArgumentLib.sol | 10 + contracts/libraries/errors/RoleLib.sol | 2 + contracts/proxy/AbstractProxy.sol | 8 +- contracts/proxy/ClaimTopicsRegistryProxy.sol | 6 +- contracts/proxy/IdentityRegistryProxy.sol | 3 +- .../proxy/IdentityRegistryStorageProxy.sol | 3 +- contracts/proxy/ModularComplianceProxy.sol | 7 +- contracts/proxy/TokenProxy.sol | 5 +- .../proxy/TrustedIssuersRegistryProxy.sol | 4 +- .../authority/TREXImplementationAuthority.sol | 41 +++- .../implementation/ClaimTopicsRegistry.sol | 11 +- .../IdentityRegistryStorage.sol | 23 +- .../implementation/TrustedIssuersRegistry.sol | 36 +++- contracts/roles/AgentRole.sol | 3 +- contracts/roles/AgentRoleUpgradeable.sol | 3 +- contracts/token/Token.sol | 43 ++-- package-lock.json | 197 ++++++------------ package.json | 2 +- .../trex-implementation-authority.test.ts | 24 ++- test/compliance.test.ts | 45 ++-- .../module-conditional-transfer.test.ts | 16 +- test/compliances/module-country-allow.test.ts | 21 +- .../module-country-restrict.test.ts | 43 ++-- .../module-exchange-monthly-limits.test.ts | 19 +- test/compliances/module-max-balance.test.ts | 10 +- test/compliances/module-supply-limit.test.ts | 14 +- .../module-time-exchange-limits.test.ts | 17 +- .../module-time-transfer-limits.test.ts | 17 +- test/compliances/module-transfer-fees.test.ts | 17 +- .../module-transfer-restrict.test.ts | 32 +-- test/dva.test.ts | 4 +- test/dvd.test.ts | 52 ++--- test/registries/claim-topics-registry.test.ts | 4 +- .../identity-registry-storage.test.ts | 38 ++-- test/registries/identity-registry.test.ts | 20 +- .../trusted-issuers-registry.test.ts | 42 ++-- test/token/token-information.test.ts | 23 +- test/token/token-recovery.test.ts | 15 +- test/token/token-transfer.test.ts | 56 ++--- 50 files changed, 831 insertions(+), 484 deletions(-) create mode 100644 contracts/libraries/errors/CommonLib.sol create mode 100644 contracts/libraries/errors/ComplianceLib.sol diff --git a/.solhint.json b/.solhint.json index aa649c29..826a2bcb 100644 --- a/.solhint.json +++ b/.solhint.json @@ -1,7 +1,7 @@ { "extends": "solhint:recommended", "rules": { - "compiler-version": ["error", "^0.8.17"], + "compiler-version": ["error", "^0.8.26"], "func-visibility": ["warn", { "ignoreConstructors": true }], "reentrancy": "error", "state-visibility": "error", diff --git a/contracts/DVD/DVDTransferManager.sol b/contracts/DVD/DVDTransferManager.sol index 0cc5f657..35c5642b 100644 --- a/contracts/DVD/DVDTransferManager.sol +++ b/contracts/DVD/DVDTransferManager.sol @@ -70,10 +70,16 @@ pragma solidity 0.8.26; import "../roles/AgentRole.sol"; import "../token/IToken.sol"; +import "../libraries/errors/CommonLib.sol"; +import "../libraries/errors/InvalidArgumentLib.sol"; contract DVDTransferManager is Ownable { + /// Errors + + error FeeWalletCannotBeZeroAddress(uint256 walletIndex); + /// Types struct Delivery { @@ -155,6 +161,16 @@ contract DVDTransferManager is Ownable { address fee1Wallet, address fee2Wallet); + /// Errors + + error InvalidFeeSettings(); + + error TransferIDDoesNotExist(); + + error TransferOnlyByCounterpartOrOwner(); + + error CancelOnlyByCounterpartOrOwnerOrAgent(); + /// functions // initiates the nonce at 0 @@ -193,22 +209,22 @@ contract DVDTransferManager is Ownable { msg.sender == owner() || isTREXOwner(_token1, msg.sender) || isTREXOwner(_token2, msg.sender) - , "Ownable: only owner can call"); + , CommonLib.OwnableUnauthorizedAccount(msg.sender)); require( IERC20(_token1).totalSupply() != 0 && IERC20(_token2).totalSupply() != 0 - , "invalid address : address is not an ERC20"); + , InvalidArgumentLib.AddressNotERC20(IERC20(_token1).totalSupply() != 0 ? _token2 : _token1)); require( - _fee1 <= 10**_feeBase && _fee1 >= 0 && - _fee2 <= 10**_feeBase && _fee2 >= 0 && + _fee1 <= 10**_feeBase && + _fee2 <= 10**_feeBase && _feeBase <= 5 && _feeBase >= 2 - , "invalid fee settings"); + , InvalidFeeSettings()); if (_fee1 > 0) { - require(_fee1Wallet != address(0), "fee wallet 1 cannot be zero address"); + require(_fee1Wallet != address(0), FeeWalletCannotBeZeroAddress(1)); } if (_fee2 > 0) { - require(_fee2Wallet != address(0), "fee wallet 2 cannot be zero address"); + require(_fee2Wallet != address(0), FeeWalletCannotBeZeroAddress(2)); } bytes32 _parity = calculateParity(_token1, _token2); Fee memory parityFee; @@ -250,12 +266,14 @@ contract DVDTransferManager is Ownable { address _counterpart, address _token2, uint256 _token2Amount) external { - require(IERC20(_token1).balanceOf(msg.sender) >= _token1Amount, "Not enough tokens in balance"); - require( - IERC20(_token1).allowance(msg.sender, address(this)) >= _token1Amount - , "not enough allowance to initiate transfer"); - require (_counterpart != address(0), "counterpart cannot be null"); - require(IERC20(_token2).totalSupply() != 0, "invalid address : address is not an ERC20"); + uint256 balance = IERC20(_token1).balanceOf(msg.sender); + require(balance >= _token1Amount, CommonLib.ERC20InsufficientBalance(msg.sender, balance, _token1Amount)); + + uint256 allowance = IERC20(_token1).allowance(msg.sender, address(this)); + require(allowance >= _token1Amount, CommonLib.ERC20InsufficientAllowance(msg.sender, allowance, _token1Amount)); + + require (_counterpart != address(0), InvalidArgumentLib.ZeroAddress()); + require(IERC20(_token2).totalSupply() != 0, InvalidArgumentLib.AddressNotERC20(_token2)); Delivery memory token1; token1.counterpart = msg.sender; token1.token = _token1; @@ -314,20 +332,25 @@ contract DVDTransferManager is Ownable { Delivery memory token2 = token2ToDeliver[_transferID]; require( token1.counterpart != address(0) && token2.counterpart != address(0) - , "transfer ID does not exist"); + , TransferIDDoesNotExist()); IERC20 token1Contract = IERC20(token1.token); IERC20 token2Contract = IERC20(token2.token); require ( msg.sender == token2.counterpart || isTREXAgent(token1.token, msg.sender) || isTREXAgent(token2.token, msg.sender) - , "transfer has to be done by the counterpart or by owner"); + , TransferOnlyByCounterpartOrOwner()); + + uint256 balance = token2Contract.balanceOf(token2.counterpart); require( - token2Contract.balanceOf(token2.counterpart) >= token2.amount - , "Not enough tokens in balance"); + balance >= token2.amount + , CommonLib.ERC20InsufficientBalance(token2.counterpart, balance, token2.amount)); + + uint256 allowance = token2Contract.allowance(token2.counterpart, address(this)); require( - token2Contract.allowance(token2.counterpart, address(this)) >= token2.amount - , "not enough allowance to transfer"); + allowance >= token2.amount + , CommonLib.ERC20InsufficientAllowance(token2.counterpart, allowance, token2.amount)); + TxFees memory fees = calculateFee(_transferID); if (fees.txFee1 != 0) { token1Contract.transferFrom(token1.counterpart, token2.counterpart, (token1.amount - fees.txFee1)); @@ -362,14 +385,14 @@ contract DVDTransferManager is Ownable { function cancelDVDTransfer(bytes32 _transferID) external { Delivery memory token1 = token1ToDeliver[_transferID]; Delivery memory token2 = token2ToDeliver[_transferID]; - require(token1.counterpart != address(0) && token2.counterpart != address(0), "transfer ID does not exist"); + require(token1.counterpart != address(0) && token2.counterpart != address(0), TransferIDDoesNotExist()); require ( msg.sender == token2.counterpart || msg.sender == token1.counterpart || msg.sender == owner() || isTREXAgent(token1.token, msg.sender) || isTREXAgent(token2.token, msg.sender) - , "you are not allowed to cancel this transfer"); + , CancelOnlyByCounterpartOrOwnerOrAgent()); delete token1ToDeliver[_transferID]; delete token2ToDeliver[_transferID]; emit DVDTransferCancelled(_transferID); diff --git a/contracts/compliance/modular/ModularCompliance.sol b/contracts/compliance/modular/ModularCompliance.sol index 01a155ff..f0c9db78 100644 --- a/contracts/compliance/modular/ModularCompliance.sol +++ b/contracts/compliance/modular/ModularCompliance.sol @@ -72,13 +72,29 @@ import "../../libraries/errors/InvalidArgumentLib.sol"; contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage { + /// errors + + error AddressNotATokenBoundToComplianceContract(); + + error CannotAddMoreThan25Modules(); + + error ComplianceNotSuitableForBindingToModule(); + + error ModuleAlreadyBound(); + + error ModuleNotBound(); + + error OnlyOwnerOrTokenCanCall(); + + error TokenNotBound(); + /// modifiers /** * @dev Throws if called by any address that is not a token bound to the compliance. */ modifier onlyToken() { - require(msg.sender == _tokenBound, "error : this address is not a token bound to the compliance contract"); + require(msg.sender == _tokenBound, AddressNotATokenBoundToComplianceContract()); _; } @@ -90,8 +106,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage * @dev See {IModularCompliance-bindToken}. */ function bindToken(address _token) external override { - require(owner() == msg.sender || (_tokenBound == address(0) && msg.sender == _token), - "only owner or token can call"); + require(owner() == msg.sender || (_tokenBound == address(0) && msg.sender == _token), OnlyOwnerOrTokenCanCall()); require(_token != address(0), InvalidArgumentLib.ZeroAddress()); _tokenBound = _token; emit TokenBound(_token); @@ -101,8 +116,8 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage * @dev See {IModularCompliance-unbindToken}. */ function unbindToken(address _token) external override { - require(owner() == msg.sender || msg.sender == _token , "only owner or token can call"); - require(_token == _tokenBound, "This token is not bound"); + require(owner() == msg.sender || msg.sender == _token , OnlyOwnerOrTokenCanCall()); + require(_token == _tokenBound, TokenNotBound()); require(_token != address(0), InvalidArgumentLib.ZeroAddress()); delete _tokenBound; emit TokenUnbound(_token); @@ -113,11 +128,11 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage */ function addModule(address _module) external override onlyOwner { require(_module != address(0), InvalidArgumentLib.ZeroAddress()); - require(!_moduleBound[_module], "module already bound"); - require(_modules.length <= 24, "cannot add more than 25 modules"); + require(!_moduleBound[_module], ModuleAlreadyBound()); + require(_modules.length <= 24, CannotAddMoreThan25Modules()); IModule module = IModule(_module); if (!module.isPlugAndPlay()) { - require(module.canComplianceBind(address(this)), "compliance is not suitable for binding to the module"); + require(module.canComplianceBind(address(this)), ComplianceNotSuitableForBindingToModule()); } module.bindCompliance(address(this)); @@ -131,7 +146,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage */ function removeModule(address _module) external override onlyOwner { require(_module != address(0), InvalidArgumentLib.ZeroAddress()); - require(_moduleBound[_module], "module not bound"); + require(_moduleBound[_module], ModuleNotBound()); uint256 length = _modules.length; for (uint256 i = 0; i < length; i++) { if (_modules[i] == _module) { @@ -153,7 +168,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage _from != address(0) && _to != address(0) , InvalidArgumentLib.ZeroAddress()); - require(_value > 0, "invalid argument - no value transfer"); + require(_value > 0, InvalidArgumentLib.NoValue()); uint256 length = _modules.length; for (uint256 i = 0; i < length; i++) { IModule(_modules[i]).moduleTransferAction(_from, _to, _value); @@ -165,7 +180,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage */ function created(address _to, uint256 _value) external onlyToken override { require(_to != address(0), InvalidArgumentLib.ZeroAddress()); - require(_value > 0, "invalid argument - no value mint"); + require(_value > 0, InvalidArgumentLib.NoValue()); uint256 length = _modules.length; for (uint256 i = 0; i < length; i++) { IModule(_modules[i]).moduleMintAction(_to, _value); @@ -177,7 +192,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage */ function destroyed(address _from, uint256 _value) external onlyToken override { require(_from != address(0), InvalidArgumentLib.ZeroAddress()); - require(_value > 0, "invalid argument - no value burn"); + require(_value > 0, InvalidArgumentLib.NoValue()); uint256 length = _modules.length; for (uint256 i = 0; i < length; i++) { IModule(_modules[i]).moduleBurnAction(_from, _value); @@ -188,7 +203,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage * @dev see {IModularCompliance-callModuleFunction}. */ function callModuleFunction(bytes calldata callData, address _module) external override onlyOwner { - require(_moduleBound[_module], "call only on bound module"); + require(_moduleBound[_module], ModuleNotBound()); // NOTE: Use assembly to call the interaction instead of a low level // call for two reasons: // - We don't want to copy the return data, since we discard it for @@ -199,16 +214,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage assembly { let freeMemoryPointer := mload(0x40) calldatacopy(freeMemoryPointer, callData.offset, callData.length) - if iszero( - call( - gas(), - _module, - 0, - freeMemoryPointer, - callData.length, - 0, - 0 - )) + if iszero(call(gas(), _module, 0, freeMemoryPointer, callData.length, 0, 0)) { returndatacopy(0, 0, returndatasize()) revert(0, returndatasize()) @@ -216,7 +222,6 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage } emit ModuleInteraction(_module, _selector(callData)); - } /** diff --git a/contracts/compliance/modular/modules/AbstractModule.sol b/contracts/compliance/modular/modules/AbstractModule.sol index 71eb9950..a2211f73 100644 --- a/contracts/compliance/modular/modules/AbstractModule.sol +++ b/contracts/compliance/modular/modules/AbstractModule.sol @@ -64,6 +64,7 @@ pragma solidity 0.8.26; import "./IModule.sol"; import "../../../libraries/errors/InvalidArgumentLib.sol"; +import "../../../libraries/errors/ComplianceLib.sol"; abstract contract AbstractModule is IModule { @@ -74,7 +75,7 @@ abstract contract AbstractModule is IModule { * @dev Throws if `_compliance` is not a bound compliance contract address. */ modifier onlyBoundCompliance(address _compliance) { - require(_complianceBound[_compliance], "compliance not bound"); + require(_complianceBound[_compliance], ComplianceLib.ComplianceNotBound()); _; } @@ -82,7 +83,7 @@ abstract contract AbstractModule is IModule { * @dev Throws if called from an address that is not a bound compliance contract. */ modifier onlyComplianceCall() { - require(_complianceBound[msg.sender], "only bound compliance can call"); + require(_complianceBound[msg.sender], ComplianceLib.OnlyBoundComplianceCanCall()); _; } @@ -91,8 +92,8 @@ abstract contract AbstractModule is IModule { */ function bindCompliance(address _compliance) external override { require(_compliance != address(0), InvalidArgumentLib.ZeroAddress()); - require(!_complianceBound[_compliance], "compliance already bound"); - require(msg.sender == _compliance, "only compliance contract can call"); + require(!_complianceBound[_compliance], ComplianceLib.ComplianceAlreadyBound()); + require(msg.sender == _compliance, ComplianceLib.OnlyComplianceContractCanCall()); _complianceBound[_compliance] = true; emit ComplianceBound(_compliance); } @@ -102,7 +103,7 @@ abstract contract AbstractModule is IModule { */ function unbindCompliance(address _compliance) external onlyComplianceCall override { require(_compliance != address(0), InvalidArgumentLib.ZeroAddress()); - require(msg.sender == _compliance, "only compliance contract can call"); + require(msg.sender == _compliance, ComplianceLib.OnlyComplianceContractCanCall()); _complianceBound[_compliance] = false; emit ComplianceUnbound(_compliance); } diff --git a/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol index 537a034b..cfaa000b 100644 --- a/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol +++ b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol @@ -67,6 +67,8 @@ import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "./IModule.sol"; import "../../../libraries/errors/InvalidArgumentLib.sol"; +import "../../../libraries/errors/ComplianceLib.sol"; + abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUpgradeable, UUPSUpgradeable { struct AbstractModuleStorage { @@ -83,7 +85,7 @@ abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUp */ modifier onlyBoundCompliance(address _compliance) { AbstractModuleStorage storage s = _getAbstractModuleStorage(); - require(s.complianceBound[_compliance], "compliance not bound"); + require(s.complianceBound[_compliance], ComplianceLib.ComplianceNotBound()); _; } @@ -92,7 +94,7 @@ abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUp */ modifier onlyComplianceCall() { AbstractModuleStorage storage s = _getAbstractModuleStorage(); - require(s.complianceBound[msg.sender], "only bound compliance can call"); + require(s.complianceBound[msg.sender], ComplianceLib.OnlyBoundComplianceCanCall()); _; } @@ -102,8 +104,8 @@ abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUp function bindCompliance(address _compliance) external override { AbstractModuleStorage storage s = _getAbstractModuleStorage(); require(_compliance != address(0), InvalidArgumentLib.ZeroAddress()); - require(!s.complianceBound[_compliance], "compliance already bound"); - require(msg.sender == _compliance, "only compliance contract can call"); + require(!s.complianceBound[_compliance], ComplianceLib.ComplianceAlreadyBound()); + require(msg.sender == _compliance, ComplianceLib.OnlyComplianceContractCanCall()); s.complianceBound[_compliance] = true; emit ComplianceBound(_compliance); } @@ -114,7 +116,7 @@ abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUp function unbindCompliance(address _compliance) external onlyComplianceCall override { AbstractModuleStorage storage s = _getAbstractModuleStorage(); require(_compliance != address(0), InvalidArgumentLib.ZeroAddress()); - require(msg.sender == _compliance, "only compliance contract can call"); + require(msg.sender == _compliance, ComplianceLib.OnlyComplianceContractCanCall()); s.complianceBound[_compliance] = false; emit ComplianceUnbound(_compliance); } diff --git a/contracts/compliance/modular/modules/ConditionalTransferModule.sol b/contracts/compliance/modular/modules/ConditionalTransferModule.sol index 9ceb3752..6eb19a0f 100644 --- a/contracts/compliance/modular/modules/ConditionalTransferModule.sol +++ b/contracts/compliance/modular/modules/ConditionalTransferModule.sol @@ -100,6 +100,10 @@ contract ConditionalTransferModule is AbstractModuleUpgradeable { */ event ApprovalRemoved(address _from, address _to, uint _amount, address _token); + /// Errors + + error NotApproved(); + /** * @dev initializes the contract and sets the initial state. * @notice This function should only be called once during the contract deployment. @@ -231,7 +235,7 @@ contract ConditionalTransferModule is AbstractModuleUpgradeable { */ function unApproveTransfer(address _from, address _to, uint _amount) public onlyComplianceCall { bytes32 transferHash = calculateTransferHash(_from, _to, _amount, IModularCompliance(msg.sender).getTokenBound()); - require(_transfersApproved[msg.sender][transferHash] > 0, "not approved"); + require(_transfersApproved[msg.sender][transferHash] > 0, NotApproved()); _transfersApproved[msg.sender][transferHash]--; emit ApprovalRemoved(_from, _to, _amount, IModularCompliance(msg.sender).getTokenBound()); diff --git a/contracts/compliance/modular/modules/CountryRestrictModule.sol b/contracts/compliance/modular/modules/CountryRestrictModule.sol index a0ed62b7..456acf17 100644 --- a/contracts/compliance/modular/modules/CountryRestrictModule.sol +++ b/contracts/compliance/modular/modules/CountryRestrictModule.sol @@ -73,6 +73,15 @@ import "../../../token/IToken.sol"; import "./AbstractModuleUpgradeable.sol"; contract CountryRestrictModule is AbstractModuleUpgradeable { + + /// errors + + error CountryAlreadyRestricted(); + + error CountryNotRestricted(); + + error Max195CountriesInBatch(); + /// Mapping between country and their restriction status per compliance contract mapping(address => mapping(uint16 => bool)) private _restrictedCountries; @@ -106,7 +115,7 @@ contract CountryRestrictModule is AbstractModuleUpgradeable { * emits an `AddedRestrictedCountry` event */ function addCountryRestriction(uint16 _country) external onlyComplianceCall { - require((_restrictedCountries[msg.sender])[_country] == false, "country already restricted"); + require((_restrictedCountries[msg.sender])[_country] == false, CountryAlreadyRestricted()); (_restrictedCountries[msg.sender])[_country] = true; emit AddedRestrictedCountry(msg.sender, _country); } @@ -120,7 +129,7 @@ contract CountryRestrictModule is AbstractModuleUpgradeable { * emits an `RemovedRestrictedCountry` event */ function removeCountryRestriction(uint16 _country) external onlyComplianceCall { - require((_restrictedCountries[msg.sender])[_country] == true, "country not restricted"); + require((_restrictedCountries[msg.sender])[_country] == true, CountryNotRestricted()); (_restrictedCountries[msg.sender])[_country] = false; emit RemovedRestrictedCountry(msg.sender, _country); } @@ -135,9 +144,9 @@ contract CountryRestrictModule is AbstractModuleUpgradeable { * emits _countries.length `AddedRestrictedCountry` events */ function batchRestrictCountries(uint16[] calldata _countries) external onlyComplianceCall { - require(_countries.length < 195, "maximum 195 can be restricted in one batch"); + require(_countries.length < 195, Max195CountriesInBatch()); for (uint256 i = 0; i < _countries.length; i++) { - require((_restrictedCountries[msg.sender])[_countries[i]] == false, "country already restricted"); + require(!(_restrictedCountries[msg.sender])[_countries[i]], CountryAlreadyRestricted()); (_restrictedCountries[msg.sender])[_countries[i]] = true; emit AddedRestrictedCountry(msg.sender, _countries[i]); } @@ -153,9 +162,9 @@ contract CountryRestrictModule is AbstractModuleUpgradeable { * emits _countries.length `RemovedRestrictedCountry` events */ function batchUnrestrictCountries(uint16[] calldata _countries) external onlyComplianceCall { - require(_countries.length < 195, "maximum 195 can be unrestricted in one batch"); + require(_countries.length < 195, Max195CountriesInBatch()); for (uint256 i = 0; i < _countries.length; i++) { - require((_restrictedCountries[msg.sender])[_countries[i]] == true, "country not restricted"); + require((_restrictedCountries[msg.sender])[_countries[i]], CountryNotRestricted()); (_restrictedCountries[msg.sender])[_countries[i]] = false; emit RemovedRestrictedCountry(msg.sender, _countries[i]); } diff --git a/contracts/compliance/modular/modules/MaxBalanceModule.sol b/contracts/compliance/modular/modules/MaxBalanceModule.sol index bee3a45a..4243a35d 100644 --- a/contracts/compliance/modular/modules/MaxBalanceModule.sol +++ b/contracts/compliance/modular/modules/MaxBalanceModule.sol @@ -107,6 +107,8 @@ contract MaxBalanceModule is AbstractModuleUpgradeable { error TokenAlreadyBound(address _compliance); + error IdentityNotFound(); + /// functions /** @@ -307,7 +309,7 @@ contract MaxBalanceModule is AbstractModuleUpgradeable { function _getIdentity(address _compliance, address _userAddress) internal view returns (address) { address identity = address(IToken(IModularCompliance(_compliance).getTokenBound()) .identityRegistry().identity(_userAddress)); - require(identity != address(0), "identity not found"); + require(identity != address(0), IdentityNotFound()); return identity; } } diff --git a/contracts/compliance/modular/modules/TransferFeesModule.sol b/contracts/compliance/modular/modules/TransferFeesModule.sol index 3632d1df..368e8ff0 100644 --- a/contracts/compliance/modular/modules/TransferFeesModule.sol +++ b/contracts/compliance/modular/modules/TransferFeesModule.sol @@ -92,10 +92,14 @@ contract TransferFeesModule is AbstractModuleUpgradeable { */ event FeeUpdated(address indexed compliance, uint256 _rate, address _collector); + /// Errors + error FeeRateIsOutOfRange(address compliance, uint256 rate); error CollectorAddressIsNotVerified(address compliance, address collector); + error TransferFeeCollectionFailed(); + /** * @dev initializes the contract and sets the initial state. * @notice This function should only be called once during the contract deployment. @@ -150,7 +154,7 @@ contract TransferFeesModule is AbstractModuleUpgradeable { IToken token = IToken(IModularCompliance(msg.sender).getTokenBound()); bool sent = token.forcedTransfer(_to, fee.collector, feeAmount); - require(sent, "transfer fee collection failed"); + require(sent, TransferFeeCollectionFailed()); } /** diff --git a/contracts/libraries/errors/CommonLib.sol b/contracts/libraries/errors/CommonLib.sol new file mode 100644 index 00000000..98a0e0c7 --- /dev/null +++ b/contracts/libraries/errors/CommonLib.sol @@ -0,0 +1,120 @@ + +// SPDX-License-Identifier: GPL-3.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// + +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2023, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +pragma solidity 0.8.26; + + +library CommonLib { + + error InitializationFailed(); + + /// @dev We must use OpenZeppelin libs when upgrading to v >= 5 for errors below + + /** + * @dev The caller account is not authorized to perform an operation. + */ + error OwnableUnauthorizedAccount(address account); + + /** + * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. + * @param spender Address that may be allowed to operate on tokens without being their owner. + * @param allowance Amount of tokens a `spender` is allowed to operate with. + * @param needed Minimum amount required to perform a transfer. + */ + error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); + + /** + * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. + * @param sender Address whose tokens are being transferred. + * @param balance Current balance for the interacting account. + * @param needed Minimum amount required to perform a transfer. + */ + error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); + + /** + * @dev Indicates a failure with the token `receiver`. Used in transfers. + * @param receiver Address to which tokens are being transferred. + */ + error ERC20InvalidReceiver(address receiver); + + /** + * @dev Indicates a failure with the `spender` to be approved. Used in approvals. + * @param spender Address that may be allowed to operate on tokens without being their owner. + */ + error ERC20InvalidSpender(address spender); + + + + /** + * @dev The operation failed because the contract is paused. + */ + error EnforcedPause(); + + /** + * @dev The operation failed because the contract is not paused. + */ + error ExpectedPause(); + +} + diff --git a/contracts/libraries/errors/ComplianceLib.sol b/contracts/libraries/errors/ComplianceLib.sol new file mode 100644 index 00000000..9e31551a --- /dev/null +++ b/contracts/libraries/errors/ComplianceLib.sol @@ -0,0 +1,79 @@ + +// SPDX-License-Identifier: GPL-3.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// + +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2023, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +pragma solidity 0.8.26; + + +library ComplianceLib { + + error ComplianceAlreadyBound(); + + error ComplianceNotBound(); + + error OnlyBoundComplianceCanCall(); + + error OnlyComplianceContractCanCall(); + +} + diff --git a/contracts/libraries/errors/InvalidArgumentLib.sol b/contracts/libraries/errors/InvalidArgumentLib.sol index 9638e074..4a30ead7 100644 --- a/contracts/libraries/errors/InvalidArgumentLib.sol +++ b/contracts/libraries/errors/InvalidArgumentLib.sol @@ -66,9 +66,19 @@ pragma solidity 0.8.26; library InvalidArgumentLib { + /// @notice Thrown when the address is not an ERC20. + error AddressNotERC20(address token); + + error DecimalsBetween0And18(); + /// @notice Thrown when the string passed is empty. error EmptyString(); + error InvalidImplementationAuthority(); + + /// @notice Thrown when token amount is zero. + error NoValue(); + /// @notice Thrown when the address passed is the zero address. error ZeroAddress(); } diff --git a/contracts/libraries/errors/RoleLib.sol b/contracts/libraries/errors/RoleLib.sol index 09fa086d..ed6bb40d 100644 --- a/contracts/libraries/errors/RoleLib.sol +++ b/contracts/libraries/errors/RoleLib.sol @@ -70,6 +70,8 @@ library RoleLib { error AccountDoesNotHaveRole(); + error CallerDoesNotHaveAgentRole(); + error SenderIsNotAdmin(); error SenderIsNotClaimRegistryManager(); diff --git a/contracts/proxy/AbstractProxy.sol b/contracts/proxy/AbstractProxy.sol index fe20ce03..c82c8a0b 100644 --- a/contracts/proxy/AbstractProxy.sol +++ b/contracts/proxy/AbstractProxy.sol @@ -69,11 +69,15 @@ import "../libraries/errors/InvalidArgumentLib.sol"; abstract contract AbstractProxy is IProxy, Initializable { + /// Errors + + error OnlyCurrentImplementationAuthorityCanCall(); + /** * @dev See {IProxy-setImplementationAuthority}. */ function setImplementationAuthority(address _newImplementationAuthority) external override { - require(msg.sender == getImplementationAuthority(), "only current implementationAuthority can call"); + require(msg.sender == getImplementationAuthority(), OnlyCurrentImplementationAuthorityCanCall()); require(_newImplementationAuthority != address(0), InvalidArgumentLib.ZeroAddress()); require( (ITREXImplementationAuthority(_newImplementationAuthority)).getTokenImplementation() != address(0) @@ -82,7 +86,7 @@ abstract contract AbstractProxy is IProxy, Initializable { && (ITREXImplementationAuthority(_newImplementationAuthority)).getIRSImplementation() != address(0) && (ITREXImplementationAuthority(_newImplementationAuthority)).getMCImplementation() != address(0) && (ITREXImplementationAuthority(_newImplementationAuthority)).getTIRImplementation() != address(0) - , "invalid Implementation Authority"); + , InvalidArgumentLib.InvalidImplementationAuthority()); _storeImplementationAuthority(_newImplementationAuthority); emit ImplementationAuthoritySet(_newImplementationAuthority); } diff --git a/contracts/proxy/ClaimTopicsRegistryProxy.sol b/contracts/proxy/ClaimTopicsRegistryProxy.sol index ec4c3935..5f8bac0d 100644 --- a/contracts/proxy/ClaimTopicsRegistryProxy.sol +++ b/contracts/proxy/ClaimTopicsRegistryProxy.sol @@ -63,11 +63,13 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; +import "../libraries/errors/InvalidArgumentLib.sol"; +import "../libraries/errors/CommonLib.sol"; contract ClaimTopicsRegistryProxy is AbstractProxy { constructor(address implementationAuthority) { - require(implementationAuthority != address(0), "invalid argument - zero address"); + require(implementationAuthority != address(0), InvalidArgumentLib.ZeroAddress()); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); @@ -75,7 +77,7 @@ contract ClaimTopicsRegistryProxy is AbstractProxy { // solhint-disable-next-line avoid-low-level-calls (bool success, ) = logic.delegatecall(abi.encodeWithSignature("init()")); - require(success, "Initialization failed."); + require(success, CommonLib.InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/IdentityRegistryProxy.sol b/contracts/proxy/IdentityRegistryProxy.sol index 22ecfb7b..0557384b 100644 --- a/contracts/proxy/IdentityRegistryProxy.sol +++ b/contracts/proxy/IdentityRegistryProxy.sol @@ -63,6 +63,7 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; +import "../libraries/errors/CommonLib.sol"; contract IdentityRegistryProxy is AbstractProxy { @@ -90,7 +91,7 @@ contract IdentityRegistryProxy is AbstractProxy { _trustedIssuersRegistry, _claimTopicsRegistry, _identityStorage)); - require(success, "Initialization failed."); + require(success, CommonLib.InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/IdentityRegistryStorageProxy.sol b/contracts/proxy/IdentityRegistryStorageProxy.sol index 84d21621..72b6bde1 100644 --- a/contracts/proxy/IdentityRegistryStorageProxy.sol +++ b/contracts/proxy/IdentityRegistryStorageProxy.sol @@ -63,6 +63,7 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; +import "../libraries/errors/CommonLib.sol"; contract IdentityRegistryStorageProxy is AbstractProxy { @@ -75,7 +76,7 @@ contract IdentityRegistryStorageProxy is AbstractProxy { // solhint-disable-next-line avoid-low-level-calls (bool success, ) = logic.delegatecall(abi.encodeWithSignature("init()")); - require(success, "Initialization failed."); + require(success, CommonLib.InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/ModularComplianceProxy.sol b/contracts/proxy/ModularComplianceProxy.sol index 61244a45..ba83e2bb 100644 --- a/contracts/proxy/ModularComplianceProxy.sol +++ b/contracts/proxy/ModularComplianceProxy.sol @@ -63,11 +63,14 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; +import "../libraries/errors/CommonLib.sol"; +import "../libraries/errors/InvalidArgumentLib.sol"; + contract ModularComplianceProxy is AbstractProxy { constructor(address implementationAuthority) { - require(implementationAuthority != address(0), "invalid argument - zero address"); + require(implementationAuthority != address(0), InvalidArgumentLib.ZeroAddress()); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); @@ -75,7 +78,7 @@ contract ModularComplianceProxy is AbstractProxy { // solhint-disable-next-line avoid-low-level-calls (bool success, ) = logic.delegatecall(abi.encodeWithSignature("init()")); - require(success, "Initialization failed."); + require(success, CommonLib.InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/TokenProxy.sol b/contracts/proxy/TokenProxy.sol index a858df7d..4cd1282d 100644 --- a/contracts/proxy/TokenProxy.sol +++ b/contracts/proxy/TokenProxy.sol @@ -64,6 +64,7 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; import "../libraries/errors/InvalidArgumentLib.sol"; +import "../libraries/errors/CommonLib.sol"; contract TokenProxy is AbstractProxy { @@ -86,7 +87,7 @@ contract TokenProxy is AbstractProxy { keccak256(abi.encode(_name)) != keccak256(abi.encode("")) && keccak256(abi.encode(_symbol)) != keccak256(abi.encode("")) , InvalidArgumentLib.EmptyString()); - require(0 <= _decimals && _decimals <= 18, "decimals between 0 and 18"); + require(0 <= _decimals && _decimals <= 18, InvalidArgumentLib.DecimalsBetween0And18()); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); @@ -104,7 +105,7 @@ contract TokenProxy is AbstractProxy { _onchainID ) ); - require(success, "Initialization failed."); + require(success, CommonLib.InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/TrustedIssuersRegistryProxy.sol b/contracts/proxy/TrustedIssuersRegistryProxy.sol index 0f0b8034..7b69cfb4 100644 --- a/contracts/proxy/TrustedIssuersRegistryProxy.sol +++ b/contracts/proxy/TrustedIssuersRegistryProxy.sol @@ -65,6 +65,8 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; import "../libraries/errors/InvalidArgumentLib.sol"; +import "../libraries/errors/CommonLib.sol"; + contract TrustedIssuersRegistryProxy is AbstractProxy { @@ -77,7 +79,7 @@ contract TrustedIssuersRegistryProxy is AbstractProxy { // solhint-disable-next-line avoid-low-level-calls (bool success, ) = logic.delegatecall(abi.encodeWithSignature("init()")); - require(success, "Initialization failed."); + require(success, CommonLib.InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/authority/TREXImplementationAuthority.sol b/contracts/proxy/authority/TREXImplementationAuthority.sol index cfa4d012..1e35795a 100644 --- a/contracts/proxy/authority/TREXImplementationAuthority.sol +++ b/contracts/proxy/authority/TREXImplementationAuthority.sol @@ -72,6 +72,26 @@ import "../../libraries/errors/InvalidArgumentLib.sol"; contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { + /// Errors + + error CallerNotOwnerOfAllImpactedContracts(); + + error CannotCallOnReferenceContract(); + + error InvalidIA(); + + error NewIAIsNotAReferenceContract(); + + error OnlyReferenceContractCanAddVersion(); + + error OnlyReferenceContractCanCall(); + + error OnlyReferenceContractCanDeployNewIA(); + + error VersionAlreadyFetched(); + + error VersionOfNewIAMustBeTheSameAsCurrentIA(); + /// variables /// current version @@ -117,7 +137,7 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { require( isReferenceContract() && ITREXFactory(trexFactory).getImplementationAuthority() == address(this) - , "only reference contract can call"); + , OnlyReferenceContractCanCall()); _trexFactory = trexFactory; emit TREXFactorySet(trexFactory); } @@ -129,7 +149,7 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { require( isReferenceContract() && ITREXFactory(_trexFactory).getImplementationAuthority() == address(this) - , "only reference contract can call"); + , OnlyReferenceContractCanCall()); _iaFactory = iaFactory; emit IAFactorySet(iaFactory); } @@ -146,9 +166,9 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { * @dev See {ITREXImplementationAuthority-fetchVersionList}. */ function fetchVersion(Version calldata _version) external override { - require(!isReferenceContract(), "cannot call on reference contract"); + require(!isReferenceContract(), CannotCallOnReferenceContract()); if (_contracts[_versionToBytes(_version)].tokenImplementation != address(0)) { - revert("version fetched already"); + revert VersionAlreadyFetched(); } _contracts[_versionToBytes(_version)] = ITREXImplementationAuthority(getReferenceContract()).getContracts(_version); @@ -162,7 +182,8 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { function changeImplementationAuthority(address _token, address _newImplementationAuthority) external override { require(_token != address(0), InvalidArgumentLib.ZeroAddress()); if(_newImplementationAuthority == address(0) && !isReferenceContract()){ - revert("only reference contract can deploy new IAs");} + revert OnlyReferenceContractCanDeployNewIA(); + } address _ir = address(IToken(_token).identityRegistry()); address _mc = address(IToken(_token).compliance()); @@ -178,7 +199,7 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { || Ownable(_irs).owner() != msg.sender || Ownable(_ctr).owner() != msg.sender || Ownable(_tir).owner() != msg.sender) { - revert("caller NOT owner of all contracts impacted"); + revert CallerNotOwnerOfAllImpactedContracts(); } if(_newImplementationAuthority == address(0)) { @@ -188,17 +209,17 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { if( _versionToBytes(ITREXImplementationAuthority(_newImplementationAuthority).getCurrentVersion()) != _versionToBytes(_currentVersion)) { - revert("version of new IA has to be the same as current IA"); + revert VersionOfNewIAMustBeTheSameAsCurrentIA(); } if( ITREXImplementationAuthority(_newImplementationAuthority).isReferenceContract() && _newImplementationAuthority != getReferenceContract()) { - revert("new IA is NOT reference contract"); + revert NewIAIsNotAReferenceContract(); } if( !IIAFactory(_iaFactory).deployedByFactory(_newImplementationAuthority) && _newImplementationAuthority != getReferenceContract()) { - revert("invalid IA"); + revert InvalidIA(); } } @@ -281,7 +302,7 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { * @dev See {ITREXImplementationAuthority-addTREXVersion}. */ function addTREXVersion(Version calldata _version, TREXContracts calldata _trex) public override onlyOwner { - require(isReferenceContract(), "ONLY reference contract can add versions"); + require(isReferenceContract(), OnlyReferenceContractCanAddVersion()); if (_contracts[_versionToBytes(_version)].tokenImplementation != address(0)) { revert("version already exists"); } diff --git a/contracts/registry/implementation/ClaimTopicsRegistry.sol b/contracts/registry/implementation/ClaimTopicsRegistry.sol index 99cb60b7..42e3df2a 100644 --- a/contracts/registry/implementation/ClaimTopicsRegistry.sol +++ b/contracts/registry/implementation/ClaimTopicsRegistry.sol @@ -68,6 +68,13 @@ import "../interface/IClaimTopicsRegistry.sol"; contract ClaimTopicsRegistry is IClaimTopicsRegistry, OwnableUpgradeable, CTRStorage { + /// Errors + + error CannotRequireMoreThan15Topics(); + + error ClaimTopicAlreadyExists(); + + function init() external initializer { __Ownable_init(); } @@ -77,9 +84,9 @@ contract ClaimTopicsRegistry is IClaimTopicsRegistry, OwnableUpgradeable, CTRSto */ function addClaimTopic(uint256 _claimTopic) external override onlyOwner { uint256 length = _claimTopics.length; - require(length < 15, "cannot require more than 15 topics"); + require(length < 15, CannotRequireMoreThan15Topics()); for (uint256 i = 0; i < length; i++) { - require(_claimTopics[i] != _claimTopic, "claimTopic already exists"); + require(_claimTopics[i] != _claimTopic, ClaimTopicAlreadyExists()); } _claimTopics.push(_claimTopic); emit ClaimTopicAdded(_claimTopic); diff --git a/contracts/registry/implementation/IdentityRegistryStorage.sol b/contracts/registry/implementation/IdentityRegistryStorage.sol index acd722ea..925f1e2f 100644 --- a/contracts/registry/implementation/IdentityRegistryStorage.sol +++ b/contracts/registry/implementation/IdentityRegistryStorage.sol @@ -71,6 +71,17 @@ import "../../libraries/errors/InvalidArgumentLib.sol"; contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeable, IRSStorage { + /// Errors + + error AddressAlreadyStored(); + + error AddressNotYetStored(); + + error IdentityRegistryNotStored(); + + error CannotBindMoreThan300IRTo1IRS(); + + function init() external initializer { __Ownable_init(); } @@ -87,7 +98,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab _userAddress != address(0) && address(_identity) != address(0) , InvalidArgumentLib.ZeroAddress()); - require(address(_identities[_userAddress].identityContract) == address(0), "address stored already"); + require(address(_identities[_userAddress].identityContract) == address(0), AddressAlreadyStored()); _identities[_userAddress].identityContract = _identity; _identities[_userAddress].investorCountry = _country; emit IdentityStored(_userAddress, _identity); @@ -101,7 +112,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab _userAddress != address(0) && address(_identity) != address(0) , InvalidArgumentLib.ZeroAddress()); - require(address(_identities[_userAddress].identityContract) != address(0), "address not stored yet"); + require(address(_identities[_userAddress].identityContract) != address(0), AddressNotYetStored()); IIdentity oldIdentity = _identities[_userAddress].identityContract; _identities[_userAddress].identityContract = _identity; emit IdentityModified(oldIdentity, _identity); @@ -112,7 +123,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab */ function modifyStoredInvestorCountry(address _userAddress, uint16 _country) external override onlyAgent { require(_userAddress != address(0), InvalidArgumentLib.ZeroAddress()); - require(address(_identities[_userAddress].identityContract) != address(0), "address not stored yet"); + require(address(_identities[_userAddress].identityContract) != address(0), AddressNotYetStored()); _identities[_userAddress].investorCountry = _country; emit CountryModified(_userAddress, _country); } @@ -122,7 +133,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab */ function removeIdentityFromStorage(address _userAddress) external override onlyAgent { require(_userAddress != address(0), InvalidArgumentLib.ZeroAddress()); - require(address(_identities[_userAddress].identityContract) != address(0), "address not stored yet"); + require(address(_identities[_userAddress].identityContract) != address(0), AddressNotYetStored()); IIdentity oldIdentity = _identities[_userAddress].identityContract; delete _identities[_userAddress]; emit IdentityUnstored(_userAddress, oldIdentity); @@ -133,7 +144,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab */ function bindIdentityRegistry(address _identityRegistry) external override { require(_identityRegistry != address(0), InvalidArgumentLib.ZeroAddress()); - require(_identityRegistries.length < 300, "cannot bind more than 300 IR to 1 IRS"); + require(_identityRegistries.length < 300, CannotBindMoreThan300IRTo1IRS()); addAgent(_identityRegistry); _identityRegistries.push(_identityRegistry); emit IdentityRegistryBound(_identityRegistry); @@ -144,7 +155,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab */ function unbindIdentityRegistry(address _identityRegistry) external override { require(_identityRegistry != address(0), InvalidArgumentLib.ZeroAddress()); - require(_identityRegistries.length > 0, "identity registry is not stored"); + require(_identityRegistries.length > 0, IdentityRegistryNotStored()); uint256 length = _identityRegistries.length; for (uint256 i = 0; i < length; i++) { if (_identityRegistries[i] == _identityRegistry) { diff --git a/contracts/registry/implementation/TrustedIssuersRegistry.sol b/contracts/registry/implementation/TrustedIssuersRegistry.sol index 267b8bcd..4a461ba0 100644 --- a/contracts/registry/implementation/TrustedIssuersRegistry.sol +++ b/contracts/registry/implementation/TrustedIssuersRegistry.sol @@ -71,6 +71,24 @@ import "../../libraries/errors/InvalidArgumentLib.sol"; contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, TIRStorage { + /// Errors + + error ClaimTopicsCannotBeEmpty(); + + error CannotHaveMoreThan15ClaimTopics(); + + error CannotHaveMoreThan50TrustedIssuers(); + + error NotATrustedIssuer(); + + error TrustedClaimTopicsCannotBeEmpty(); + + error TrustedIssuerAlreadyExists(); + + error TrustedIssuerDoesntExist(); + + /// Functions + function init() external initializer { __Ownable_init(); } @@ -80,10 +98,10 @@ contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, */ function addTrustedIssuer(IClaimIssuer _trustedIssuer, uint256[] calldata _claimTopics) external override onlyOwner { require(address(_trustedIssuer) != address(0), InvalidArgumentLib.ZeroAddress()); - require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length == 0, "trusted Issuer already exists"); - require(_claimTopics.length > 0, "trusted claim topics cannot be empty"); - require(_claimTopics.length <= 15, "cannot have more than 15 claim topics"); - require(_trustedIssuers.length < 50, "cannot have more than 50 trusted issuers"); + require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length == 0, TrustedIssuerAlreadyExists()); + require(_claimTopics.length > 0, TrustedClaimTopicsCannotBeEmpty()); + require(_claimTopics.length <= 15, CannotHaveMoreThan15ClaimTopics()); + require(_trustedIssuers.length < 50, CannotHaveMoreThan50TrustedIssuers()); _trustedIssuers.push(_trustedIssuer); _trustedIssuerClaimTopics[address(_trustedIssuer)] = _claimTopics; for (uint256 i = 0; i < _claimTopics.length; i++) { @@ -97,7 +115,7 @@ contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, */ function removeTrustedIssuer(IClaimIssuer _trustedIssuer) external override onlyOwner { require(address(_trustedIssuer) != address(0), InvalidArgumentLib.ZeroAddress()); - require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length != 0, "NOT a trusted issuer"); + require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length != 0, NotATrustedIssuer()); uint256 length = _trustedIssuers.length; for (uint256 i = 0; i < length; i++) { if (_trustedIssuers[i] == _trustedIssuer) { @@ -130,9 +148,9 @@ contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, */ function updateIssuerClaimTopics(IClaimIssuer _trustedIssuer, uint256[] calldata _claimTopics) external override onlyOwner { require(address(_trustedIssuer) != address(0), InvalidArgumentLib.ZeroAddress()); - require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length != 0, "NOT a trusted issuer"); - require(_claimTopics.length <= 15, "cannot have more than 15 claim topics"); - require(_claimTopics.length > 0, "claim topics cannot be empty"); + require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length != 0, NotATrustedIssuer()); + require(_claimTopics.length <= 15, CannotHaveMoreThan15ClaimTopics()); + require(_claimTopics.length > 0, ClaimTopicsCannotBeEmpty()); for (uint256 i = 0; i < _trustedIssuerClaimTopics[address(_trustedIssuer)].length; i++) { uint256 claimTopic = _trustedIssuerClaimTopics[address(_trustedIssuer)][i]; @@ -181,7 +199,7 @@ contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, * @dev See {ITrustedIssuersRegistry-getTrustedIssuerClaimTopics}. */ function getTrustedIssuerClaimTopics(IClaimIssuer _trustedIssuer) external view override returns (uint256[] memory) { - require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length != 0, "trusted Issuer doesn\'t exist"); + require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length != 0, TrustedIssuerDoesntExist()); return _trustedIssuerClaimTopics[address(_trustedIssuer)]; } diff --git a/contracts/roles/AgentRole.sol b/contracts/roles/AgentRole.sol index cbe11eff..8935d065 100644 --- a/contracts/roles/AgentRole.sol +++ b/contracts/roles/AgentRole.sol @@ -67,6 +67,7 @@ import "@openzeppelin/contracts/access/Ownable.sol"; import "./Roles.sol"; import "../libraries/errors/InvalidArgumentLib.sol"; +import "../libraries/errors/RoleLib.sol"; contract AgentRole is Ownable { using Roles for Roles.Role; @@ -77,7 +78,7 @@ contract AgentRole is Ownable { event AgentRemoved(address indexed _agent); modifier onlyAgent() { - require(isAgent(msg.sender), "AgentRole: caller does not have the Agent role"); + require(isAgent(msg.sender), RoleLib.CallerDoesNotHaveAgentRole()); _; } diff --git a/contracts/roles/AgentRoleUpgradeable.sol b/contracts/roles/AgentRoleUpgradeable.sol index 08df264c..040080c4 100644 --- a/contracts/roles/AgentRoleUpgradeable.sol +++ b/contracts/roles/AgentRoleUpgradeable.sol @@ -67,6 +67,7 @@ import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "./Roles.sol"; import "../libraries/errors/InvalidArgumentLib.sol"; +import "../libraries/errors/RoleLib.sol"; contract AgentRoleUpgradeable is OwnableUpgradeable { using Roles for Roles.Role; @@ -77,7 +78,7 @@ contract AgentRoleUpgradeable is OwnableUpgradeable { event AgentRemoved(address indexed _agent); modifier onlyAgent() { - require(isAgent(msg.sender), "AgentRole: caller does not have the Agent role"); + require(isAgent(msg.sender), RoleLib.CallerDoesNotHaveAgentRole()); _; } diff --git a/contracts/token/Token.sol b/contracts/token/Token.sol index f50dca49..7bcbc9e2 100755 --- a/contracts/token/Token.sol +++ b/contracts/token/Token.sol @@ -68,6 +68,7 @@ import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; import "./TokenStorage.sol"; import "../roles/AgentRoleUpgradeable.sol"; import "../libraries/errors/InvalidArgumentLib.sol"; +import "../libraries/errors/CommonLib.sol"; contract Token is IToken, AgentRoleUpgradeable, TokenStorage { @@ -77,19 +78,27 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { error AgentNotAuthorized(address agent, string reason); - //error InvalidArgumentEmptyString(); + error AlreadyInitialized(); + + error FrozenWallet(); + + error NoTokenToRecover(); + + error RecoveryNotPossible(); + + error TransferNotPossible(); /// modifiers /// @dev Modifier to make a function callable only when the contract is not paused. modifier whenNotPaused() { - require(!_tokenPaused, "Pausable: paused"); + require(!_tokenPaused, CommonLib.EnforcedPause()); _; } /// @dev Modifier to make a function callable only when the contract is paused. modifier whenPaused() { - require(_tokenPaused, "Pausable: not paused"); + require(_tokenPaused, CommonLib.ExpectedPause()); _; } @@ -119,7 +128,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { // as there was a bug with the initializer modifier on these proxies // that check is preventing attackers to call the init functions on those // legacy contracts. - require(owner() == address(0), "already initialized"); + require(owner() == address(0), AlreadyInitialized()); require( _identityRegistry != address(0) && _compliance != address(0) @@ -128,7 +137,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { keccak256(abi.encode(_name)) != keccak256(abi.encode("")) && keccak256(abi.encode(_symbol)) != keccak256(abi.encode("")) , InvalidArgumentLib.EmptyString()); - require(0 <= _decimals && _decimals <= 18, "decimals between 0 and 18"); + require(0 <= _decimals && _decimals <= 18, InvalidArgumentLib.DecimalsBetween0And18()); __Ownable_init(); _tokenName = _name; _tokenSymbol = _symbol; @@ -256,15 +265,17 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { address _to, uint256 _amount ) external override whenNotPaused returns (bool) { - require(!_frozen[_to] && !_frozen[_from], "wallet is frozen"); - require(_amount <= balanceOf(_from) - (_frozenTokens[_from]), "Insufficient Balance"); + require(!_frozen[_to] && !_frozen[_from], FrozenWallet()); + + uint256 balance = balanceOf(_from) - (_frozenTokens[_from]); + require(_amount <= balance, CommonLib.ERC20InsufficientBalance(_from, balance, _amount)); if (_tokenIdentityRegistry.isVerified(_to) && _tokenCompliance.canTransfer(_from, _to, _amount)) { _approve(_from, msg.sender, _allowances[_from][msg.sender] - (_amount)); _transfer(_from, _to, _amount); _tokenCompliance.transferred(_from, _to, _amount); return true; } - revert("Transfer not possible"); + revert TransferNotPossible(); } /** @@ -336,7 +347,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { if(getAgentRestrictions(msg.sender).disableRecovery) { revert AgentNotAuthorized(msg.sender, "recovery disabled"); } - require(balanceOf(_lostWallet) != 0, "no tokens to recover"); + require(balanceOf(_lostWallet) != 0, NoTokenToRecover()); IIdentity _onchainID = IIdentity(_investorOnchainID); bytes32 _key = keccak256(abi.encode(_newWallet)); if (_onchainID.keyHasPurpose(_key, 1)) { @@ -355,7 +366,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { emit RecoverySuccess(_lostWallet, _newWallet, _investorOnchainID); return true; } - revert("Recovery not possible"); + revert RecoveryNotPossible(); } /** @@ -452,7 +463,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @return `true` if successful and revert if unsuccessful */ function transfer(address _to, uint256 _amount) public override whenNotPaused returns (bool) { - require(!_frozen[_to] && !_frozen[msg.sender], "wallet is frozen"); + require(!_frozen[_to] && !_frozen[msg.sender], FrozenWallet()); require(_amount <= balanceOf(msg.sender) - (_frozenTokens[msg.sender]), "Insufficient Balance"); if (_tokenIdentityRegistry.isVerified(_to) && _tokenCompliance.canTransfer(msg.sender, _to, _amount)) { _transfer(msg.sender, _to, _amount); @@ -485,7 +496,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { _tokenCompliance.transferred(_from, _to, _amount); return true; } - revert("Transfer not possible"); + revert TransferNotPossible(); } /** @@ -598,8 +609,8 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { address _to, uint256 _amount ) internal virtual { - require(_from != address(0), "ERC20: transfer from the zero address"); - require(_to != address(0), "ERC20: transfer to the zero address"); + require(_from != address(0), CommonLib.ERC20InvalidSpender(_from)); + require(_to != address(0), CommonLib.ERC20InvalidReceiver(_to)); _beforeTokenTransfer(_from, _to, _amount); @@ -612,7 +623,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {ERC20-_mint}. */ function _mint(address _userAddress, uint256 _amount) internal virtual { - require(_userAddress != address(0), "ERC20: mint to the zero address"); + require(_userAddress != address(0), CommonLib.ERC20InvalidReceiver(_userAddress)); _beforeTokenTransfer(address(0), _userAddress, _amount); @@ -625,7 +636,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {ERC20-_burn}. */ function _burn(address _userAddress, uint256 _amount) internal virtual { - require(_userAddress != address(0), "ERC20: burn from the zero address"); + require(_userAddress != address(0), CommonLib.ERC20InvalidSpender(_userAddress)); _beforeTokenTransfer(_userAddress, address(0), _amount); diff --git a/package-lock.json b/package-lock.json index afbdad71..632fca09 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,7 @@ "eth-gas-reporter": "^0.2.27", "fs-extra": "^11.2.0", "glob": "^10.4.1", - "hardhat": "^2.22.4", + "hardhat": "^2.22.6", "husky": "^9.0.11", "lint-staged": "^15.2.5", "prettier": "^3.2.5", @@ -1692,82 +1692,90 @@ } }, "node_modules/@nomicfoundation/edr": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.3.8.tgz", - "integrity": "sha512-u2UJ5QpznSHVkZRh6ePWoeVb6kmPrrqh08gCnZ9FHlJV9CITqlrTQHJkacd+INH31jx88pTAJnxePE4XAiH5qg==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.4.1.tgz", + "integrity": "sha512-NgrMo2rI9r28uidumvd+K2/AJLdxtXsUlJr3hj/pM6S1FCd/HiWaLeLa/cjCVPcE2u1rYAa3W6UFxLCB7S5Dhw==", "dev": true, + "license": "MIT", "dependencies": { - "@nomicfoundation/edr-darwin-arm64": "0.3.8", - "@nomicfoundation/edr-darwin-x64": "0.3.8", - "@nomicfoundation/edr-linux-arm64-gnu": "0.3.8", - "@nomicfoundation/edr-linux-arm64-musl": "0.3.8", - "@nomicfoundation/edr-linux-x64-gnu": "0.3.8", - "@nomicfoundation/edr-linux-x64-musl": "0.3.8", - "@nomicfoundation/edr-win32-x64-msvc": "0.3.8" + "@nomicfoundation/edr-darwin-arm64": "0.4.1", + "@nomicfoundation/edr-darwin-x64": "0.4.1", + "@nomicfoundation/edr-linux-arm64-gnu": "0.4.1", + "@nomicfoundation/edr-linux-arm64-musl": "0.4.1", + "@nomicfoundation/edr-linux-x64-gnu": "0.4.1", + "@nomicfoundation/edr-linux-x64-musl": "0.4.1", + "@nomicfoundation/edr-win32-x64-msvc": "0.4.1" }, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-darwin-arm64": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.3.8.tgz", - "integrity": "sha512-eB0leCexS8sQEmfyD72cdvLj9djkBzQGP4wSQw6SNf2I4Sw4Cnzb3d45caG2FqFFjbvfqL0t+badUUIceqQuMw==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.4.1.tgz", + "integrity": "sha512-XuiUUnWAVNw7JYv7nRqDWfpBm21HOxCRBQ8lQnRnmiets9Ss2X5Ul9mvBheIPh/D0wBzwJ8TRtsSrorpwE79cA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-darwin-x64": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.3.8.tgz", - "integrity": "sha512-JksVCS1N5ClwVF14EvO25HCQ+Laljh/KRfHERMVAC9ZwPbTuAd/9BtKvToCBi29uCHWqsXMI4lxCApYQv2nznw==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.4.1.tgz", + "integrity": "sha512-N1MfJqEX5ixaXlyyrHnaYxzwIT27Nc/jUgLI7ts4/9kRvPTvyZRYmXS1ciKhmUFr/WvFckTCix2RJbZoGGtX7g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.3.8.tgz", - "integrity": "sha512-raCE+fOeNXhVBLUo87cgsHSGvYYRB6arih4eG6B9KGACWK5Veebtm9xtKeiD8YCsdUlUfat6F7ibpeNm91fpsA==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.4.1.tgz", + "integrity": "sha512-bSPOfmcFjJwDgWOV5kgZHeqg2OWu1cINrHSGjig0aVHehjcoX4Sgayrj6fyAxcOV5NQKA6WcyTFll6NrCxzWRA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-arm64-musl": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.3.8.tgz", - "integrity": "sha512-PwiDp4wBZWMCIy29eKkv8moTKRrpiSDlrc+GQMSZLhOAm8T33JKKXPwD/2EbplbhCygJDGXZdtEKl9x9PaH66A==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.4.1.tgz", + "integrity": "sha512-F/+DgOdeBFQDrk+SX4aFffJFBgJfd75ZtE2mjcWNAh/qWiS7NfUxdQX/5OvNo/H6EY4a+3bZH6Bgzqg4mEWvMw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-x64-gnu": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.3.8.tgz", - "integrity": "sha512-6AcvA/XKoipGap5jJmQ9Y6yT7Uf39D9lu2hBcDCXnXbMcXaDGw4mn1/L4R63D+9VGZyu1PqlcJixCUZlGGIWlg==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.4.1.tgz", + "integrity": "sha512-POHhTWczIXCPhzKtY0Vt/l+VCqqCx5gNR5ErwSrNnLz/arfQobZFAU+nc61BX3Jch82TW8b3AbfGI73Kh7gO0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-x64-musl": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.3.8.tgz", - "integrity": "sha512-cxb0sEmZjlwhYWO28sPsV64VDx31ekskhC1IsDXU1p9ntjHSJRmW4KEIqJ2O3QwJap/kLKfMS6TckvY10gjc6w==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.4.1.tgz", + "integrity": "sha512-uu8oNp4Ozg3H1x1We0FF+rwXfFiAvsOm5GQ+OBx9YYOXnfDPWqguQfGIkhrti9GD0iYhfQ/WOG5wvp0IzzgGSg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-win32-x64-msvc": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.3.8.tgz", - "integrity": "sha512-yVuVPqRRNLZk7TbBMkKw7lzCvI8XO8fNTPTYxymGadjr9rEGRuNTU1yBXjfJ59I1jJU/X2TSkRk1OFX0P5tpZQ==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.4.1.tgz", + "integrity": "sha512-PaZHFw455z89ZiKYNTnKu+/TiVZVRI+mRJsbRTe2N0VlYfUBS1o2gdXBM12oP1t198HR7xQwEPPAslTFxGBqHA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 18" } @@ -4847,7 +4855,8 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/command-line-args": { "version": "5.2.1", @@ -7467,14 +7476,15 @@ } }, "node_modules/hardhat": { - "version": "2.22.4", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.4.tgz", - "integrity": "sha512-09qcXJFBHQUaraJkYNr7XlmwjOj27xBB0SL2rYS024hTj9tPMbp26AFjlf5quBMO9SR4AJFg+4qWahcYcvXBuQ==", + "version": "2.22.6", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.6.tgz", + "integrity": "sha512-abFEnd9QACwEtSvZZGSmzvw7N3zhQN1cDKz5SLHAupfG24qTHofCjqvD5kT5Wwsq5XOL0ON1Mq5rr4v0XX5ciw==", "dev": true, + "license": "MIT", "dependencies": { "@ethersproject/abi": "^5.1.2", "@metamask/eth-sig-util": "^4.0.0", - "@nomicfoundation/edr": "^0.3.7", + "@nomicfoundation/edr": "^0.4.1", "@nomicfoundation/ethereumjs-common": "4.0.4", "@nomicfoundation/ethereumjs-tx": "5.0.4", "@nomicfoundation/ethereumjs-util": "9.0.4", @@ -7508,7 +7518,7 @@ "raw-body": "^2.4.1", "resolve": "1.17.0", "semver": "^6.3.0", - "solc": "0.7.3", + "solc": "0.8.26", "source-map-support": "^0.5.13", "stacktrace-parser": "^0.1.10", "tsort": "0.0.1", @@ -8731,15 +8741,6 @@ "node": ">=0.10.0" } }, - "node_modules/klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.9" - } - }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -10047,6 +10048,7 @@ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -11453,110 +11455,35 @@ } }, "node_modules/solc": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz", - "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==", + "version": "0.8.26", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.26.tgz", + "integrity": "sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==", "dev": true, + "license": "MIT", "dependencies": { "command-exists": "^1.2.8", - "commander": "3.0.2", + "commander": "^8.1.0", "follow-redirects": "^1.12.1", - "fs-extra": "^0.30.0", "js-sha3": "0.8.0", "memorystream": "^0.3.1", - "require-from-string": "^2.0.0", "semver": "^5.5.0", "tmp": "0.0.33" }, "bin": { - "solcjs": "solcjs" + "solcjs": "solc.js" }, "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/solc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node": ">=10.0.0" } }, "node_modules/solc/node_modules/commander": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", - "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", - "dev": true - }, - "node_modules/solc/node_modules/fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, - "node_modules/solc/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/solc/node_modules/jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/solc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", "engines": { - "node": "*" - } - }, - "node_modules/solc/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "node": ">= 12" } }, "node_modules/solc/node_modules/semver": { @@ -11564,6 +11491,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -12594,6 +12522,7 @@ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, + "license": "MIT", "dependencies": { "os-tmpdir": "~1.0.2" }, diff --git a/package.json b/package.json index 4251eb2b..0dd8cafd 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "eth-gas-reporter": "^0.2.27", "fs-extra": "^11.2.0", "glob": "^10.4.1", - "hardhat": "^2.22.4", + "hardhat": "^2.22.6", "husky": "^9.0.11", "lint-staged": "^15.2.5", "prettier": "^3.2.5", diff --git a/test/authorities/trex-implementation-authority.test.ts b/test/authorities/trex-implementation-authority.test.ts index f79dabf2..38aed713 100644 --- a/test/authorities/trex-implementation-authority.test.ts +++ b/test/authorities/trex-implementation-authority.test.ts @@ -57,7 +57,7 @@ describe('TrexImplementationAuthority', () => { deployer, ); - await expect(trexImplementationAuthority.setTREXFactory(trexFactory.target)).to.be.revertedWith('only reference contract can call'); + await expect(trexImplementationAuthority.setTREXFactory(trexFactory.target)).to.be.revertedWithCustomError(trexImplementationAuthority, 'OnlyReferenceContractCanCall'); }); }); @@ -134,7 +134,7 @@ describe('TrexImplementationAuthority', () => { patch: 0, }; - await expect(trexImplementationAuthority.fetchVersion(versionStruct)).to.be.revertedWith('cannot call on reference contract'); + await expect(trexImplementationAuthority.fetchVersion(versionStruct)).to.be.revertedWithCustomError(trexImplementationAuthority, 'CannotCallOnReferenceContract'); }); }); @@ -162,7 +162,7 @@ describe('TrexImplementationAuthority', () => { await otherTrexImplementationAuthority.fetchVersion(versionStruct); - await expect(otherTrexImplementationAuthority.fetchVersion(versionStruct)).to.be.revertedWith('version fetched already'); + await expect(otherTrexImplementationAuthority.fetchVersion(versionStruct)).to.be.revertedWithCustomError(otherTrexImplementationAuthority, 'VersionAlreadyFetched'); }); }); @@ -255,8 +255,9 @@ describe('TrexImplementationAuthority', () => { mcImplementation: implementations.modularComplianceImplementation.target, }; - await expect(otherTrexImplementationAuthority.addTREXVersion(versionStruct, contractsStruct)).to.be.revertedWith( - 'ONLY reference contract can add versions', + await expect(otherTrexImplementationAuthority.addTREXVersion(versionStruct, contractsStruct)).to.be.revertedWithCustomError( + otherTrexImplementationAuthority, + 'OnlyReferenceContractCanAddVersion', ); }); }); @@ -406,8 +407,9 @@ describe('TrexImplementationAuthority', () => { deployer, ); - await expect(otherTrexImplementationAuthority.changeImplementationAuthority(token.target, ethers.ZeroAddress)).to.be.revertedWith( - 'only reference contract can deploy new IAs', + await expect(otherTrexImplementationAuthority.changeImplementationAuthority(token.target, ethers.ZeroAddress)).to.be.revertedWithCustomError( + otherTrexImplementationAuthority, + 'OnlyReferenceContractCanDeployNewIA', ); }); }); @@ -423,7 +425,7 @@ describe('TrexImplementationAuthority', () => { await expect( trexImplementationAuthority.connect(anotherWallet).changeImplementationAuthority(token.target, ethers.ZeroAddress), - ).to.be.revertedWith('caller NOT owner of all contracts impacted'); + ).to.be.revertedWithCustomError(trexImplementationAuthority, 'CallerNotOwnerOfAllImpactedContracts'); }); }); @@ -492,7 +494,7 @@ describe('TrexImplementationAuthority', () => { await expect( trexImplementationAuthority.changeImplementationAuthority(token.target, otherTrexImplementationAuthority.target), - ).to.be.revertedWith('version of new IA has to be the same as current IA'); + ).to.be.revertedWithCustomError(trexImplementationAuthority, 'VersionOfNewIAMustBeTheSameAsCurrentIA'); }); }); @@ -534,7 +536,7 @@ describe('TrexImplementationAuthority', () => { await expect( trexImplementationAuthority.changeImplementationAuthority(token.target, otherTrexImplementationAuthority.target), - ).to.be.revertedWith('new IA is NOT reference contract'); + ).to.be.revertedWithCustomError(trexImplementationAuthority, 'NewIAIsNotAReferenceContract'); }); }); @@ -566,7 +568,7 @@ describe('TrexImplementationAuthority', () => { await expect( trexImplementationAuthority.changeImplementationAuthority(token.target, otherTrexImplementationAuthority.target), - ).to.be.revertedWith('invalid IA'); + ).to.be.revertedWithCustomError(trexImplementationAuthority, 'InvalidIA'); }); }); }); diff --git a/test/compliance.test.ts b/test/compliance.test.ts index d904e53f..f4268b59 100644 --- a/test/compliance.test.ts +++ b/test/compliance.test.ts @@ -26,7 +26,7 @@ describe('ModularCompliance', () => { suite: { token, compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.connect(anotherWallet).bindToken(token.target)).to.be.revertedWith('only owner or token can call'); + await expect(compliance.connect(anotherWallet).bindToken(token.target)).to.be.revertedWithCustomError(compliance, 'OnlyOwnerOrTokenCanCall'); }); }); @@ -43,7 +43,7 @@ describe('ModularCompliance', () => { await compliance.bindToken(token.target); - await expect(compliance.connect(anotherWallet).bindToken(token.target)).to.be.revertedWith('only owner or token can call'); + await expect(compliance.connect(anotherWallet).bindToken(token.target)).to.be.revertedWithCustomError(compliance, 'OnlyOwnerOrTokenCanCall'); }); }); @@ -90,7 +90,7 @@ describe('ModularCompliance', () => { suite: { token, compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.connect(anotherWallet).unbindToken(token.target)).to.be.revertedWith('only owner or token can call'); + await expect(compliance.connect(anotherWallet).unbindToken(token.target)).to.be.revertedWithCustomError(compliance, 'OnlyOwnerOrTokenCanCall'); }); }); @@ -115,7 +115,7 @@ describe('ModularCompliance', () => { const compliance = await ethers.deployContract('ModularCompliance', deployer); await compliance.init(); - await expect(compliance.unbindToken(token.target)).to.be.revertedWith('This token is not bound'); + await expect(compliance.unbindToken(token.target)).to.be.revertedWithCustomError(compliance, 'TokenNotBound'); }); }); }); @@ -170,7 +170,7 @@ describe('ModularCompliance', () => { const module = await ethers.deployContract('CountryAllowModule'); await compliance.addModule(module.target); - await expect(compliance.addModule(module.target)).to.be.revertedWith('module already bound'); + await expect(compliance.addModule(module.target)).to.be.revertedWithCustomError(compliance, 'ModuleAlreadyBound'); }); }); @@ -184,7 +184,7 @@ describe('ModularCompliance', () => { await compliance.connect(accounts.deployer).bindToken(token.target); const module = await ethers.deployContract('MaxBalanceModule'); - await expect(compliance.addModule(module.target)).to.be.revertedWith('compliance is not suitable for binding to the module'); + await expect(compliance.addModule(module.target)).to.be.revertedWithCustomError(compliance, 'ComplianceNotSuitableForBindingToModule'); }); }); @@ -234,7 +234,7 @@ describe('ModularCompliance', () => { const module = await ethers.deployContract('CountryAllowModule'); - await expect(compliance.addModule(module.target)).to.be.revertedWith('cannot add more than 25 modules'); + await expect(compliance.addModule(module.target)).to.be.revertedWithCustomError(compliance, 'CannotAddMoreThan25Modules'); }); }); }); @@ -271,7 +271,7 @@ describe('ModularCompliance', () => { const module = await ethers.deployContract('CountryAllowModule'); - await expect(compliance.removeModule(module.target)).to.be.revertedWith('module not bound'); + await expect(compliance.removeModule(module.target)).to.be.revertedWithCustomError(compliance, 'ModuleNotBound'); }); }); @@ -305,8 +305,9 @@ describe('ModularCompliance', () => { suite: { compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.connect(anotherWallet).transferred(ethers.ZeroAddress, ethers.ZeroAddress, 0)).to.be.revertedWith( - 'error : this address is not a token bound to the compliance contract', + await expect(compliance.connect(anotherWallet).transferred(ethers.ZeroAddress, ethers.ZeroAddress, 0)).to.be.revertedWithCustomError( + compliance, + 'AddressNotATokenBoundToComplianceContract', ); }); }); @@ -347,8 +348,9 @@ describe('ModularCompliance', () => { accounts: { aliceWallet, bobWallet, charlieWallet }, } = await loadFixture(deploySuiteWithModuleComplianceBoundToWallet); - await expect(compliance.connect(charlieWallet).transferred(aliceWallet.address, bobWallet.address, 0)).to.be.revertedWith( - 'invalid argument - no value transfer', + await expect(compliance.connect(charlieWallet).transferred(aliceWallet.address, bobWallet.address, 0)).to.be.revertedWithCustomError( + compliance, + 'NoValue', ); }); }); @@ -374,8 +376,9 @@ describe('ModularCompliance', () => { suite: { compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.connect(anotherWallet).created(ethers.ZeroAddress, 0)).to.be.revertedWith( - 'error : this address is not a token bound to the compliance contract', + await expect(compliance.connect(anotherWallet).created(ethers.ZeroAddress, 0)).to.be.revertedWithCustomError( + compliance, + 'AddressNotATokenBoundToComplianceContract', ); }); }); @@ -399,7 +402,7 @@ describe('ModularCompliance', () => { accounts: { bobWallet, charlieWallet }, } = await loadFixture(deploySuiteWithModuleComplianceBoundToWallet); - await expect(compliance.connect(charlieWallet).created(bobWallet.address, 0)).to.be.revertedWith('invalid argument - no value mint'); + await expect(compliance.connect(charlieWallet).created(bobWallet.address, 0)).to.be.revertedWithCustomError(compliance, 'NoValue'); }); }); @@ -424,8 +427,9 @@ describe('ModularCompliance', () => { suite: { compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.connect(anotherWallet).destroyed(ethers.ZeroAddress, 0)).to.be.revertedWith( - 'error : this address is not a token bound to the compliance contract', + await expect(compliance.connect(anotherWallet).destroyed(ethers.ZeroAddress, 0)).to.be.revertedWithCustomError( + compliance, + 'AddressNotATokenBoundToComplianceContract', ); }); }); @@ -449,7 +453,7 @@ describe('ModularCompliance', () => { accounts: { aliceWallet, charlieWallet }, } = await loadFixture(deploySuiteWithModuleComplianceBoundToWallet); - await expect(compliance.connect(charlieWallet).destroyed(aliceWallet.address, 0)).to.be.revertedWith('invalid argument - no value burn'); + await expect(compliance.connect(charlieWallet).destroyed(aliceWallet.address, 0)).to.be.revertedWithCustomError(compliance, 'NoValue'); }); }); @@ -487,8 +491,9 @@ describe('ModularCompliance', () => { suite: { compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.connect(deployer).callModuleFunction(ethers.randomBytes(32), ethers.ZeroAddress)).to.be.revertedWith( - 'call only on bound module', + await expect(compliance.connect(deployer).callModuleFunction(ethers.randomBytes(32), ethers.ZeroAddress)).to.be.revertedWithCustomError( + compliance, + 'ModuleNotBound', ); }); }); diff --git a/test/compliances/module-conditional-transfer.test.ts b/test/compliances/module-conditional-transfer.test.ts index 275d9b42..da2d5970 100644 --- a/test/compliances/module-conditional-transfer.test.ts +++ b/test/compliances/module-conditional-transfer.test.ts @@ -128,7 +128,7 @@ describe('ConditionalTransferModule', () => { await expect( conditionalTransferModule.connect(anotherWallet).batchApproveTransfers([anotherWallet.address], [anotherWallet.address], [10]), - ).to.be.revertedWith('only bound compliance can call'); + ).to.be.revertedWithCustomError(conditionalTransferModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -181,7 +181,7 @@ describe('ConditionalTransferModule', () => { await expect( conditionalTransferModule.connect(anotherWallet).batchUnApproveTransfers([anotherWallet.address], [anotherWallet.address], [10]), - ).to.be.revertedWith('only bound compliance can call'); + ).to.be.revertedWithCustomError(conditionalTransferModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -203,7 +203,7 @@ describe('ConditionalTransferModule', () => { ), conditionalTransferModule.target, ), - ).to.be.revertedWith('not approved'); + ).to.be.revertedWithCustomError(conditionalTransferModule, 'NotApproved'); }); }); @@ -258,7 +258,7 @@ describe('ConditionalTransferModule', () => { await expect( conditionalTransferModule.connect(anotherWallet).approveTransfer(anotherWallet.address, anotherWallet.address, 10), - ).to.be.revertedWith('only bound compliance can call'); + ).to.be.revertedWithCustomError(conditionalTransferModule, 'OnlyBoundComplianceCanCall'); }); }); }); @@ -273,7 +273,7 @@ describe('ConditionalTransferModule', () => { await expect( conditionalTransferModule.connect(anotherWallet).unApproveTransfer(anotherWallet.address, anotherWallet.address, 10), - ).to.be.revertedWith('only bound compliance can call'); + ).to.be.revertedWithCustomError(conditionalTransferModule, 'OnlyBoundComplianceCanCall'); }); }); }); @@ -321,7 +321,7 @@ describe('ConditionalTransferModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithConditionalTransferModule); - await expect(conditionalTransferModule.moduleBurnAction(anotherWallet.address, 10)).to.be.revertedWith('only bound compliance can call'); + await expect(conditionalTransferModule.moduleBurnAction(anotherWallet.address, 10)).to.be.revertedWithCustomError(conditionalTransferModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -355,7 +355,7 @@ describe('ConditionalTransferModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithConditionalTransferModule); - await expect(conditionalTransferModule.moduleMintAction(anotherWallet.address, 10)).to.be.revertedWith('only bound compliance can call'); + await expect(conditionalTransferModule.moduleMintAction(anotherWallet.address, 10)).to.be.revertedWithCustomError(conditionalTransferModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -391,7 +391,7 @@ describe('ConditionalTransferModule', () => { await expect( conditionalTransferModule.connect(anotherWallet).moduleTransferAction(aliceWallet.address, bobWallet.address, 10), - ).to.be.revertedWith('only bound compliance can call'); + ).to.be.revertedWithCustomError(conditionalTransferModule, 'OnlyBoundComplianceCanCall'); }); }); diff --git a/test/compliances/module-country-allow.test.ts b/test/compliances/module-country-allow.test.ts index 48938644..baf461d0 100644 --- a/test/compliances/module-country-allow.test.ts +++ b/test/compliances/module-country-allow.test.ts @@ -139,7 +139,7 @@ describe('CountryAllowModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(anotherWallet).batchAllowCountries([42, 66])).to.be.revertedWith('only bound compliance can call'); + await expect(countryAllowModule.connect(anotherWallet).batchAllowCountries([42, 66])).to.be.revertedWithCustomError(countryAllowModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -150,7 +150,7 @@ describe('CountryAllowModule', () => { accounts: { deployer }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(deployer).batchAllowCountries([42, 66])).to.be.revertedWith('only bound compliance can call'); + await expect(countryAllowModule.connect(deployer).batchAllowCountries([42, 66])).to.be.revertedWithCustomError(countryAllowModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -185,7 +185,7 @@ describe('CountryAllowModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(anotherWallet).batchDisallowCountries([42, 66])).to.be.revertedWith('only bound compliance can call'); + await expect(countryAllowModule.connect(anotherWallet).batchDisallowCountries([42, 66])).to.be.revertedWithCustomError(countryAllowModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -196,7 +196,7 @@ describe('CountryAllowModule', () => { accounts: { deployer }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(deployer).batchDisallowCountries([42, 66])).to.be.revertedWith('only bound compliance can call'); + await expect(countryAllowModule.connect(deployer).batchDisallowCountries([42, 66])).to.be.revertedWithCustomError(countryAllowModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -233,7 +233,7 @@ describe('CountryAllowModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(anotherWallet).addAllowedCountry(42)).to.be.revertedWith('only bound compliance can call'); + await expect(countryAllowModule.connect(anotherWallet).addAllowedCountry(42)).to.be.revertedWithCustomError(countryAllowModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -244,7 +244,7 @@ describe('CountryAllowModule', () => { accounts: { deployer }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(deployer).addAllowedCountry(42)).to.be.revertedWith('only bound compliance can call'); + await expect(countryAllowModule.connect(deployer).addAllowedCountry(42)).to.be.revertedWithCustomError(countryAllowModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -306,7 +306,7 @@ describe('CountryAllowModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(anotherWallet).removeAllowedCountry(42)).to.be.revertedWith('only bound compliance can call'); + await expect(countryAllowModule.connect(anotherWallet).removeAllowedCountry(42)).to.be.revertedWithCustomError(countryAllowModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -317,7 +317,7 @@ describe('CountryAllowModule', () => { accounts: { deployer }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(deployer).removeAllowedCountry(42)).to.be.revertedWith('only bound compliance can call'); + await expect(countryAllowModule.connect(deployer).removeAllowedCountry(42)).to.be.revertedWithCustomError(countryAllowModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -449,8 +449,9 @@ describe('CountryAllowModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(anotherWallet).unbindCompliance(compliance.target)).to.be.revertedWith( - 'only bound compliance can call', + await expect(countryAllowModule.connect(anotherWallet).unbindCompliance(compliance.target)).to.be.revertedWithCustomError( + countryAllowModule, + 'OnlyBoundComplianceCanCall', ); }); }); diff --git a/test/compliances/module-country-restrict.test.ts b/test/compliances/module-country-restrict.test.ts index 4e93f6d2..00277ea7 100644 --- a/test/compliances/module-country-restrict.test.ts +++ b/test/compliances/module-country-restrict.test.ts @@ -120,7 +120,7 @@ describe('CountryRestrictModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect(countryRestrictModule.connect(anotherWallet).addCountryRestriction(42)).to.be.revertedWith('only bound compliance can call'); + await expect(countryRestrictModule.connect(anotherWallet).addCountryRestriction(42)).to.be.revertedWithCustomError(countryRestrictModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -131,7 +131,7 @@ describe('CountryRestrictModule', () => { accounts: { deployer }, } = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect(countryRestrictModule.connect(deployer).addCountryRestriction(42)).to.be.revertedWith('only bound compliance can call'); + await expect(countryRestrictModule.connect(deployer).addCountryRestriction(42)).to.be.revertedWithCustomError(countryRestrictModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -157,7 +157,7 @@ describe('CountryRestrictModule', () => { new ethers.Interface(['function addCountryRestriction(uint16 country)']).encodeFunctionData('addCountryRestriction', [42]), countryRestrictModule.target, ), - ).to.be.revertedWith('country already restricted'); + ).to.be.revertedWithCustomError(countryRestrictModule, 'CountryAlreadyRestricted'); }); }); @@ -191,7 +191,7 @@ describe('CountryRestrictModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect(countryRestrictModule.connect(anotherWallet).removeCountryRestriction(42)).to.be.revertedWith('only bound compliance can call'); + await expect(countryRestrictModule.connect(anotherWallet).removeCountryRestriction(42)).to.be.revertedWithCustomError(countryRestrictModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -202,7 +202,7 @@ describe('CountryRestrictModule', () => { accounts: { deployer }, } = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect(countryRestrictModule.connect(deployer).removeCountryRestriction(42)).to.be.revertedWith('only bound compliance can call'); + await expect(countryRestrictModule.connect(deployer).removeCountryRestriction(42)).to.be.revertedWithCustomError(countryRestrictModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -221,7 +221,7 @@ describe('CountryRestrictModule', () => { new ethers.Interface(['function removeCountryRestriction(uint16 country)']).encodeFunctionData('removeCountryRestriction', [42]), countryRestrictModule.target, ), - ).to.be.revertedWith('country not restricted'); + ).to.be.revertedWithCustomError(countryRestrictModule, 'CountryNotRestricted'); }); }); @@ -262,7 +262,7 @@ describe('CountryRestrictModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect(countryRestrictModule.connect(anotherWallet).batchRestrictCountries([42])).to.be.revertedWith('only bound compliance can call'); + await expect(countryRestrictModule.connect(anotherWallet).batchRestrictCountries([42])).to.be.revertedWithCustomError(countryRestrictModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -273,7 +273,7 @@ describe('CountryRestrictModule', () => { accounts: { deployer }, } = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect(countryRestrictModule.connect(deployer).batchRestrictCountries([42])).to.be.revertedWith('only bound compliance can call'); + await expect(countryRestrictModule.connect(deployer).batchRestrictCountries([42])).to.be.revertedWithCustomError(countryRestrictModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -294,7 +294,7 @@ describe('CountryRestrictModule', () => { ]), countryRestrictModule.target, ), - ).to.be.revertedWith('maximum 195 can be restricted in one batch'); + ).to.be.revertedWithCustomError(countryRestrictModule, 'Max195CountriesInBatch'); }); }); @@ -321,7 +321,7 @@ describe('CountryRestrictModule', () => { ]), countryRestrictModule.target, ), - ).to.be.revertedWith('country already restricted'); + ).to.be.revertedWithCustomError(countryRestrictModule, 'CountryAlreadyRestricted'); }); }); @@ -357,8 +357,9 @@ describe('CountryRestrictModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect(countryRestrictModule.connect(anotherWallet).batchUnrestrictCountries([42])).to.be.revertedWith( - 'only bound compliance can call', + await expect(countryRestrictModule.connect(anotherWallet).batchUnrestrictCountries([42])).to.be.revertedWithCustomError( + countryRestrictModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -370,7 +371,7 @@ describe('CountryRestrictModule', () => { accounts: { deployer }, } = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect(countryRestrictModule.connect(deployer).batchUnrestrictCountries([42])).to.be.revertedWith('only bound compliance can call'); + await expect(countryRestrictModule.connect(deployer).batchUnrestrictCountries([42])).to.be.revertedWithCustomError(countryRestrictModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -392,7 +393,7 @@ describe('CountryRestrictModule', () => { ), countryRestrictModule.target, ), - ).to.be.revertedWith('maximum 195 can be unrestricted in one batch'); + ).to.be.revertedWithCustomError(countryRestrictModule, 'Max195CountriesInBatch'); }); }); @@ -413,7 +414,7 @@ describe('CountryRestrictModule', () => { ), countryRestrictModule.target, ), - ).to.be.revertedWith('country not restricted'); + ).to.be.revertedWithCustomError(countryRestrictModule, 'CountryNotRestricted'); }); }); @@ -460,7 +461,7 @@ describe('CountryRestrictModule', () => { await expect( countryRestrictModule.connect(anotherWallet).moduleTransferAction(aliceWallet.address, bobWallet.address, 10), - ).to.be.revertedWith('only bound compliance can call'); + ).to.be.revertedWithCustomError(countryRestrictModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -495,8 +496,9 @@ describe('CountryRestrictModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect(countryRestrictModule.connect(anotherWallet).moduleMintAction(anotherWallet.address, 10)).to.be.revertedWith( - 'only bound compliance can call', + await expect(countryRestrictModule.connect(anotherWallet).moduleMintAction(anotherWallet.address, 10)).to.be.revertedWithCustomError( + countryRestrictModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -531,8 +533,9 @@ describe('CountryRestrictModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect(countryRestrictModule.connect(anotherWallet).moduleBurnAction(anotherWallet.address, 10)).to.be.revertedWith( - 'only bound compliance can call', + await expect(countryRestrictModule.connect(anotherWallet).moduleBurnAction(anotherWallet.address, 10)).to.be.revertedWithCustomError( + countryRestrictModule, + 'OnlyBoundComplianceCanCall', ); }); }); diff --git a/test/compliances/module-exchange-monthly-limits.test.ts b/test/compliances/module-exchange-monthly-limits.test.ts index f9388984..9581ab0b 100644 --- a/test/compliances/module-exchange-monthly-limits.test.ts +++ b/test/compliances/module-exchange-monthly-limits.test.ts @@ -148,7 +148,9 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { const context = await loadFixture(deployExchangeMonthlyLimitsFixture); const exchangeID = context.accounts.anotherWallet.address; - await expect(context.contracts.complianceModule.setExchangeMonthlyLimit(exchangeID, 1)).to.revertedWith('only bound compliance can call'); + await expect(context.contracts.complianceModule.setExchangeMonthlyLimit(exchangeID, 1)).to.revertedWithCustomError( + context.contracts.complianceModule, + 'OnlyBoundComplianceCanCall'); }); }); @@ -298,7 +300,10 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { const from = context.accounts.aliceWallet.address; const to = context.accounts.bobWallet.address; - await expect(context.contracts.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWith('only bound compliance can call'); + await expect(context.contracts.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWithCustomError( + context.contracts.complianceModule, + 'OnlyBoundComplianceCanCall' + ); }); }); @@ -653,8 +658,9 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { it('should revert', async () => { const context = await loadFixture(deployExchangeMonthlyLimitsFixture); - await expect(context.contracts.complianceModule.moduleMintAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWith( - 'only bound compliance can call', + await expect(context.contracts.complianceModule.moduleMintAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWithCustomError( + context.contracts.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -681,8 +687,9 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { it('should revert', async () => { const context = await loadFixture(deployExchangeMonthlyLimitsFixture); - await expect(context.contracts.complianceModule.moduleBurnAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWith( - 'only bound compliance can call', + await expect(context.contracts.complianceModule.moduleBurnAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWithCustomError( + context.contracts.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); diff --git a/test/compliances/module-max-balance.test.ts b/test/compliances/module-max-balance.test.ts index dbd08775..7b2d6238 100644 --- a/test/compliances/module-max-balance.test.ts +++ b/test/compliances/module-max-balance.test.ts @@ -87,7 +87,7 @@ describe('Compliance Module: MaxBalance', () => { it('should revert', async () => { const context = await loadFixture(deployMaxBalanceFullSuite); - await expect(context.suite.complianceModule.setMaxBalance(100)).to.revertedWith('only bound compliance can call'); + await expect(context.suite.complianceModule.setMaxBalance(100)).to.revertedWithCustomError(context.suite.complianceModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -319,7 +319,7 @@ describe('Compliance Module: MaxBalance', () => { const from = context.accounts.aliceWallet.address; const to = context.accounts.bobWallet.address; - await expect(context.suite.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWith('only bound compliance can call'); + await expect(context.suite.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWithCustomError(context.suite.complianceModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -407,7 +407,7 @@ describe('Compliance Module: MaxBalance', () => { const context = await loadFixture(deployMaxBalanceFullSuite); const to = context.accounts.bobWallet.address; - await expect(context.suite.complianceModule.moduleMintAction(to, 10)).to.revertedWith('only bound compliance can call'); + await expect(context.suite.complianceModule.moduleMintAction(to, 10)).to.revertedWithCustomError(context.suite.complianceModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -460,7 +460,7 @@ describe('Compliance Module: MaxBalance', () => { const context = await loadFixture(deployMaxBalanceFullSuite); const from = context.accounts.bobWallet.address; - await expect(context.suite.complianceModule.moduleBurnAction(from, 10)).to.revertedWith('only bound compliance can call'); + await expect(context.suite.complianceModule.moduleBurnAction(from, 10)).to.revertedWithCustomError(context.suite.complianceModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -503,7 +503,7 @@ describe('Compliance Module: MaxBalance', () => { context.suite.complianceModule.target, ); - await expect(context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.target)).to.revertedWith('identity not found'); + await expect(context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.target)).to.revertedWithCustomError(context.suite.complianceModule, 'IdentityNotFound'); }); }); diff --git a/test/compliances/module-supply-limit.test.ts b/test/compliances/module-supply-limit.test.ts index 05d5022d..02a34bd4 100644 --- a/test/compliances/module-supply-limit.test.ts +++ b/test/compliances/module-supply-limit.test.ts @@ -146,7 +146,7 @@ describe('Compliance Module: SupplyLimit', () => { it('should revert', async () => { const context = await loadFixture(deploySupplyLimitFixture); - await expect(context.suite.complianceModule.setSupplyLimit(100)).to.revertedWith('only bound compliance can call'); + await expect(context.suite.complianceModule.setSupplyLimit(100)).to.revertedWithCustomError(context.suite.complianceModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -219,7 +219,7 @@ describe('Compliance Module: SupplyLimit', () => { await expect( context.suite.complianceModule.moduleTransferAction(context.accounts.anotherWallet.address, context.accounts.anotherWallet.address, 10), - ).to.be.revertedWith('only bound compliance can call'); + ).to.be.revertedWithCustomError(context.suite.complianceModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -245,8 +245,9 @@ describe('Compliance Module: SupplyLimit', () => { it('should revert', async () => { const context = await loadFixture(deploySupplyLimitFullSuite); - await expect(context.suite.complianceModule.moduleMintAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWith( - 'only bound compliance can call', + await expect(context.suite.complianceModule.moduleMintAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -273,8 +274,9 @@ describe('Compliance Module: SupplyLimit', () => { it('should revert', async () => { const context = await loadFixture(deploySupplyLimitFullSuite); - await expect(context.suite.complianceModule.moduleBurnAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWith( - 'only bound compliance can call', + await expect(context.suite.complianceModule.moduleBurnAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); diff --git a/test/compliances/module-time-exchange-limits.test.ts b/test/compliances/module-time-exchange-limits.test.ts index 561b887c..474a8951 100644 --- a/test/compliances/module-time-exchange-limits.test.ts +++ b/test/compliances/module-time-exchange-limits.test.ts @@ -134,8 +134,9 @@ describe('Compliance Module: TimeExchangeLimits', () => { const context = await loadFixture(deployTimeExchangeLimitsFixture); const exchangeID = context.accounts.anotherWallet.address; - await expect(context.contracts.complianceModule.setExchangeLimit(exchangeID, { limitTime: 1, limitValue: 100 })).to.revertedWith( - 'only bound compliance can call', + await expect(context.contracts.complianceModule.setExchangeLimit(exchangeID, { limitTime: 1, limitValue: 100 })).to.revertedWithCustomError( + context.contracts.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -400,7 +401,7 @@ describe('Compliance Module: TimeExchangeLimits', () => { const from = context.accounts.aliceWallet.address; const to = context.accounts.bobWallet.address; - await expect(context.contracts.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWith('only bound compliance can call'); + await expect(context.contracts.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWithCustomError(context.contracts.complianceModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -797,8 +798,9 @@ describe('Compliance Module: TimeExchangeLimits', () => { it('should revert', async () => { const context = await loadFixture(deployTimeExchangeLimitsFixture); - await expect(context.contracts.complianceModule.moduleMintAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWith( - 'only bound compliance can call', + await expect(context.contracts.complianceModule.moduleMintAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWithCustomError( + context.contracts.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -825,8 +827,9 @@ describe('Compliance Module: TimeExchangeLimits', () => { it('should revert', async () => { const context = await loadFixture(deployTimeExchangeLimitsFixture); - await expect(context.contracts.complianceModule.moduleBurnAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWith( - 'only bound compliance can call', + await expect(context.contracts.complianceModule.moduleBurnAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWithCustomError( + context.contracts.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); diff --git a/test/compliances/module-time-transfer-limits.test.ts b/test/compliances/module-time-transfer-limits.test.ts index 3506afac..94f0a97c 100644 --- a/test/compliances/module-time-transfer-limits.test.ts +++ b/test/compliances/module-time-transfer-limits.test.ts @@ -133,8 +133,9 @@ describe('Compliance Module: TimeTransferLimits', () => { it('should revert', async () => { const context = await loadFixture(deployTimeTransferLimitsFixture); - await expect(context.contracts.complianceModule.setTimeTransferLimit({ limitTime: 1, limitValue: 100 })).to.revertedWith( - 'only bound compliance can call', + await expect(context.contracts.complianceModule.setTimeTransferLimit({ limitTime: 1, limitValue: 100 })).to.revertedWithCustomError( + context.contracts.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -278,7 +279,7 @@ describe('Compliance Module: TimeTransferLimits', () => { const from = context.accounts.aliceWallet.address; const to = context.accounts.bobWallet.address; - await expect(context.contracts.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWith('only bound compliance can call'); + await expect(context.contracts.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWithCustomError(context.contracts.complianceModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -574,8 +575,9 @@ describe('Compliance Module: TimeTransferLimits', () => { it('should revert', async () => { const context = await loadFixture(deployTimeTransferLimitsFixture); - await expect(context.contracts.complianceModule.moduleMintAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWith( - 'only bound compliance can call', + await expect(context.contracts.complianceModule.moduleMintAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWithCustomError( + context.contracts.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -602,8 +604,9 @@ describe('Compliance Module: TimeTransferLimits', () => { it('should revert', async () => { const context = await loadFixture(deployTimeTransferLimitsFixture); - await expect(context.contracts.complianceModule.moduleBurnAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWith( - 'only bound compliance can call', + await expect(context.contracts.complianceModule.moduleBurnAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWithCustomError( + context.contracts.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); diff --git a/test/compliances/module-transfer-fees.test.ts b/test/compliances/module-transfer-fees.test.ts index 69d8905b..aa44612e 100644 --- a/test/compliances/module-transfer-fees.test.ts +++ b/test/compliances/module-transfer-fees.test.ts @@ -114,8 +114,9 @@ describe('Compliance Module: TransferFees', () => { const context = await loadFixture(deployTransferFeesFullSuite); const collector = context.accounts.anotherWallet.address; - await expect(context.suite.complianceModule.connect(context.accounts.anotherWallet).setFee(1, collector)).to.revertedWith( - 'only bound compliance can call', + await expect(context.suite.complianceModule.connect(context.accounts.anotherWallet).setFee(1, collector)).to.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -219,7 +220,7 @@ describe('Compliance Module: TransferFees', () => { const from = context.accounts.aliceWallet.address; const to = context.accounts.bobWallet.address; - await expect(context.suite.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWith('only bound compliance can call'); + await expect(context.suite.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWithCustomError(context.suite.complianceModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -385,8 +386,9 @@ describe('Compliance Module: TransferFees', () => { it('should revert', async () => { const context = await loadFixture(deployTransferFeesFullSuite); - await expect(context.suite.complianceModule.moduleMintAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWith( - 'only bound compliance can call', + await expect(context.suite.complianceModule.moduleMintAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -413,8 +415,9 @@ describe('Compliance Module: TransferFees', () => { it('should revert', async () => { const context = await loadFixture(deployTransferFeesFullSuite); - await expect(context.suite.complianceModule.moduleBurnAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWith( - 'only bound compliance can call', + await expect(context.suite.complianceModule.moduleBurnAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); diff --git a/test/compliances/module-transfer-restrict.test.ts b/test/compliances/module-transfer-restrict.test.ts index 909963de..c46ae48d 100644 --- a/test/compliances/module-transfer-restrict.test.ts +++ b/test/compliances/module-transfer-restrict.test.ts @@ -131,8 +131,9 @@ describe('Compliance Module: TransferRestrict', () => { it('should revert', async () => { const context = await loadFixture(deployTransferRestrictFullSuite); - await expect(context.suite.complianceModule.allowUser(context.accounts.aliceWallet.address)).to.revertedWith( - 'only bound compliance can call', + await expect(context.suite.complianceModule.allowUser(context.accounts.aliceWallet.address)).to.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -158,8 +159,9 @@ describe('Compliance Module: TransferRestrict', () => { it('should revert', async () => { const context = await loadFixture(deployTransferRestrictFullSuite); - await expect(context.suite.complianceModule.batchAllowUsers([context.accounts.aliceWallet.address])).to.revertedWith( - 'only bound compliance can call', + await expect(context.suite.complianceModule.batchAllowUsers([context.accounts.aliceWallet.address])).to.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -189,8 +191,9 @@ describe('Compliance Module: TransferRestrict', () => { it('should revert', async () => { const context = await loadFixture(deployTransferRestrictFullSuite); - await expect(context.suite.complianceModule.disallowUser(context.accounts.aliceWallet.address)).to.revertedWith( - 'only bound compliance can call', + await expect(context.suite.complianceModule.disallowUser(context.accounts.aliceWallet.address)).to.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -222,8 +225,9 @@ describe('Compliance Module: TransferRestrict', () => { it('should revert', async () => { const context = await loadFixture(deployTransferRestrictFullSuite); - await expect(context.suite.complianceModule.batchDisallowUsers([context.accounts.aliceWallet.address])).to.revertedWith( - 'only bound compliance can call', + await expect(context.suite.complianceModule.batchDisallowUsers([context.accounts.aliceWallet.address])).to.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -346,8 +350,9 @@ describe('Compliance Module: TransferRestrict', () => { it('should revert', async () => { const context = await loadFixture(deployTransferRestrictFullSuite); - await expect(context.suite.complianceModule.moduleMintAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWith( - 'only bound compliance can call', + await expect(context.suite.complianceModule.moduleMintAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -374,8 +379,9 @@ describe('Compliance Module: TransferRestrict', () => { it('should revert', async () => { const context = await loadFixture(deployTransferRestrictFullSuite); - await expect(context.suite.complianceModule.moduleBurnAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWith( - 'only bound compliance can call', + await expect(context.suite.complianceModule.moduleBurnAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -404,7 +410,7 @@ describe('Compliance Module: TransferRestrict', () => { await expect( context.suite.complianceModule.moduleTransferAction(context.accounts.aliceWallet.address, context.accounts.anotherWallet.address, 10), - ).to.be.revertedWith('only bound compliance can call'); + ).to.be.revertedWithCustomError(context.suite.complianceModule, 'OnlyBoundComplianceCanCall'); }); }); diff --git a/test/dva.test.ts b/test/dva.test.ts index 95aed026..0cd12453 100644 --- a/test/dva.test.ts +++ b/test/dva.test.ts @@ -104,7 +104,9 @@ describe('DVATransferManager', () => { describe('when the contract is already initialized', () => { it('should revert', async () => { const context = await loadFixture(deployFullSuiteWithTransferManager); - await expect(context.suite.transferManager.initialize()).to.eventually.be.rejectedWith('Initializable: contract is already initialized'); + // @dev Line below is commented due to Hardhat incompatibility with viaIR, should be tested with newer Hardhat version. + // await expect(context.suite.transferManager.initialize()).to.eventually.be.rejectedWith('Initializable: contract is already initialized'); + await expect(context.suite.transferManager.initialize()).to.be.reverted; }); }); }); diff --git a/test/dvd.test.ts b/test/dvd.test.ts index 59c6bb16..9df53571 100644 --- a/test/dvd.test.ts +++ b/test/dvd.test.ts @@ -67,7 +67,7 @@ describe('DVDTransferManager', () => { await expect( transferManager.connect(anotherWallet).modifyFee(erc20A.target, erc20B.target, 1, 1, 1, charlieWallet.address, davidWallet.address), - ).to.be.revertedWith('Ownable: only owner can call'); + ).to.be.revertedWithCustomError(transferManager, 'OwnableUnauthorizedAccount'); }); }); @@ -80,7 +80,7 @@ describe('DVDTransferManager', () => { await expect( transferManager.connect(deployer).modifyFee(token.target, erc20A.target, 1, 1, 1, charlieWallet.address, davidWallet.address), - ).to.be.revertedWith('invalid fee settings'); + ).to.be.revertedWithCustomError(transferManager, 'InvalidFeeSettings'); }); it('should revert for invalid fee settings', async () => { @@ -91,7 +91,7 @@ describe('DVDTransferManager', () => { await expect( transferManager.connect(deployer).modifyFee(erc20A.target, token.target, 1, 1, 1, charlieWallet.address, davidWallet.address), - ).to.be.revertedWith('invalid fee settings'); + ).to.be.revertedWithCustomError(transferManager, 'InvalidFeeSettings'); }); }); @@ -106,7 +106,7 @@ describe('DVDTransferManager', () => { await expect( transferManager.connect(deployer).modifyFee(erc20A.target, erc20B.target, 1000, 1, 2, charlieWallet.address, davidWallet.address), - ).to.be.revertedWith('invalid fee settings'); + ).to.be.revertedWithCustomError(transferManager, 'InvalidFeeSettings'); }); }); @@ -119,7 +119,7 @@ describe('DVDTransferManager', () => { await expect( transferManager.connect(deployer).modifyFee(erc20A.target, erc20B.target, 1, 1000, 2, charlieWallet.address, davidWallet.address), - ).to.be.revertedWith('invalid fee settings'); + ).to.be.revertedWithCustomError(transferManager, 'InvalidFeeSettings'); }); }); @@ -132,7 +132,7 @@ describe('DVDTransferManager', () => { await expect( transferManager.connect(deployer).modifyFee(erc20A.target, erc20B.target, 0, 0, 1, charlieWallet.address, davidWallet.address), - ).to.be.revertedWith('invalid fee settings'); + ).to.be.revertedWithCustomError(transferManager, 'InvalidFeeSettings'); }); }); @@ -145,7 +145,7 @@ describe('DVDTransferManager', () => { await expect( transferManager.connect(deployer).modifyFee(erc20A.target, erc20B.target, 1000, 1, 10, charlieWallet.address, davidWallet.address), - ).to.be.revertedWith('invalid fee settings'); + ).to.be.revertedWithCustomError(transferManager, 'InvalidFeeSettings'); }); }); @@ -158,7 +158,7 @@ describe('DVDTransferManager', () => { await expect( transferManager.connect(deployer).modifyFee(erc20A.target, erc20B.target, 2, 0, 2, ethers.ZeroAddress, davidWallet.address), - ).to.be.revertedWith('fee wallet 1 cannot be zero address'); + ).to.be.revertedWithCustomError(transferManager, 'FeeWalletCannotBeZeroAddress'); }); }); @@ -171,7 +171,7 @@ describe('DVDTransferManager', () => { await expect( transferManager.connect(deployer).modifyFee(erc20A.target, erc20B.target, 0, 1, 2, ethers.ZeroAddress, ethers.ZeroAddress), - ).to.be.revertedWith('fee wallet 2 cannot be zero address'); + ).to.be.revertedWithCustomError(transferManager, 'FeeWalletCannotBeZeroAddress'); }); }); }); @@ -260,7 +260,7 @@ describe('DVDTransferManager', () => { await expect( transferManager.connect(charlieWallet).initiateDVDTransfer(erc20A.target, 1000, charlieWallet.address, erc20B.target, 1000), - ).to.be.revertedWith('Not enough tokens in balance'); + ).to.be.revertedWithCustomError(transferManager, 'ERC20InsufficientBalance'); }); }); @@ -274,7 +274,7 @@ describe('DVDTransferManager', () => { await erc20A.connect(deployer).mint(charlieWallet.address, 1000); await expect( transferManager.connect(charlieWallet).initiateDVDTransfer(erc20A.target, 1000, davidWallet.address, erc20B.target, 1000), - ).to.be.revertedWith('not enough allowance to initiate transfer'); + ).to.be.revertedWithCustomError(transferManager, 'ERC20InsufficientAllowance'); }); }); @@ -289,7 +289,7 @@ describe('DVDTransferManager', () => { await erc20A.connect(charlieWallet).approve(transferManager.target, 1000); await expect( transferManager.connect(charlieWallet).initiateDVDTransfer(erc20A.target, 1000, ethers.ZeroAddress, erc20B.target, 1000), - ).to.be.revertedWith('counterpart cannot be null'); + ).to.be.revertedWithCustomError(transferManager, 'ZeroAddress'); }); }); @@ -304,7 +304,7 @@ describe('DVDTransferManager', () => { await erc20A.connect(charlieWallet).approve(transferManager.target, 1000); await expect( transferManager.connect(charlieWallet).initiateDVDTransfer(erc20A.target, 1000, davidWallet.address, erc20C.target, 1000), - ).to.be.revertedWith('invalid address : address is not an ERC20'); + ).to.be.revertedWithCustomError(transferManager, 'AddressNotERC20'); }); }); @@ -333,7 +333,7 @@ describe('DVDTransferManager', () => { accounts: { charlieWallet }, } = await loadFixture(deployFullSuiteWithTransferManager); - await expect(transferManager.connect(charlieWallet).cancelDVDTransfer(ethers.ZeroHash)).to.be.revertedWith('transfer ID does not exist'); + await expect(transferManager.connect(charlieWallet).cancelDVDTransfer(ethers.ZeroHash)).to.be.revertedWithCustomError(transferManager, 'TransferIDDoesNotExist'); }); }); @@ -345,8 +345,9 @@ describe('DVDTransferManager', () => { values: { transferId }, } = await loadFixture(deployFullSuiteWithTransferManagerAndInitiatedTransfer); - await expect(transferManager.connect(anotherWallet).cancelDVDTransfer(transferId)).to.be.revertedWith( - 'you are not allowed to cancel this transfer', + await expect(transferManager.connect(anotherWallet).cancelDVDTransfer(transferId)).to.be.revertedWithCustomError( + transferManager, + 'CancelOnlyByCounterpartOrOwnerOrAgent', ); }); }); @@ -361,7 +362,7 @@ describe('DVDTransferManager', () => { const tx = await transferManager.connect(aliceWallet).cancelDVDTransfer(transferId); await expect(tx).to.emit(transferManager, 'DVDTransferCancelled').withArgs(transferId); - await expect(transferManager.connect(aliceWallet).cancelDVDTransfer(transferId)).to.be.revertedWith('transfer ID does not exist'); + await expect(transferManager.connect(aliceWallet).cancelDVDTransfer(transferId)).to.be.revertedWithCustomError(transferManager, 'TransferIDDoesNotExist'); }); }); @@ -375,7 +376,7 @@ describe('DVDTransferManager', () => { const tx = await transferManager.connect(bobWallet).cancelDVDTransfer(transferId); await expect(tx).to.emit(transferManager, 'DVDTransferCancelled').withArgs(transferId); - await expect(transferManager.connect(bobWallet).cancelDVDTransfer(transferId)).to.be.revertedWith('transfer ID does not exist'); + await expect(transferManager.connect(bobWallet).cancelDVDTransfer(transferId)).to.be.revertedWithCustomError(transferManager, 'TransferIDDoesNotExist'); }); }); @@ -389,7 +390,7 @@ describe('DVDTransferManager', () => { const tx = await transferManager.connect(deployer).cancelDVDTransfer(transferId); await expect(tx).to.emit(transferManager, 'DVDTransferCancelled').withArgs(transferId); - await expect(transferManager.connect(deployer).cancelDVDTransfer(transferId)).to.be.revertedWith('transfer ID does not exist'); + await expect(transferManager.connect(deployer).cancelDVDTransfer(transferId)).to.be.revertedWithCustomError(transferManager, 'TransferIDDoesNotExist'); }); }); @@ -403,7 +404,7 @@ describe('DVDTransferManager', () => { const tx = await transferManager.connect(deployer).cancelDVDTransfer(transferId); await expect(tx).to.emit(transferManager, 'DVDTransferCancelled').withArgs(transferId); - await expect(transferManager.connect(deployer).cancelDVDTransfer(transferId)).to.be.revertedWith('transfer ID does not exist'); + await expect(transferManager.connect(deployer).cancelDVDTransfer(transferId)).to.be.revertedWithCustomError(transferManager, 'TransferIDDoesNotExist'); }); }); }); @@ -416,7 +417,7 @@ describe('DVDTransferManager', () => { accounts: { charlieWallet }, } = await loadFixture(deployFullSuiteWithTransferManager); - await expect(transferManager.connect(charlieWallet).takeDVDTransfer(ethers.ZeroHash)).to.be.revertedWith('transfer ID does not exist'); + await expect(transferManager.connect(charlieWallet).takeDVDTransfer(ethers.ZeroHash)).to.be.revertedWithCustomError(transferManager, 'TransferIDDoesNotExist'); }); }); @@ -429,8 +430,9 @@ describe('DVDTransferManager', () => { values: { transferId }, } = await loadFixture(deployFullSuiteWithTransferManagerAndInitiatedTransfer); - await expect(transferManager.connect(anotherWallet).takeDVDTransfer(transferId)).to.be.revertedWith( - 'transfer has to be done by the counterpart or by owner', + await expect(transferManager.connect(anotherWallet).takeDVDTransfer(transferId)).to.be.revertedWithCustomError( + transferManager, + 'TransferOnlyByCounterpartOrOwner', ); }); }); @@ -451,7 +453,7 @@ describe('DVDTransferManager', () => { await expect(tx).to.emit(erc20A, 'Transfer').withArgs(aliceWallet.address, charlieWallet.address, 10); await expect(tx).to.emit(erc20B, 'Transfer').withArgs(bobWallet.address, aliceWallet.address, 490); await expect(tx).to.emit(erc20B, 'Transfer').withArgs(bobWallet.address, davidWallet.address, 10); - await expect(transferManager.connect(bobWallet).takeDVDTransfer(transferId)).to.be.revertedWith('transfer ID does not exist'); + await expect(transferManager.connect(bobWallet).takeDVDTransfer(transferId)).to.be.revertedWithCustomError(transferManager, 'TransferIDDoesNotExist'); }); }); @@ -467,7 +469,7 @@ describe('DVDTransferManager', () => { await expect(tx).to.emit(transferManager, 'DVDTransferExecuted').withArgs(transferId); await expect(tx).to.emit(erc20A, 'Transfer').withArgs(aliceWallet.address, bobWallet.address, 1000); await expect(tx).to.emit(erc20B, 'Transfer').withArgs(bobWallet.address, aliceWallet.address, 500); - await expect(transferManager.connect(bobWallet).takeDVDTransfer(transferId)).to.be.revertedWith('transfer ID does not exist'); + await expect(transferManager.connect(bobWallet).takeDVDTransfer(transferId)).to.be.revertedWithCustomError(transferManager, 'TransferIDDoesNotExist'); }); }); }); diff --git a/test/registries/claim-topics-registry.test.ts b/test/registries/claim-topics-registry.test.ts index 4cf8760d..47995ac7 100644 --- a/test/registries/claim-topics-registry.test.ts +++ b/test/registries/claim-topics-registry.test.ts @@ -37,7 +37,7 @@ describe('ClaimTopicsRegistry', () => { await Promise.all(Array.from({ length: 14 }, (_, i) => i).map((i) => claimTopicsRegistry.addClaimTopic(i))); - await expect(claimTopicsRegistry.connect(deployer).addClaimTopic(14)).to.be.revertedWith('cannot require more than 15 topics'); + await expect(claimTopicsRegistry.connect(deployer).addClaimTopic(14)).to.be.revertedWithCustomError(claimTopicsRegistry, 'CannotRequireMoreThan15Topics'); }); }); @@ -50,7 +50,7 @@ describe('ClaimTopicsRegistry', () => { await claimTopicsRegistry.addClaimTopic(1); - await expect(claimTopicsRegistry.connect(deployer).addClaimTopic(1)).to.be.revertedWith('claimTopic already exists'); + await expect(claimTopicsRegistry.connect(deployer).addClaimTopic(1)).to.be.revertedWithCustomError(claimTopicsRegistry, 'ClaimTopicAlreadyExists'); }); }); }); diff --git a/test/registries/identity-registry-storage.test.ts b/test/registries/identity-registry-storage.test.ts index 78317de4..bc310468 100644 --- a/test/registries/identity-registry-storage.test.ts +++ b/test/registries/identity-registry-storage.test.ts @@ -27,7 +27,7 @@ describe('IdentityRegistryStorage', () => { await expect( identityRegistryStorage.connect(anotherWallet).addIdentityToStorage(charlieWallet.address, charlieIdentity.target, 42), - ).to.be.revertedWith('AgentRole: caller does not have the Agent role'); + ).to.be.revertedWithCustomError(identityRegistryStorage, 'CallerDoesNotHaveAgentRole'); }); }); @@ -75,7 +75,7 @@ describe('IdentityRegistryStorage', () => { await expect( identityRegistryStorage.connect(tokenAgent).addIdentityToStorage(bobWallet.address, charlieIdentity.target, 42), - ).to.be.revertedWith('address stored already'); + ).to.be.revertedWithCustomError(identityRegistryStorage, 'AddressAlreadyStored'); }); }); }); @@ -92,7 +92,7 @@ describe('IdentityRegistryStorage', () => { await expect( identityRegistryStorage.connect(anotherWallet).modifyStoredIdentity(charlieWallet.address, charlieIdentity.target), - ).to.be.revertedWith('AgentRole: caller does not have the Agent role'); + ).to.be.revertedWithCustomError(identityRegistryStorage, 'CallerDoesNotHaveAgentRole'); }); }); @@ -140,7 +140,7 @@ describe('IdentityRegistryStorage', () => { await expect( identityRegistryStorage.connect(tokenAgent).modifyStoredIdentity(charlieWallet.address, charlieIdentity.target), - ).to.be.revertedWith('address not stored yet'); + ).to.be.revertedWithCustomError(identityRegistryStorage, 'AddressNotYetStored'); }); }); }); @@ -154,8 +154,9 @@ describe('IdentityRegistryStorage', () => { accounts: { anotherWallet, charlieWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistryStorage.connect(anotherWallet).modifyStoredInvestorCountry(charlieWallet.address, 42)).to.be.revertedWith( - 'AgentRole: caller does not have the Agent role', + await expect(identityRegistryStorage.connect(anotherWallet).modifyStoredInvestorCountry(charlieWallet.address, 42)).to.be.revertedWithCustomError( + identityRegistryStorage, + 'CallerDoesNotHaveAgentRole', ); }); }); @@ -186,8 +187,9 @@ describe('IdentityRegistryStorage', () => { await identityRegistryStorage.addAgent(tokenAgent.address); - await expect(identityRegistryStorage.connect(tokenAgent).modifyStoredInvestorCountry(charlieWallet.address, 42)).to.be.revertedWith( - 'address not stored yet', + await expect(identityRegistryStorage.connect(tokenAgent).modifyStoredInvestorCountry(charlieWallet.address, 42)).to.be.revertedWithCustomError( + identityRegistryStorage, + 'AddressNotYetStored', ); }); }); @@ -202,8 +204,9 @@ describe('IdentityRegistryStorage', () => { accounts: { anotherWallet, charlieWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistryStorage.connect(anotherWallet).removeIdentityFromStorage(charlieWallet.address)).to.be.revertedWith( - 'AgentRole: caller does not have the Agent role', + await expect(identityRegistryStorage.connect(anotherWallet).removeIdentityFromStorage(charlieWallet.address)).to.be.revertedWithCustomError( + identityRegistryStorage, + 'CallerDoesNotHaveAgentRole', ); }); }); @@ -234,8 +237,9 @@ describe('IdentityRegistryStorage', () => { await identityRegistryStorage.addAgent(tokenAgent.address); - await expect(identityRegistryStorage.connect(tokenAgent).removeIdentityFromStorage(charlieWallet.address)).to.be.revertedWith( - 'address not stored yet', + await expect(identityRegistryStorage.connect(tokenAgent).removeIdentityFromStorage(charlieWallet.address)).to.be.revertedWithCustomError( + identityRegistryStorage, + 'AddressNotYetStored', ); }); }); @@ -284,8 +288,9 @@ describe('IdentityRegistryStorage', () => { Array.from({ length: 299 }, () => identityRegistryStorage.connect(deployer).bindIdentityRegistry(ethers.Wallet.createRandom().address)), ); - await expect(identityRegistryStorage.connect(deployer).bindIdentityRegistry(charlieIdentity.target)).to.be.revertedWith( - 'cannot bind more than 300 IR to 1 IRS', + await expect(identityRegistryStorage.connect(deployer).bindIdentityRegistry(charlieIdentity.target)).to.be.revertedWithCustomError( + identityRegistryStorage, + 'CannotBindMoreThan300IRTo1IRS', ); }); }); @@ -331,8 +336,9 @@ describe('IdentityRegistryStorage', () => { await identityRegistryStorage.unbindIdentityRegistry(identityRegistry.target); - await expect(identityRegistryStorage.connect(deployer).unbindIdentityRegistry(identityRegistry.target)).to.be.revertedWith( - 'identity registry is not stored', + await expect(identityRegistryStorage.connect(deployer).unbindIdentityRegistry(identityRegistry.target)).to.be.revertedWithCustomError( + identityRegistryStorage, + 'IdentityRegistryNotStored', ); }); }); diff --git a/test/registries/identity-registry.test.ts b/test/registries/identity-registry.test.ts index 91d1e6e0..a1974bd1 100644 --- a/test/registries/identity-registry.test.ts +++ b/test/registries/identity-registry.test.ts @@ -44,8 +44,9 @@ describe('IdentityRegistry', () => { identities: { bobIdentity, charlieIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistry.connect(anotherWallet).updateIdentity(bobIdentity.target, charlieIdentity.target)).to.be.revertedWith( - 'AgentRole: caller does not have the Agent role', + await expect(identityRegistry.connect(anotherWallet).updateIdentity(bobIdentity.target, charlieIdentity.target)).to.be.revertedWithCustomError( + identityRegistry, + 'CallerDoesNotHaveAgentRole', ); }); }); @@ -60,8 +61,9 @@ describe('IdentityRegistry', () => { identities: { bobIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistry.connect(anotherWallet).updateCountry(bobIdentity.target, 100)).to.be.revertedWith( - 'AgentRole: caller does not have the Agent role', + await expect(identityRegistry.connect(anotherWallet).updateCountry(bobIdentity.target, 100)).to.be.revertedWithCustomError( + identityRegistry, + 'CallerDoesNotHaveAgentRole', ); }); }); @@ -75,8 +77,9 @@ describe('IdentityRegistry', () => { accounts: { anotherWallet, bobWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistry.connect(anotherWallet).deleteIdentity(bobWallet.address)).to.be.revertedWith( - 'AgentRole: caller does not have the Agent role', + await expect(identityRegistry.connect(anotherWallet).deleteIdentity(bobWallet.address)).to.be.revertedWithCustomError( + identityRegistry, + 'CallerDoesNotHaveAgentRole', ); }); }); @@ -90,8 +93,9 @@ describe('IdentityRegistry', () => { accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistry.connect(anotherWallet).registerIdentity(ethers.ZeroAddress, ethers.ZeroAddress, 0)).to.be.revertedWith( - 'AgentRole: caller does not have the Agent role', + await expect(identityRegistry.connect(anotherWallet).registerIdentity(ethers.ZeroAddress, ethers.ZeroAddress, 0)).to.be.revertedWithCustomError( + identityRegistry, + 'CallerDoesNotHaveAgentRole', ); }); }); diff --git a/test/registries/trusted-issuers-registry.test.ts b/test/registries/trusted-issuers-registry.test.ts index 7431daf2..acaf652a 100644 --- a/test/registries/trusted-issuers-registry.test.ts +++ b/test/registries/trusted-issuers-registry.test.ts @@ -2,6 +2,7 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { expect } from 'chai'; import { ethers } from 'hardhat'; import { deployFullSuiteFixture } from '../fixtures/deploy-full-suite.fixture'; +import { TestUpgradedCountryAllowModule__factory } from '../../typechain-types'; describe('TrustedIssuersRegistry', () => { describe('.addTrustedIssuer()', () => { @@ -44,7 +45,7 @@ describe('TrustedIssuersRegistry', () => { await expect( trustedIssuersRegistry.connect(deployer).addTrustedIssuer(claimIssuerContract.target, Array.from(claimTopics)), - ).to.be.revertedWith('trusted Issuer already exists'); + ).to.be.revertedWithCustomError(trustedIssuersRegistry, 'TrustedIssuerAlreadyExists'); }); }); @@ -55,8 +56,9 @@ describe('TrustedIssuersRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect(trustedIssuersRegistry.connect(deployer).addTrustedIssuer(deployer.address, [])).to.be.revertedWith( - 'trusted claim topics cannot be empty', + await expect(trustedIssuersRegistry.connect(deployer).addTrustedIssuer(deployer.address, [])).to.be.revertedWithCustomError( + trustedIssuersRegistry, + 'TrustedClaimTopicsCannotBeEmpty', ); }); }); @@ -70,8 +72,9 @@ describe('TrustedIssuersRegistry', () => { const claimTopics = Array.from({ length: 16 }, (_, i) => i); - await expect(trustedIssuersRegistry.connect(deployer).addTrustedIssuer(deployer.address, claimTopics)).to.be.revertedWith( - 'cannot have more than 15 claim topics', + await expect(trustedIssuersRegistry.connect(deployer).addTrustedIssuer(deployer.address, claimTopics)).to.be.revertedWithCustomError( + trustedIssuersRegistry, + 'CannotHaveMoreThan15ClaimTopics', ); }); }); @@ -92,8 +95,9 @@ describe('TrustedIssuersRegistry', () => { }), ); - await expect(trustedIssuersRegistry.connect(deployer).addTrustedIssuer(deployer.address, claimTopics)).to.be.revertedWith( - 'cannot have more than 50 trusted issuers', + await expect(trustedIssuersRegistry.connect(deployer).addTrustedIssuer(deployer.address, claimTopics)).to.be.revertedWithCustomError( + trustedIssuersRegistry, + 'CannotHaveMoreThan50TrustedIssuers', ); }); }); @@ -136,7 +140,9 @@ describe('TrustedIssuersRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect(trustedIssuersRegistry.connect(deployer).removeTrustedIssuer(deployer.address)).to.be.revertedWith('NOT a trusted issuer'); + await expect(trustedIssuersRegistry.connect(deployer).removeTrustedIssuer(deployer.address)).to.be.revertedWithCustomError( + trustedIssuersRegistry, + 'NotATrustedIssuer'); }); }); @@ -203,8 +209,9 @@ describe('TrustedIssuersRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect(trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(deployer.address, [10])).to.be.revertedWith( - 'NOT a trusted issuer', + await expect(trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(deployer.address, [10])).to.be.revertedWithCustomError( + trustedIssuersRegistry, + 'NotATrustedIssuer', ); }); }); @@ -218,8 +225,9 @@ describe('TrustedIssuersRegistry', () => { const claimTopics = Array.from({ length: 16 }, (_, i) => i); - await expect(trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(claimIssuerContract.target, claimTopics)).to.be.revertedWith( - 'cannot have more than 15 claim topics', + await expect(trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(claimIssuerContract.target, claimTopics)).to.be.revertedWithCustomError( + trustedIssuersRegistry, + 'CannotHaveMoreThan15ClaimTopics', ); }); }); @@ -231,8 +239,9 @@ describe('TrustedIssuersRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect(trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(claimIssuerContract.target, [])).to.be.revertedWith( - 'claim topics cannot be empty', + await expect(trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(claimIssuerContract.target, [])).to.be.revertedWithCustomError( + trustedIssuersRegistry, + 'ClaimTopicsCannotBeEmpty', ); }); }); @@ -266,8 +275,9 @@ describe('TrustedIssuersRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect(trustedIssuersRegistry.connect(deployer).getTrustedIssuerClaimTopics(deployer.address)).to.be.revertedWith( - "trusted Issuer doesn't exist", + await expect(trustedIssuersRegistry.connect(deployer).getTrustedIssuerClaimTopics(deployer.address)).to.be.revertedWithCustomError( + trustedIssuersRegistry, + 'TrustedIssuerDoesntExist', ); }); }); diff --git a/test/token/token-information.test.ts b/test/token/token-information.test.ts index 105a289f..08a967ee 100644 --- a/test/token/token-information.test.ts +++ b/test/token/token-information.test.ts @@ -150,7 +150,7 @@ describe('Token - Information', () => { suite: { token }, accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(anotherWallet).pause()).to.be.revertedWith('AgentRole: caller does not have the Agent role'); + await expect(token.connect(anotherWallet).pause()).to.be.revertedWithCustomError(token, 'CallerDoesNotHaveAgentRole'); }); }); @@ -195,7 +195,7 @@ describe('Token - Information', () => { accounts: { tokenAgent }, } = await loadFixture(deployFullSuiteFixture); await token.connect(tokenAgent).pause(); - await expect(token.connect(tokenAgent).pause()).to.be.revertedWith('Pausable: paused'); + await expect(token.connect(tokenAgent).pause()).to.be.revertedWithCustomError(token, 'EnforcedPause'); }); }); }); @@ -208,7 +208,7 @@ describe('Token - Information', () => { suite: { token }, accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(anotherWallet).unpause()).to.be.revertedWith('AgentRole: caller does not have the Agent role'); + await expect(token.connect(anotherWallet).unpause()).to.be.revertedWithCustomError(token, 'CallerDoesNotHaveAgentRole'); }); }); @@ -254,7 +254,7 @@ describe('Token - Information', () => { suite: { token }, accounts: { tokenAgent }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(tokenAgent).unpause()).to.be.revertedWith('Pausable: not paused'); + await expect(token.connect(tokenAgent).unpause()).to.be.revertedWithCustomError(token, 'ExpectedPause'); }); }); }); @@ -267,8 +267,9 @@ describe('Token - Information', () => { suite: { token }, accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(anotherWallet).setAddressFrozen(anotherWallet.address, true)).to.be.revertedWith( - 'AgentRole: caller does not have the Agent role', + await expect(token.connect(anotherWallet).setAddressFrozen(anotherWallet.address, true)).to.be.revertedWithCustomError( + token, + 'CallerDoesNotHaveAgentRole', ); }); }); @@ -281,8 +282,9 @@ describe('Token - Information', () => { suite: { token }, accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(anotherWallet).freezePartialTokens(anotherWallet.address, 1)).to.be.revertedWith( - 'AgentRole: caller does not have the Agent role', + await expect(token.connect(anotherWallet).freezePartialTokens(anotherWallet.address, 1)).to.be.revertedWithCustomError( + token, + 'CallerDoesNotHaveAgentRole', ); }); }); @@ -309,8 +311,9 @@ describe('Token - Information', () => { suite: { token }, accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(anotherWallet).unfreezePartialTokens(anotherWallet.address, 1)).to.be.revertedWith( - 'AgentRole: caller does not have the Agent role', + await expect(token.connect(anotherWallet).unfreezePartialTokens(anotherWallet.address, 1)).to.be.revertedWithCustomError( + token, + 'CallerDoesNotHaveAgentRole', ); }); }); diff --git a/test/token/token-recovery.test.ts b/test/token/token-recovery.test.ts index 3fff529c..fdbd5ec9 100644 --- a/test/token/token-recovery.test.ts +++ b/test/token/token-recovery.test.ts @@ -17,8 +17,9 @@ describe('Token - Recovery', () => { .connect(bobWallet) .addKey(ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address'], [anotherWallet.address])), 1, 1); - await expect(token.connect(anotherWallet).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target)).to.be.revertedWith( - 'AgentRole: caller does not have the Agent role', + await expect(token.connect(anotherWallet).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target)).to.be.revertedWithCustomError( + token, + 'CallerDoesNotHaveAgentRole', ); }); }); @@ -62,8 +63,9 @@ describe('Token - Recovery', () => { await token.connect(bobWallet).transfer(aliceWallet.address, await token.balanceOf(bobWallet.address)); - await expect(token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target)).to.be.revertedWith( - 'no tokens to recover', + await expect(token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target)).to.be.revertedWithCustomError( + token, + 'NoTokenToRecover', ); }); }); @@ -76,8 +78,9 @@ describe('Token - Recovery', () => { identities: { bobIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target)).to.be.revertedWith( - 'Recovery not possible', + await expect(token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target)).to.be.revertedWithCustomError( + token, + 'RecoveryNotPossible', ); }); }); diff --git a/test/token/token-transfer.test.ts b/test/token/token-transfer.test.ts index ec74d6af..e063185c 100644 --- a/test/token/token-transfer.test.ts +++ b/test/token/token-transfer.test.ts @@ -60,7 +60,7 @@ describe('Token - Transfers', () => { await token.connect(tokenAgent).pause(); - await expect(token.connect(aliceWallet).transfer(bobWallet.address, 100)).to.be.revertedWith('Pausable: paused'); + await expect(token.connect(aliceWallet).transfer(bobWallet.address, 100)).to.be.revertedWithCustomError(token, 'EnforcedPause'); }); }); @@ -73,7 +73,7 @@ describe('Token - Transfers', () => { await token.connect(tokenAgent).setAddressFrozen(bobWallet.address, true); - await expect(token.connect(aliceWallet).transfer(bobWallet.address, 100)).to.be.revertedWith('wallet is frozen'); + await expect(token.connect(aliceWallet).transfer(bobWallet.address, 100)).to.be.revertedWithCustomError(token, 'FrozenWallet'); }); }); @@ -86,7 +86,7 @@ describe('Token - Transfers', () => { await token.connect(tokenAgent).setAddressFrozen(aliceWallet.address, true); - await expect(token.connect(aliceWallet).transfer(bobWallet.address, 100)).to.be.revertedWith('wallet is frozen'); + await expect(token.connect(aliceWallet).transfer(bobWallet.address, 100)).to.be.revertedWithCustomError(token, 'FrozenWallet'); }); }); @@ -179,7 +179,7 @@ describe('Token - Transfers', () => { await token.connect(tokenAgent).pause(); - await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWith('Pausable: paused'); + await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWithCustomError(token, 'EnforcedPause'); }); }); @@ -192,7 +192,7 @@ describe('Token - Transfers', () => { await token.connect(tokenAgent).setAddressFrozen(aliceWallet.address, true); - await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWith('wallet is frozen'); + await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWithCustomError(token, 'FrozenWallet'); }); }); @@ -205,7 +205,7 @@ describe('Token - Transfers', () => { await token.connect(tokenAgent).setAddressFrozen(bobWallet.address, true); - await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWith('wallet is frozen'); + await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWithCustomError(token, 'FrozenWallet'); }); }); @@ -218,8 +218,9 @@ describe('Token - Transfers', () => { const balance = await token.balanceOf(aliceWallet.address); - await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, balance + 1000n)).to.be.revertedWith( - 'Insufficient Balance', + await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, balance + 1000n)).to.be.revertedWithCustomError( + token, + 'ERC20InsufficientBalance', ); }); }); @@ -234,8 +235,9 @@ describe('Token - Transfers', () => { const balance = await token.balanceOf(aliceWallet.address); await token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, balance - 100n); - await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, balance)).to.be.revertedWith( - 'Insufficient Balance', + await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, balance)).to.be.revertedWithCustomError( + token, + 'ERC20InsufficientBalance', ); }); }); @@ -247,8 +249,9 @@ describe('Token - Transfers', () => { accounts: { aliceWallet, anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, anotherWallet.address, 100)).to.be.revertedWith( - 'Transfer not possible', + await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, anotherWallet.address, 100)).to.be.revertedWithCustomError( + token, + 'TransferNotPossible', ); }); }); @@ -264,8 +267,9 @@ describe('Token - Transfers', () => { await compliance.addModule(complianceModuleA.target); await token.setCompliance(compliance.target); - await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWith( - 'Transfer not possible', + await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWithCustomError( + token, + 'TransferNotPossible', ); }); }); @@ -295,8 +299,9 @@ describe('Token - Transfers', () => { accounts: { aliceWallet, bobWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(aliceWallet).forcedTransfer(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWith( - 'AgentRole: caller does not have the Agent role', + await expect(token.connect(aliceWallet).forcedTransfer(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWithCustomError( + token, + 'CallerDoesNotHaveAgentRole', ); }); }); @@ -347,8 +352,9 @@ describe('Token - Transfers', () => { accounts: { aliceWallet, anotherWallet, tokenAgent }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(tokenAgent).forcedTransfer(aliceWallet.address, anotherWallet.address, 100)).to.be.revertedWith( - 'Transfer not possible', + await expect(token.connect(tokenAgent).forcedTransfer(aliceWallet.address, anotherWallet.address, 100)).to.be.revertedWithCustomError( + token, + 'TransferNotPossible', ); }); }); @@ -399,7 +405,7 @@ describe('Token - Transfers', () => { accounts: { aliceWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(aliceWallet).mint(aliceWallet.address, 100)).to.be.revertedWith('AgentRole: caller does not have the Agent role'); + await expect(token.connect(aliceWallet).mint(aliceWallet.address, 100)).to.be.revertedWithCustomError(token, 'CallerDoesNotHaveAgentRole'); }); }); @@ -459,7 +465,7 @@ describe('Token - Transfers', () => { accounts: { aliceWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(aliceWallet).burn(aliceWallet.address, 100)).to.be.revertedWith('AgentRole: caller does not have the Agent role'); + await expect(token.connect(aliceWallet).burn(aliceWallet.address, 100)).to.be.revertedWithCustomError(token, 'CallerDoesNotHaveAgentRole'); }); }); @@ -527,8 +533,9 @@ describe('Token - Transfers', () => { accounts: { aliceWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(aliceWallet).freezePartialTokens(aliceWallet.address, 100)).to.be.revertedWith( - 'AgentRole: caller does not have the Agent role', + await expect(token.connect(aliceWallet).freezePartialTokens(aliceWallet.address, 100)).to.be.revertedWithCustomError( + token, + 'CallerDoesNotHaveAgentRole', ); }); }); @@ -592,8 +599,9 @@ describe('Token - Transfers', () => { accounts: { aliceWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(aliceWallet).unfreezePartialTokens(aliceWallet.address, 100)).to.be.revertedWith( - 'AgentRole: caller does not have the Agent role', + await expect(token.connect(aliceWallet).unfreezePartialTokens(aliceWallet.address, 100)).to.be.revertedWithCustomError( + token, + 'CallerDoesNotHaveAgentRole', ); }); }); From e6bf7a6173697976d7034804f95d822727b367f9 Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Wed, 3 Jul 2024 15:50:33 +0200 Subject: [PATCH 25/55] =?UTF-8?q?=E2=99=BB()=20TREX-132=20Custom=20Errors?= =?UTF-8?q?=20contd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/DVA/DVATransferManager.sol | 58 +++------ contracts/DVD/DVDTransferManager.sol | 30 ++--- .../compliance/modular/ModularCompliance.sol | 22 ++-- .../modular/modules/AbstractModule.sol | 18 +-- .../modules/AbstractModuleUpgradeable.sol | 18 +-- .../modular/modules/CountryAllowModule.sol | 6 +- .../modular/modules/CountryRestrictModule.sol | 18 +-- .../modules/ExchangeMonthlyLimitsModule.sol | 9 +- .../modular/modules/MaxBalanceModule.sol | 31 ++--- .../modules/TimeExchangeLimitsModule.sol | 17 ++- .../modules/TimeTransfersLimitsModule.sol | 7 +- .../modular/modules/TransferFeesModule.sol | 8 +- contracts/factory/TREXFactory.sol | 48 +++++--- contracts/factory/TREXGateway.sol | 30 +++-- .../{CommonLib.sol => CommonErrors.sol} | 8 +- ...ComplianceLib.sol => ComplianceErrors.sol} | 2 +- ...umentLib.sol => InvalidArgumentErrors.sol} | 2 +- .../errors/{RoleLib.sol => RoleErrors.sol} | 2 +- contracts/proxy/AbstractProxy.sol | 6 +- contracts/proxy/ClaimTopicsRegistryProxy.sol | 8 +- contracts/proxy/IdentityRegistryProxy.sol | 6 +- .../proxy/IdentityRegistryStorageProxy.sol | 6 +- contracts/proxy/ModularComplianceProxy.sol | 8 +- contracts/proxy/TokenProxy.sol | 12 +- .../proxy/TrustedIssuersRegistryProxy.sol | 8 +- contracts/proxy/authority/IAFactory.sol | 8 +- .../authority/TREXImplementationAuthority.sol | 112 +++++++++--------- .../implementation/IdentityRegistry.sol | 4 +- .../IdentityRegistryStorage.sol | 14 +-- .../implementation/TrustedIssuersRegistry.sol | 8 +- contracts/roles/AgentRole.sol | 10 +- contracts/roles/AgentRoleUpgradeable.sol | 10 +- contracts/roles/Roles.sol | 10 +- .../permissioning/agent/AgentManager.sol | 40 +++---- .../roles/permissioning/agent/AgentRoles.sol | 4 +- .../agent/AgentRolesUpgradeable.sol | 4 +- .../permissioning/owner/OwnerManager.sol | 28 ++--- .../roles/permissioning/owner/OwnerRoles.sol | 4 +- .../owner/OwnerRolesUpgradeable.sol | 4 +- contracts/token/Token.sol | 81 +++++++------ test/agentManager.test.ts | 56 +++++---- test/agentRole.test.ts | 10 +- .../trex-implementation-authority.test.ts | 47 +++++--- test/compliance.test.ts | 14 ++- .../module-conditional-transfer.test.ts | 10 +- test/compliances/module-country-allow.test.ts | 40 +++++-- .../module-country-restrict.test.ts | 35 ++++-- .../module-exchange-monthly-limits.test.ts | 5 +- test/compliances/module-max-balance.test.ts | 25 +++- test/compliances/module-supply-limit.test.ts | 5 +- .../module-time-exchange-limits.test.ts | 5 +- .../module-time-transfer-limits.test.ts | 5 +- test/compliances/module-transfer-fees.test.ts | 5 +- test/dva.test.ts | 2 +- test/dvd.test.ts | 40 +++++-- test/factory.test.ts | 14 +-- test/registries/claim-topics-registry.test.ts | 10 +- .../identity-registry-storage.test.ts | 14 +-- test/registries/identity-registry.test.ts | 14 +-- .../trusted-issuers-registry.test.ts | 22 ++-- test/token/token-information.test.ts | 12 +- test/token/token-recovery.test.ts | 21 ++-- test/token/token-transfer.test.ts | 53 ++++++--- 63 files changed, 656 insertions(+), 537 deletions(-) rename contracts/libraries/errors/{CommonLib.sol => CommonErrors.sol} (96%) rename contracts/libraries/errors/{ComplianceLib.sol => ComplianceErrors.sol} (99%) rename contracts/libraries/errors/{InvalidArgumentLib.sol => InvalidArgumentErrors.sol} (99%) rename contracts/libraries/errors/{RoleLib.sol => RoleErrors.sol} (99%) diff --git a/contracts/DVA/DVATransferManager.sol b/contracts/DVA/DVATransferManager.sol index d499cc0a..036b0695 100644 --- a/contracts/DVA/DVATransferManager.sol +++ b/contracts/DVA/DVATransferManager.sol @@ -101,13 +101,8 @@ contract DVATransferManager is IDVATransferManager, Initializable, OwnableUpgrad bool sequentialApproval, address[] memory additionalApprovers ) external { - if (AgentRole(tokenAddress).owner() != msg.sender) { - revert OnlyTokenOwnerCanCall(tokenAddress); - } - - if (!AgentRole(tokenAddress).isAgent(address(this))) { - revert DVAManagerIsNotAnAgentOfTheToken(tokenAddress); - } + require(AgentRole(tokenAddress).owner() == msg.sender, OnlyTokenOwnerCanCall(tokenAddress)); + require(AgentRole(tokenAddress).isAgent(address(this)), DVAManagerIsNotAnAgentOfTheToken(tokenAddress)); bytes32 hash = keccak256( abi.encode( @@ -140,14 +135,10 @@ contract DVATransferManager is IDVATransferManager, Initializable, OwnableUpgrad */ function initiateTransfer(address tokenAddress, address recipient, uint256 amount) external { ApprovalCriteria memory approvalCriteria = _approvalCriteria[tokenAddress]; - if (approvalCriteria.hash == bytes32(0)) { - revert TokenIsNotRegistered(tokenAddress); - } + require(approvalCriteria.hash != bytes32(0), TokenIsNotRegistered(tokenAddress)); IToken token = IToken(tokenAddress); - if (!token.identityRegistry().isVerified(recipient)) { - revert RecipientIsNotVerified(tokenAddress, recipient); - } + require(token.identityRegistry().isVerified(recipient), RecipientIsNotVerified(tokenAddress, recipient)); token.freezePartialTokens(msg.sender, amount); @@ -192,9 +183,7 @@ contract DVATransferManager is IDVATransferManager, Initializable, OwnableUpgrad * @dev See {IDVATransferManager-delegateApproveTransfer} */ function delegateApproveTransfer(bytes32 transferID, Signature[] memory signatures) external { - if (signatures.length == 0) { - revert SignaturesCanNotBeEmpty(transferID); - } + require(signatures.length > 0, SignaturesCanNotBeEmpty(transferID)); Transfer storage transfer = _getPendingTransfer(transferID); if (_approvalCriteriaChanged(transferID, transfer)) { @@ -219,9 +208,7 @@ contract DVATransferManager is IDVATransferManager, Initializable, OwnableUpgrad */ function cancelTransfer(bytes32 transferID) external { Transfer storage transfer = _getPendingTransfer(transferID); - if (msg.sender != transfer.sender) { - revert OnlyTransferSenderCanCall(transferID); - } + require(msg.sender == transfer.sender, OnlyTransferSenderCanCall(transferID)); transfer.status = TransferStatus.CANCELLED; IToken(transfer.tokenAddress).unfreezePartialTokens(transfer.sender, transfer.amount); @@ -250,14 +237,10 @@ contract DVATransferManager is IDVATransferManager, Initializable, OwnableUpgrad break; } - if (approvalCriteria.sequentialApproval) { - revert ApprovalsMustBeSequential(transferID); - } + require(!approvalCriteria.sequentialApproval, ApprovalsMustBeSequential(transferID)); } - if (!rejected) { - revert ApproverNotFound(transferID, msg.sender); - } + require(rejected, ApproverNotFound(transferID, msg.sender)); transfer.status = TransferStatus.REJECTED; IToken(transfer.tokenAddress).unfreezePartialTokens(transfer.sender, transfer.amount); @@ -269,9 +252,7 @@ contract DVATransferManager is IDVATransferManager, Initializable, OwnableUpgrad */ function getApprovalCriteria(address tokenAddress) external view returns (ApprovalCriteria memory) { ApprovalCriteria memory approvalCriteria = _approvalCriteria[tokenAddress]; - if (approvalCriteria.hash == bytes32(0)) { - revert TokenIsNotRegistered(tokenAddress); - } + require(approvalCriteria.hash != bytes32(0), TokenIsNotRegistered(tokenAddress)); return approvalCriteria; } @@ -283,9 +264,7 @@ contract DVATransferManager is IDVATransferManager, Initializable, OwnableUpgrad */ function getTransfer(bytes32 transferID) external view returns (Transfer memory) { Transfer memory transfer = _transfers[transferID]; - if (transfer.tokenAddress == address(0)) { - revert InvalidTransferID(transferID); - } + require(transfer.tokenAddress != address(0), InvalidTransferID(transferID)); return transfer; } @@ -365,16 +344,12 @@ contract DVATransferManager is IDVATransferManager, Initializable, OwnableUpgrad continue; } - if (approvalCriteria.sequentialApproval) { - revert ApprovalsMustBeSequential(transferID); - } + require(!approvalCriteria.sequentialApproval, ApprovalsMustBeSequential(transferID)); pendingApproverCount++; } - if (!approved) { - revert ApproverNotFound(transferID, caller); - } + require(approved, ApproverNotFound(transferID, caller)); return pendingApproverCount == 0; } @@ -431,13 +406,8 @@ contract DVATransferManager is IDVATransferManager, Initializable, OwnableUpgrad function _getPendingTransfer(bytes32 transferID) internal view returns (Transfer storage) { Transfer storage transfer = _transfers[transferID]; - if (transfer.tokenAddress == address(0)) { - revert InvalidTransferID(transferID); - } - - if (transfer.status != TransferStatus.PENDING) { - revert TransferIsNotInPendingStatus(transferID); - } + require(transfer.tokenAddress != address(0), InvalidTransferID(transferID)); + require(transfer.status == TransferStatus.PENDING, TransferIsNotInPendingStatus(transferID)); return transfer; } diff --git a/contracts/DVD/DVDTransferManager.sol b/contracts/DVD/DVDTransferManager.sol index 35c5642b..2bd359cd 100644 --- a/contracts/DVD/DVDTransferManager.sol +++ b/contracts/DVD/DVDTransferManager.sol @@ -70,16 +70,12 @@ pragma solidity 0.8.26; import "../roles/AgentRole.sol"; import "../token/IToken.sol"; -import "../libraries/errors/CommonLib.sol"; -import "../libraries/errors/InvalidArgumentLib.sol"; +import "../libraries/errors/CommonErrors.sol"; +import "../libraries/errors/InvalidArgumentErrors.sol"; contract DVDTransferManager is Ownable { - /// Errors - - error FeeWalletCannotBeZeroAddress(uint256 walletIndex); - /// Types struct Delivery { @@ -163,6 +159,8 @@ contract DVDTransferManager is Ownable { /// Errors + error FeeWalletCannotBeZeroAddress(uint256 walletIndex); + error InvalidFeeSettings(); error TransferIDDoesNotExist(); @@ -209,11 +207,11 @@ contract DVDTransferManager is Ownable { msg.sender == owner() || isTREXOwner(_token1, msg.sender) || isTREXOwner(_token2, msg.sender) - , CommonLib.OwnableUnauthorizedAccount(msg.sender)); + , CommonErrors.OwnableUnauthorizedAccount(msg.sender)); require( IERC20(_token1).totalSupply() != 0 && IERC20(_token2).totalSupply() != 0 - , InvalidArgumentLib.AddressNotERC20(IERC20(_token1).totalSupply() != 0 ? _token2 : _token1)); + , InvalidArgumentErrors.AddressNotERC20(IERC20(_token1).totalSupply() != 0 ? _token2 : _token1)); require( _fee1 <= 10**_feeBase && _fee2 <= 10**_feeBase && @@ -267,13 +265,13 @@ contract DVDTransferManager is Ownable { address _token2, uint256 _token2Amount) external { uint256 balance = IERC20(_token1).balanceOf(msg.sender); - require(balance >= _token1Amount, CommonLib.ERC20InsufficientBalance(msg.sender, balance, _token1Amount)); + require(balance >= _token1Amount, CommonErrors.ERC20InsufficientBalance(msg.sender, balance, _token1Amount)); uint256 allowance = IERC20(_token1).allowance(msg.sender, address(this)); - require(allowance >= _token1Amount, CommonLib.ERC20InsufficientAllowance(msg.sender, allowance, _token1Amount)); + require(allowance >= _token1Amount, CommonErrors.ERC20InsufficientAllowance(msg.sender, allowance, _token1Amount)); - require (_counterpart != address(0), InvalidArgumentLib.ZeroAddress()); - require(IERC20(_token2).totalSupply() != 0, InvalidArgumentLib.AddressNotERC20(_token2)); + require (_counterpart != address(0), InvalidArgumentErrors.ZeroAddress()); + require(IERC20(_token2).totalSupply() != 0, InvalidArgumentErrors.AddressNotERC20(_token2)); Delivery memory token1; token1.counterpart = msg.sender; token1.token = _token1; @@ -344,12 +342,12 @@ contract DVDTransferManager is Ownable { uint256 balance = token2Contract.balanceOf(token2.counterpart); require( balance >= token2.amount - , CommonLib.ERC20InsufficientBalance(token2.counterpart, balance, token2.amount)); + , CommonErrors.ERC20InsufficientBalance(token2.counterpart, balance, token2.amount)); uint256 allowance = token2Contract.allowance(token2.counterpart, address(this)); require( allowance >= token2.amount - , CommonLib.ERC20InsufficientAllowance(token2.counterpart, allowance, token2.amount)); + , CommonErrors.ERC20InsufficientAllowance(token2.counterpart, allowance, token2.amount)); TxFees memory fees = calculateFee(_transferID); if (fees.txFee1 != 0) { @@ -459,9 +457,7 @@ contract DVDTransferManager is Ownable { TxFees memory fees; Delivery memory token1 = token1ToDeliver[_transferID]; Delivery memory token2 = token2ToDeliver[_transferID]; - require( - token1.counterpart != address(0) && token2.counterpart != address(0) - , "transfer ID does not exist"); + require(token1.counterpart != address(0) && token2.counterpart != address(0), TransferIDDoesNotExist()); bytes32 parity = calculateParity(token1.token, token2.token); Fee memory feeDetails = fee[parity]; if (feeDetails.token1Fee != 0 || feeDetails.token2Fee != 0 ){ diff --git a/contracts/compliance/modular/ModularCompliance.sol b/contracts/compliance/modular/ModularCompliance.sol index f0c9db78..f3ac5d57 100644 --- a/contracts/compliance/modular/ModularCompliance.sol +++ b/contracts/compliance/modular/ModularCompliance.sol @@ -67,7 +67,7 @@ import "../../token/IToken.sol"; import "./IModularCompliance.sol"; import "./MCStorage.sol"; import "./modules/IModule.sol"; -import "../../libraries/errors/InvalidArgumentLib.sol"; +import "../../libraries/errors/InvalidArgumentErrors.sol"; contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage { @@ -107,7 +107,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage */ function bindToken(address _token) external override { require(owner() == msg.sender || (_tokenBound == address(0) && msg.sender == _token), OnlyOwnerOrTokenCanCall()); - require(_token != address(0), InvalidArgumentLib.ZeroAddress()); + require(_token != address(0), InvalidArgumentErrors.ZeroAddress()); _tokenBound = _token; emit TokenBound(_token); } @@ -118,7 +118,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage function unbindToken(address _token) external override { require(owner() == msg.sender || msg.sender == _token , OnlyOwnerOrTokenCanCall()); require(_token == _tokenBound, TokenNotBound()); - require(_token != address(0), InvalidArgumentLib.ZeroAddress()); + require(_token != address(0), InvalidArgumentErrors.ZeroAddress()); delete _tokenBound; emit TokenUnbound(_token); } @@ -127,7 +127,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage * @dev See {IModularCompliance-addModule}. */ function addModule(address _module) external override onlyOwner { - require(_module != address(0), InvalidArgumentLib.ZeroAddress()); + require(_module != address(0), InvalidArgumentErrors.ZeroAddress()); require(!_moduleBound[_module], ModuleAlreadyBound()); require(_modules.length <= 24, CannotAddMoreThan25Modules()); IModule module = IModule(_module); @@ -145,7 +145,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage * @dev See {IModularCompliance-removeModule}. */ function removeModule(address _module) external override onlyOwner { - require(_module != address(0), InvalidArgumentLib.ZeroAddress()); + require(_module != address(0), InvalidArgumentErrors.ZeroAddress()); require(_moduleBound[_module], ModuleNotBound()); uint256 length = _modules.length; for (uint256 i = 0; i < length; i++) { @@ -167,8 +167,8 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage require( _from != address(0) && _to != address(0) - , InvalidArgumentLib.ZeroAddress()); - require(_value > 0, InvalidArgumentLib.NoValue()); + , InvalidArgumentErrors.ZeroAddress()); + require(_value > 0, InvalidArgumentErrors.NoValue()); uint256 length = _modules.length; for (uint256 i = 0; i < length; i++) { IModule(_modules[i]).moduleTransferAction(_from, _to, _value); @@ -179,8 +179,8 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage * @dev See {IModularCompliance-created}. */ function created(address _to, uint256 _value) external onlyToken override { - require(_to != address(0), InvalidArgumentLib.ZeroAddress()); - require(_value > 0, InvalidArgumentLib.NoValue()); + require(_to != address(0), InvalidArgumentErrors.ZeroAddress()); + require(_value > 0, InvalidArgumentErrors.NoValue()); uint256 length = _modules.length; for (uint256 i = 0; i < length; i++) { IModule(_modules[i]).moduleMintAction(_to, _value); @@ -191,8 +191,8 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage * @dev See {IModularCompliance-destroyed}. */ function destroyed(address _from, uint256 _value) external onlyToken override { - require(_from != address(0), InvalidArgumentLib.ZeroAddress()); - require(_value > 0, InvalidArgumentLib.NoValue()); + require(_from != address(0), InvalidArgumentErrors.ZeroAddress()); + require(_value > 0, InvalidArgumentErrors.NoValue()); uint256 length = _modules.length; for (uint256 i = 0; i < length; i++) { IModule(_modules[i]).moduleBurnAction(_from, _value); diff --git a/contracts/compliance/modular/modules/AbstractModule.sol b/contracts/compliance/modular/modules/AbstractModule.sol index a2211f73..4c15ec0b 100644 --- a/contracts/compliance/modular/modules/AbstractModule.sol +++ b/contracts/compliance/modular/modules/AbstractModule.sol @@ -63,8 +63,8 @@ pragma solidity 0.8.26; import "./IModule.sol"; -import "../../../libraries/errors/InvalidArgumentLib.sol"; -import "../../../libraries/errors/ComplianceLib.sol"; +import "../../../libraries/errors/InvalidArgumentErrors.sol"; +import "../../../libraries/errors/ComplianceErrors.sol"; abstract contract AbstractModule is IModule { @@ -75,7 +75,7 @@ abstract contract AbstractModule is IModule { * @dev Throws if `_compliance` is not a bound compliance contract address. */ modifier onlyBoundCompliance(address _compliance) { - require(_complianceBound[_compliance], ComplianceLib.ComplianceNotBound()); + require(_complianceBound[_compliance], ComplianceErrors.ComplianceNotBound()); _; } @@ -83,7 +83,7 @@ abstract contract AbstractModule is IModule { * @dev Throws if called from an address that is not a bound compliance contract. */ modifier onlyComplianceCall() { - require(_complianceBound[msg.sender], ComplianceLib.OnlyBoundComplianceCanCall()); + require(_complianceBound[msg.sender], ComplianceErrors.OnlyBoundComplianceCanCall()); _; } @@ -91,9 +91,9 @@ abstract contract AbstractModule is IModule { * @dev See {IModule-bindCompliance}. */ function bindCompliance(address _compliance) external override { - require(_compliance != address(0), InvalidArgumentLib.ZeroAddress()); - require(!_complianceBound[_compliance], ComplianceLib.ComplianceAlreadyBound()); - require(msg.sender == _compliance, ComplianceLib.OnlyComplianceContractCanCall()); + require(_compliance != address(0), InvalidArgumentErrors.ZeroAddress()); + require(!_complianceBound[_compliance], ComplianceErrors.ComplianceAlreadyBound()); + require(msg.sender == _compliance, ComplianceErrors.OnlyComplianceContractCanCall()); _complianceBound[_compliance] = true; emit ComplianceBound(_compliance); } @@ -102,8 +102,8 @@ abstract contract AbstractModule is IModule { * @dev See {IModule-unbindCompliance}. */ function unbindCompliance(address _compliance) external onlyComplianceCall override { - require(_compliance != address(0), InvalidArgumentLib.ZeroAddress()); - require(msg.sender == _compliance, ComplianceLib.OnlyComplianceContractCanCall()); + require(_compliance != address(0), InvalidArgumentErrors.ZeroAddress()); + require(msg.sender == _compliance, ComplianceErrors.OnlyComplianceContractCanCall()); _complianceBound[_compliance] = false; emit ComplianceUnbound(_compliance); } diff --git a/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol index cfaa000b..b74d2fcb 100644 --- a/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol +++ b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol @@ -66,8 +66,8 @@ import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "./IModule.sol"; -import "../../../libraries/errors/InvalidArgumentLib.sol"; -import "../../../libraries/errors/ComplianceLib.sol"; +import "../../../libraries/errors/InvalidArgumentErrors.sol"; +import "../../../libraries/errors/ComplianceErrors.sol"; abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUpgradeable, UUPSUpgradeable { @@ -85,7 +85,7 @@ abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUp */ modifier onlyBoundCompliance(address _compliance) { AbstractModuleStorage storage s = _getAbstractModuleStorage(); - require(s.complianceBound[_compliance], ComplianceLib.ComplianceNotBound()); + require(s.complianceBound[_compliance], ComplianceErrors.ComplianceNotBound()); _; } @@ -94,7 +94,7 @@ abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUp */ modifier onlyComplianceCall() { AbstractModuleStorage storage s = _getAbstractModuleStorage(); - require(s.complianceBound[msg.sender], ComplianceLib.OnlyBoundComplianceCanCall()); + require(s.complianceBound[msg.sender], ComplianceErrors.OnlyBoundComplianceCanCall()); _; } @@ -103,9 +103,9 @@ abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUp */ function bindCompliance(address _compliance) external override { AbstractModuleStorage storage s = _getAbstractModuleStorage(); - require(_compliance != address(0), InvalidArgumentLib.ZeroAddress()); - require(!s.complianceBound[_compliance], ComplianceLib.ComplianceAlreadyBound()); - require(msg.sender == _compliance, ComplianceLib.OnlyComplianceContractCanCall()); + require(_compliance != address(0), InvalidArgumentErrors.ZeroAddress()); + require(!s.complianceBound[_compliance], ComplianceErrors.ComplianceAlreadyBound()); + require(msg.sender == _compliance, ComplianceErrors.OnlyComplianceContractCanCall()); s.complianceBound[_compliance] = true; emit ComplianceBound(_compliance); } @@ -115,8 +115,8 @@ abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUp */ function unbindCompliance(address _compliance) external onlyComplianceCall override { AbstractModuleStorage storage s = _getAbstractModuleStorage(); - require(_compliance != address(0), InvalidArgumentLib.ZeroAddress()); - require(msg.sender == _compliance, ComplianceLib.OnlyComplianceContractCanCall()); + require(_compliance != address(0), InvalidArgumentErrors.ZeroAddress()); + require(msg.sender == _compliance, ComplianceErrors.OnlyComplianceContractCanCall()); s.complianceBound[_compliance] = false; emit ComplianceUnbound(_compliance); } diff --git a/contracts/compliance/modular/modules/CountryAllowModule.sol b/contracts/compliance/modular/modules/CountryAllowModule.sol index 64cc31d4..3902c73d 100644 --- a/contracts/compliance/modular/modules/CountryAllowModule.sol +++ b/contracts/compliance/modular/modules/CountryAllowModule.sol @@ -144,7 +144,8 @@ contract CountryAllowModule is AbstractModuleUpgradeable { * emits an `AddedAllowedCountry` event */ function addAllowedCountry(uint16 _country) external onlyComplianceCall { - if ((_allowedCountries[msg.sender])[_country] == true) revert CountryAlreadyAllowed(msg.sender, _country); + require(!(_allowedCountries[msg.sender])[_country], CountryAlreadyAllowed(msg.sender, _country)); + (_allowedCountries[msg.sender])[_country] = true; emit CountryAllowed(msg.sender, _country); } @@ -158,7 +159,8 @@ contract CountryAllowModule is AbstractModuleUpgradeable { * emits an `RemoveAllowedCountry` event */ function removeAllowedCountry(uint16 _country) external onlyComplianceCall { - if ((_allowedCountries[msg.sender])[_country] == false) revert CountryNotAllowed(msg.sender, _country); + require((_allowedCountries[msg.sender])[_country], CountryNotAllowed(msg.sender, _country)); + (_allowedCountries[msg.sender])[_country] = false; emit CountryUnallowed(msg.sender, _country); } diff --git a/contracts/compliance/modular/modules/CountryRestrictModule.sol b/contracts/compliance/modular/modules/CountryRestrictModule.sol index 456acf17..4d9cecdf 100644 --- a/contracts/compliance/modular/modules/CountryRestrictModule.sol +++ b/contracts/compliance/modular/modules/CountryRestrictModule.sol @@ -74,14 +74,6 @@ import "./AbstractModuleUpgradeable.sol"; contract CountryRestrictModule is AbstractModuleUpgradeable { - /// errors - - error CountryAlreadyRestricted(); - - error CountryNotRestricted(); - - error Max195CountriesInBatch(); - /// Mapping between country and their restriction status per compliance contract mapping(address => mapping(uint16 => bool)) private _restrictedCountries; @@ -99,6 +91,16 @@ contract CountryRestrictModule is AbstractModuleUpgradeable { */ event RemovedRestrictedCountry(address indexed _compliance, uint16 _country); + /// errors + + error CountryAlreadyRestricted(); + + error CountryNotRestricted(); + + error Max195CountriesInBatch(); + + /// Functions + /** * @dev initializes the contract and sets the initial state. * @notice This function should only be called once during the contract deployment. diff --git a/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol b/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol index ae7c53d7..cf9d88a1 100644 --- a/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol +++ b/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol @@ -143,9 +143,7 @@ contract ExchangeMonthlyLimitsModule is AbstractModuleUpgradeable { * emits an `ExchangeIDAdded` event */ function addExchangeID(address _exchangeID) external onlyOwner { - if (isExchangeID(_exchangeID)) { - revert ONCHAINIDAlreadyTaggedAsExchange(_exchangeID); - } + require(!isExchangeID(_exchangeID), ONCHAINIDAlreadyTaggedAsExchange(_exchangeID)); _exchangeIDs[_exchangeID] = true; emit ExchangeIDAdded(_exchangeID); @@ -159,9 +157,8 @@ contract ExchangeMonthlyLimitsModule is AbstractModuleUpgradeable { * emits an `ExchangeIDRemoved` event */ function removeExchangeID(address _exchangeID) external onlyOwner { - if (!isExchangeID(_exchangeID)) { - revert ONCHAINIDNotTaggedAsExchange(_exchangeID); - } + require(isExchangeID(_exchangeID), ONCHAINIDNotTaggedAsExchange(_exchangeID)); + _exchangeIDs[_exchangeID] = false; emit ExchangeIDRemoved(_exchangeID); } diff --git a/contracts/compliance/modular/modules/MaxBalanceModule.sol b/contracts/compliance/modular/modules/MaxBalanceModule.sol index 4243a35d..6f4d30bf 100644 --- a/contracts/compliance/modular/modules/MaxBalanceModule.sol +++ b/contracts/compliance/modular/modules/MaxBalanceModule.sol @@ -139,13 +139,8 @@ contract MaxBalanceModule is AbstractModuleUpgradeable { * emits a `IDBalancePreSet` event */ function preSetModuleState(address _compliance, address _id, uint256 _balance) external { - if (OwnableUpgradeable(_compliance).owner() != msg.sender) { - revert OnlyComplianceOwnerCanCall(_compliance); - } - - if (IModularCompliance(_compliance).isModuleBound(address(this))) { - revert TokenAlreadyBound(_compliance); - } + require(OwnableUpgradeable(_compliance).owner() == msg.sender, OnlyComplianceOwnerCanCall(_compliance)); + require(!IModularCompliance(_compliance).isModuleBound(address(this)), TokenAlreadyBound(_compliance)); _preSetModuleState(_compliance, _id, _balance); } @@ -162,17 +157,9 @@ contract MaxBalanceModule is AbstractModuleUpgradeable { address _compliance, address[] calldata _id, uint256[] calldata _balance) external { - if(_id.length == 0 || _id.length != _balance.length) { - revert InvalidPresetValues(_compliance, _id, _balance); - } - - if (OwnableUpgradeable(_compliance).owner() != msg.sender) { - revert OnlyComplianceOwnerCanCall(_compliance); - } - - if (IModularCompliance(_compliance).isModuleBound(address(this))) { - revert TokenAlreadyBound(_compliance); - } + require(_id.length > 0 && _id.length == _balance.length, InvalidPresetValues(_compliance, _id, _balance)); + require(OwnableUpgradeable(_compliance).owner() == msg.sender, OnlyComplianceOwnerCanCall(_compliance)); + require(!IModularCompliance(_compliance).isModuleBound(address(this)), TokenAlreadyBound(_compliance)); for (uint i = 0; i < _id.length; i++) { _preSetModuleState(_compliance, _id[i], _balance[i]); @@ -187,9 +174,7 @@ contract MaxBalanceModule is AbstractModuleUpgradeable { * Only the owner of the Compliance smart contract can call this function */ function presetCompleted(address _compliance) external { - if (OwnableUpgradeable(_compliance).owner() != msg.sender) { - revert OnlyComplianceOwnerCanCall(_compliance); - } + require(OwnableUpgradeable(_compliance).owner() == msg.sender, OnlyComplianceOwnerCanCall(_compliance)); _compliancePresetStatus[_compliance] = true; } @@ -203,7 +188,7 @@ contract MaxBalanceModule is AbstractModuleUpgradeable { address _idTo = _getIdentity(msg.sender, _to); _IDBalance[msg.sender][_idTo] += _value; _IDBalance[msg.sender][_idFrom] -= _value; - if (_IDBalance[msg.sender][_idTo] > _maxBalance[msg.sender]) revert MaxBalanceExceeded(msg.sender, _value); + require(_IDBalance[msg.sender][_idTo] <= _maxBalance[msg.sender], MaxBalanceExceeded(msg.sender, _value)); } /** @@ -213,7 +198,7 @@ contract MaxBalanceModule is AbstractModuleUpgradeable { function moduleMintAction(address _to, uint256 _value) external override onlyComplianceCall { address _idTo = _getIdentity(msg.sender, _to); _IDBalance[msg.sender][_idTo] += _value; - if (_IDBalance[msg.sender][_idTo] > _maxBalance[msg.sender]) revert MaxBalanceExceeded(msg.sender, _value); + require(_IDBalance[msg.sender][_idTo] <= _maxBalance[msg.sender], MaxBalanceExceeded(msg.sender, _value)); } /** diff --git a/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol b/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol index d3db9f4b..ba947ae7 100644 --- a/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol +++ b/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol @@ -127,6 +127,8 @@ contract TimeExchangeLimitsModule is AbstractModuleUpgradeable { */ event ExchangeIDRemoved(address _exchangeID); + /// Errors + error ONCHAINIDAlreadyTaggedAsExchange(address _exchangeID); error ONCHAINIDNotTaggedAsExchange(address _exchangeID); @@ -151,11 +153,9 @@ contract TimeExchangeLimitsModule is AbstractModuleUpgradeable { function setExchangeLimit(address _exchangeID, Limit memory _limit) external onlyComplianceCall { bool limitIsAttributed = _limitValues[msg.sender][_exchangeID][_limit.limitTime].attributedLimit; uint8 limitCount = uint8(_exchangeLimits[msg.sender][_exchangeID].length); - if (!limitIsAttributed && limitCount >= 4) { - revert LimitsArraySizeExceeded(msg.sender, limitCount); - } + require(limitIsAttributed || limitCount < 4, LimitsArraySizeExceeded(msg.sender, limitCount)); - if (!limitIsAttributed && limitCount < 4) { + if (!limitIsAttributed) { _exchangeLimits[msg.sender][_exchangeID].push(_limit); _limitValues[msg.sender][_exchangeID][_limit.limitTime] = IndexLimit(true, limitCount); } else { @@ -173,9 +173,7 @@ contract TimeExchangeLimitsModule is AbstractModuleUpgradeable { * emits an `ExchangeIDAdded` event */ function addExchangeID(address _exchangeID) external onlyOwner { - if (isExchangeID(_exchangeID)) { - revert ONCHAINIDAlreadyTaggedAsExchange(_exchangeID); - } + require(!isExchangeID(_exchangeID), ONCHAINIDAlreadyTaggedAsExchange(_exchangeID)); _exchangeIDs[_exchangeID] = true; emit ExchangeIDAdded(_exchangeID); @@ -189,9 +187,8 @@ contract TimeExchangeLimitsModule is AbstractModuleUpgradeable { * emits an `ExchangeIDRemoved` event */ function removeExchangeID(address _exchangeID) external onlyOwner { - if (!isExchangeID(_exchangeID)) { - revert ONCHAINIDNotTaggedAsExchange(_exchangeID); - } + require(isExchangeID(_exchangeID), ONCHAINIDNotTaggedAsExchange(_exchangeID)); + _exchangeIDs[_exchangeID] = false; emit ExchangeIDRemoved(_exchangeID); } diff --git a/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol b/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol index 5fec8323..e6c43306 100644 --- a/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol +++ b/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol @@ -126,10 +126,9 @@ contract TimeTransfersLimitsModule is AbstractModuleUpgradeable { function setTimeTransferLimit(Limit calldata _limit) external onlyComplianceCall { bool limitIsAttributed = limitValues[msg.sender][_limit.limitTime].attributedLimit; uint8 limitCount = uint8(transferLimits[msg.sender].length); - if (!limitIsAttributed && limitCount >= 4) { - revert LimitsArraySizeExceeded(msg.sender, limitCount); - } - if (!limitIsAttributed && limitCount < 4) { + require(limitIsAttributed || limitCount < 4, LimitsArraySizeExceeded(msg.sender, limitCount)); + + if (!limitIsAttributed) { transferLimits[msg.sender].push(_limit); limitValues[msg.sender][_limit.limitTime] = IndexLimit(true, limitCount); } else { diff --git a/contracts/compliance/modular/modules/TransferFeesModule.sol b/contracts/compliance/modular/modules/TransferFeesModule.sol index 368e8ff0..a51b7fa0 100644 --- a/contracts/compliance/modular/modules/TransferFeesModule.sol +++ b/contracts/compliance/modular/modules/TransferFeesModule.sol @@ -117,14 +117,10 @@ contract TransferFeesModule is AbstractModuleUpgradeable { */ function setFee(uint256 _rate, address _collector) external onlyComplianceCall { address tokenAddress = IModularCompliance(msg.sender).getTokenBound(); - if (_rate > 10000) { - revert FeeRateIsOutOfRange(msg.sender, _rate); - } + require(_rate <= 10000, FeeRateIsOutOfRange(msg.sender, _rate)); IIdentityRegistry identityRegistry = IToken(tokenAddress).identityRegistry(); - if (!identityRegistry.isVerified(_collector)) { - revert CollectorAddressIsNotVerified(msg.sender, _collector); - } + require(identityRegistry.isVerified(_collector), CollectorAddressIsNotVerified(msg.sender, _collector)); _fees[msg.sender].rate = _rate; _fees[msg.sender].collector = _collector; diff --git a/contracts/factory/TREXFactory.sol b/contracts/factory/TREXFactory.sol index 25120d12..895c4ecd 100644 --- a/contracts/factory/TREXFactory.sol +++ b/contracts/factory/TREXFactory.sol @@ -77,7 +77,7 @@ import "../proxy/TrustedIssuersRegistryProxy.sol"; import "../proxy/ModularComplianceProxy.sol"; import "./ITREXFactory.sol"; import "@onchain-id/solidity/contracts/factory/IIdFactory.sol"; -import "../libraries/errors/InvalidArgumentLib.sol"; +import "../libraries/errors/InvalidArgumentErrors.sol"; contract TREXFactory is ITREXFactory, Ownable { @@ -91,6 +91,24 @@ contract TREXFactory is ITREXFactory, Ownable { /// mapping containing info about the token contracts corresponding to salt already used for CREATE2 deployments mapping(string => address) public tokenDeployed; + /// Errors + + error InvalidClaimPattern(); + + error InvalidCompliancePattern(); + + error InvalidImplementationAuthority(); + + error MaxClaimIssuersReached(uint256 max); + + error MaxClaimTopicsReached(uint256 max); + + error MaxAgentsReached(uint256 max); + + error MaxModuleActionsReached(uint256 max); + + error TokenAlreadyDeployed(); + /// constructor is setting the implementation authority and the Identity Factory of the TREX factory constructor(address implementationAuthority_, address idFactory_) { setImplementationAuthority(implementationAuthority_); @@ -104,20 +122,14 @@ contract TREXFactory is ITREXFactory, Ownable { function deployTREXSuite(string memory _salt, TokenDetails calldata _tokenDetails, ClaimDetails calldata _claimDetails) external override onlyOwner { - require(tokenDeployed[_salt] == address(0) - , "token already deployed"); - require((_claimDetails.issuers).length == (_claimDetails.issuerClaims).length - , "claim pattern not valid"); - require((_claimDetails.issuers).length <= 5 - , "max 5 claim issuers at deployment"); - require((_claimDetails.claimTopics).length <= 5 - , "max 5 claim topics at deployment"); - require((_tokenDetails.irAgents).length <= 5 && (_tokenDetails.tokenAgents).length <= 5 - , "max 5 agents at deployment"); - require((_tokenDetails.complianceModules).length <= 30 - , "max 30 module actions at deployment"); - require((_tokenDetails.complianceModules).length >= (_tokenDetails.complianceSettings).length - , "invalid compliance pattern"); + require(tokenDeployed[_salt] == address(0), TokenAlreadyDeployed()); + require((_claimDetails.issuers).length == (_claimDetails.issuerClaims).length, InvalidClaimPattern()); + require((_claimDetails.issuers).length <= 5, MaxClaimIssuersReached(5)); + require((_claimDetails.claimTopics).length <= 5, MaxClaimTopicsReached(5)); + require((_tokenDetails.irAgents).length <= 5 && (_tokenDetails.tokenAgents).length <= 5, MaxAgentsReached(5)); + require((_tokenDetails.complianceModules).length <= 30, MaxModuleActionsReached(30)); + require((_tokenDetails.complianceModules).length >= (_tokenDetails.complianceSettings).length, + InvalidCompliancePattern()); ITrustedIssuersRegistry tir = ITrustedIssuersRegistry(_deployTIR(_salt, _implementationAuthority)); IClaimTopicsRegistry ctr = IClaimTopicsRegistry(_deployCTR(_salt, _implementationAuthority)); @@ -209,7 +221,7 @@ contract TREXFactory is ITREXFactory, Ownable { * @dev See {ITREXFactory-setImplementationAuthority}. */ function setImplementationAuthority(address implementationAuthority_) public override onlyOwner { - require(implementationAuthority_ != address(0), InvalidArgumentLib.ZeroAddress()); + require(implementationAuthority_ != address(0), InvalidArgumentErrors.ZeroAddress()); // should not be possible to set an implementation authority that is not complete require( (ITREXImplementationAuthority(implementationAuthority_)).getTokenImplementation() != address(0) @@ -218,7 +230,7 @@ contract TREXFactory is ITREXFactory, Ownable { && (ITREXImplementationAuthority(implementationAuthority_)).getIRSImplementation() != address(0) && (ITREXImplementationAuthority(implementationAuthority_)).getMCImplementation() != address(0) && (ITREXImplementationAuthority(implementationAuthority_)).getTIRImplementation() != address(0), - "invalid Implementation Authority"); + InvalidImplementationAuthority()); _implementationAuthority = implementationAuthority_; emit ImplementationAuthoritySet(implementationAuthority_); } @@ -227,7 +239,7 @@ contract TREXFactory is ITREXFactory, Ownable { * @dev See {ITREXFactory-setIdFactory}. */ function setIdFactory(address idFactory_) public override onlyOwner { - require(idFactory_ != address(0), InvalidArgumentLib.ZeroAddress()); + require(idFactory_ != address(0), InvalidArgumentErrors.ZeroAddress()); _idFactory = idFactory_; emit IdFactorySet(idFactory_); } diff --git a/contracts/factory/TREXGateway.sol b/contracts/factory/TREXGateway.sol index 901ea7ad..c431a086 100644 --- a/contracts/factory/TREXGateway.sol +++ b/contracts/factory/TREXGateway.sol @@ -65,8 +65,8 @@ import "./ITREXGateway.sol"; import "../roles/AgentRole.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "../libraries/errors/InvalidArgumentLib.sol"; -import "../libraries/errors/RoleLib.sol"; +import "../libraries/errors/InvalidArgumentErrors.sol"; +import "../libraries/errors/RoleErrors.sol"; /// The Public Deployment Status is already set properly error PublicDeploymentAlreadyEnabled(); @@ -132,7 +132,7 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-setFactory}. */ function setFactory(address factory) external override onlyOwner { - require(factory != address(0), InvalidArgumentLib.ZeroAddress()); + require(factory != address(0), InvalidArgumentErrors.ZeroAddress()); _factory = factory; emit FactorySet(factory); @@ -177,7 +177,7 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-setDeploymentFee}. */ function setDeploymentFee(uint256 _fee, address _feeToken, address _feeCollector) external override onlyOwner { - require(_feeToken != address(0) && _feeCollector != address(0), InvalidArgumentLib.ZeroAddress()); + require(_feeToken != address(0) && _feeCollector != address(0), InvalidArgumentErrors.ZeroAddress()); _deploymentFee.fee = _fee; _deploymentFee.feeToken = _feeToken; @@ -189,7 +189,7 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-batchAddDeployer}. */ function batchAddDeployer(address[] calldata deployers) external override { - require(isAgent(msg.sender) || msg.sender == owner(), RoleLib.SenderIsNotAdmin()); + require(isAgent(msg.sender) || msg.sender == owner(), RoleErrors.SenderIsNotAdmin()); require(deployers.length <= 500, BatchMaxLengthExceeded(500)); for (uint256 i = 0; i < deployers.length; i++) { @@ -204,7 +204,7 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-addDeployer}. */ function addDeployer(address deployer) external override { - require(isAgent(msg.sender) || msg.sender == owner(), RoleLib.SenderIsNotAdmin()); + require(isAgent(msg.sender) || msg.sender == owner(), RoleErrors.SenderIsNotAdmin()); require(!isDeployer(deployer), DeployerAlreadyExists(deployer)); _deployers[deployer] = true; @@ -215,7 +215,7 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-batchRemoveDeployer}. */ function batchRemoveDeployer(address[] calldata deployers) external override { - require(isAgent(msg.sender) || msg.sender == owner(), RoleLib.SenderIsNotAdmin()); + require(isAgent(msg.sender) || msg.sender == owner(), RoleErrors.SenderIsNotAdmin()); require(deployers.length <= 500, BatchMaxLengthExceeded(500)); for (uint256 i = 0; i < deployers.length; i++) { @@ -230,7 +230,7 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-removeDeployer}. */ function removeDeployer(address deployer) external override { - require(isAgent(msg.sender) || msg.sender == owner(), RoleLib.SenderIsNotAdmin()); + require(isAgent(msg.sender) || msg.sender == owner(), RoleErrors.SenderIsNotAdmin()); require(isDeployer(deployer), DeployerDoesNotExist(deployer)); delete _deployers[deployer]; @@ -241,7 +241,7 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-batchApplyFeeDiscount}. */ function batchApplyFeeDiscount(address[] calldata deployers, uint16[] calldata discounts) external override { - require(isAgent(msg.sender) || msg.sender == owner(), RoleLib.SenderIsNotAdmin()); + require(isAgent(msg.sender) || msg.sender == owner(), RoleErrors.SenderIsNotAdmin()); require(deployers.length <= 500, BatchMaxLengthExceeded(500)); for (uint256 i = 0; i < deployers.length; i++) { @@ -256,7 +256,7 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-applyFeeDiscount}. */ function applyFeeDiscount(address deployer, uint16 discount) external override { - require(isAgent(msg.sender) || msg.sender == owner(), RoleLib.SenderIsNotAdmin()); + require(isAgent(msg.sender) || msg.sender == owner(), RoleErrors.SenderIsNotAdmin()); require(discount <= 10000, DiscountOutOfRange()); _feeDiscount[deployer] = discount; @@ -310,12 +310,10 @@ contract TREXGateway is ITREXGateway, AgentRole { */ function deployTREXSuite(ITREXFactory.TokenDetails memory _tokenDetails, ITREXFactory.ClaimDetails memory _claimDetails) public override { - if(!_publicDeploymentStatus && !isDeployer(msg.sender)) { - revert PublicDeploymentsNotAllowed(); - } - if(_publicDeploymentStatus && msg.sender != _tokenDetails.owner && !isDeployer(msg.sender)) { - revert PublicCannotDeployOnBehalf(); - } + require(_publicDeploymentStatus || isDeployer(msg.sender), PublicDeploymentsNotAllowed()); + require(!_publicDeploymentStatus || msg.sender == _tokenDetails.owner || isDeployer(msg.sender), + PublicCannotDeployOnBehalf()); + uint256 feeApplied = 0; if(_deploymentFeeEnabled) { if(_deploymentFee.fee > 0 && _feeDiscount[msg.sender] < 10000) { diff --git a/contracts/libraries/errors/CommonLib.sol b/contracts/libraries/errors/CommonErrors.sol similarity index 96% rename from contracts/libraries/errors/CommonLib.sol rename to contracts/libraries/errors/CommonErrors.sol index 98a0e0c7..ca0f43bd 100644 --- a/contracts/libraries/errors/CommonLib.sol +++ b/contracts/libraries/errors/CommonErrors.sol @@ -65,7 +65,7 @@ pragma solidity 0.8.26; -library CommonLib { +library CommonErrors { error InitializationFailed(); @@ -98,6 +98,12 @@ library CommonLib { */ error ERC20InvalidReceiver(address receiver); + /** + * @dev Indicates a failure with the token `sender`. Used in transfers. + * @param sender Address whose tokens are being transferred. + */ + error ERC20InvalidSender(address sender); + /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. diff --git a/contracts/libraries/errors/ComplianceLib.sol b/contracts/libraries/errors/ComplianceErrors.sol similarity index 99% rename from contracts/libraries/errors/ComplianceLib.sol rename to contracts/libraries/errors/ComplianceErrors.sol index 9e31551a..025b3092 100644 --- a/contracts/libraries/errors/ComplianceLib.sol +++ b/contracts/libraries/errors/ComplianceErrors.sol @@ -65,7 +65,7 @@ pragma solidity 0.8.26; -library ComplianceLib { +library ComplianceErrors { error ComplianceAlreadyBound(); diff --git a/contracts/libraries/errors/InvalidArgumentLib.sol b/contracts/libraries/errors/InvalidArgumentErrors.sol similarity index 99% rename from contracts/libraries/errors/InvalidArgumentLib.sol rename to contracts/libraries/errors/InvalidArgumentErrors.sol index 4a30ead7..22b99ae8 100644 --- a/contracts/libraries/errors/InvalidArgumentLib.sol +++ b/contracts/libraries/errors/InvalidArgumentErrors.sol @@ -64,7 +64,7 @@ pragma solidity 0.8.26; -library InvalidArgumentLib { +library InvalidArgumentErrors { /// @notice Thrown when the address is not an ERC20. error AddressNotERC20(address token); diff --git a/contracts/libraries/errors/RoleLib.sol b/contracts/libraries/errors/RoleErrors.sol similarity index 99% rename from contracts/libraries/errors/RoleLib.sol rename to contracts/libraries/errors/RoleErrors.sol index ed6bb40d..1b1ec92c 100644 --- a/contracts/libraries/errors/RoleLib.sol +++ b/contracts/libraries/errors/RoleErrors.sol @@ -64,7 +64,7 @@ pragma solidity 0.8.26; -library RoleLib { +library RoleErrors { error AccountAlreadyHasRole(); diff --git a/contracts/proxy/AbstractProxy.sol b/contracts/proxy/AbstractProxy.sol index c82c8a0b..5d268a23 100644 --- a/contracts/proxy/AbstractProxy.sol +++ b/contracts/proxy/AbstractProxy.sol @@ -65,7 +65,7 @@ pragma solidity 0.8.26; import "./interface/IProxy.sol"; import "./authority/ITREXImplementationAuthority.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import "../libraries/errors/InvalidArgumentLib.sol"; +import "../libraries/errors/InvalidArgumentErrors.sol"; abstract contract AbstractProxy is IProxy, Initializable { @@ -78,7 +78,7 @@ abstract contract AbstractProxy is IProxy, Initializable { */ function setImplementationAuthority(address _newImplementationAuthority) external override { require(msg.sender == getImplementationAuthority(), OnlyCurrentImplementationAuthorityCanCall()); - require(_newImplementationAuthority != address(0), InvalidArgumentLib.ZeroAddress()); + require(_newImplementationAuthority != address(0), InvalidArgumentErrors.ZeroAddress()); require( (ITREXImplementationAuthority(_newImplementationAuthority)).getTokenImplementation() != address(0) && (ITREXImplementationAuthority(_newImplementationAuthority)).getCTRImplementation() != address(0) @@ -86,7 +86,7 @@ abstract contract AbstractProxy is IProxy, Initializable { && (ITREXImplementationAuthority(_newImplementationAuthority)).getIRSImplementation() != address(0) && (ITREXImplementationAuthority(_newImplementationAuthority)).getMCImplementation() != address(0) && (ITREXImplementationAuthority(_newImplementationAuthority)).getTIRImplementation() != address(0) - , InvalidArgumentLib.InvalidImplementationAuthority()); + , InvalidArgumentErrors.InvalidImplementationAuthority()); _storeImplementationAuthority(_newImplementationAuthority); emit ImplementationAuthoritySet(_newImplementationAuthority); } diff --git a/contracts/proxy/ClaimTopicsRegistryProxy.sol b/contracts/proxy/ClaimTopicsRegistryProxy.sol index 5f8bac0d..2b4b517c 100644 --- a/contracts/proxy/ClaimTopicsRegistryProxy.sol +++ b/contracts/proxy/ClaimTopicsRegistryProxy.sol @@ -63,13 +63,13 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; -import "../libraries/errors/InvalidArgumentLib.sol"; -import "../libraries/errors/CommonLib.sol"; +import "../libraries/errors/InvalidArgumentErrors.sol"; +import "../libraries/errors/CommonErrors.sol"; contract ClaimTopicsRegistryProxy is AbstractProxy { constructor(address implementationAuthority) { - require(implementationAuthority != address(0), InvalidArgumentLib.ZeroAddress()); + require(implementationAuthority != address(0), InvalidArgumentErrors.ZeroAddress()); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); @@ -77,7 +77,7 @@ contract ClaimTopicsRegistryProxy is AbstractProxy { // solhint-disable-next-line avoid-low-level-calls (bool success, ) = logic.delegatecall(abi.encodeWithSignature("init()")); - require(success, CommonLib.InitializationFailed()); + require(success, CommonErrors.InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/IdentityRegistryProxy.sol b/contracts/proxy/IdentityRegistryProxy.sol index 0557384b..7e8086c6 100644 --- a/contracts/proxy/IdentityRegistryProxy.sol +++ b/contracts/proxy/IdentityRegistryProxy.sol @@ -63,7 +63,7 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; -import "../libraries/errors/CommonLib.sol"; +import "../libraries/errors/CommonErrors.sol"; contract IdentityRegistryProxy is AbstractProxy { @@ -78,7 +78,7 @@ contract IdentityRegistryProxy is AbstractProxy { && _trustedIssuersRegistry != address(0) && _claimTopicsRegistry != address(0) && _identityStorage != address(0) - , InvalidArgumentLib.ZeroAddress()); + , InvalidArgumentErrors.ZeroAddress()); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); @@ -91,7 +91,7 @@ contract IdentityRegistryProxy is AbstractProxy { _trustedIssuersRegistry, _claimTopicsRegistry, _identityStorage)); - require(success, CommonLib.InitializationFailed()); + require(success, CommonErrors.InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/IdentityRegistryStorageProxy.sol b/contracts/proxy/IdentityRegistryStorageProxy.sol index 72b6bde1..277bb1cb 100644 --- a/contracts/proxy/IdentityRegistryStorageProxy.sol +++ b/contracts/proxy/IdentityRegistryStorageProxy.sol @@ -63,12 +63,12 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; -import "../libraries/errors/CommonLib.sol"; +import "../libraries/errors/CommonErrors.sol"; contract IdentityRegistryStorageProxy is AbstractProxy { constructor(address implementationAuthority) { - require(implementationAuthority != address(0), InvalidArgumentLib.ZeroAddress()); + require(implementationAuthority != address(0), InvalidArgumentErrors.ZeroAddress()); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); @@ -76,7 +76,7 @@ contract IdentityRegistryStorageProxy is AbstractProxy { // solhint-disable-next-line avoid-low-level-calls (bool success, ) = logic.delegatecall(abi.encodeWithSignature("init()")); - require(success, CommonLib.InitializationFailed()); + require(success, CommonErrors.InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/ModularComplianceProxy.sol b/contracts/proxy/ModularComplianceProxy.sol index ba83e2bb..1814d28c 100644 --- a/contracts/proxy/ModularComplianceProxy.sol +++ b/contracts/proxy/ModularComplianceProxy.sol @@ -63,14 +63,14 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; -import "../libraries/errors/CommonLib.sol"; -import "../libraries/errors/InvalidArgumentLib.sol"; +import "../libraries/errors/CommonErrors.sol"; +import "../libraries/errors/InvalidArgumentErrors.sol"; contract ModularComplianceProxy is AbstractProxy { constructor(address implementationAuthority) { - require(implementationAuthority != address(0), InvalidArgumentLib.ZeroAddress()); + require(implementationAuthority != address(0), InvalidArgumentErrors.ZeroAddress()); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); @@ -78,7 +78,7 @@ contract ModularComplianceProxy is AbstractProxy { // solhint-disable-next-line avoid-low-level-calls (bool success, ) = logic.delegatecall(abi.encodeWithSignature("init()")); - require(success, CommonLib.InitializationFailed()); + require(success, CommonErrors.InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/TokenProxy.sol b/contracts/proxy/TokenProxy.sol index 4cd1282d..3dcbb92a 100644 --- a/contracts/proxy/TokenProxy.sol +++ b/contracts/proxy/TokenProxy.sol @@ -63,8 +63,8 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; -import "../libraries/errors/InvalidArgumentLib.sol"; -import "../libraries/errors/CommonLib.sol"; +import "../libraries/errors/InvalidArgumentErrors.sol"; +import "../libraries/errors/CommonErrors.sol"; contract TokenProxy is AbstractProxy { @@ -82,12 +82,12 @@ contract TokenProxy is AbstractProxy { implementationAuthority != address(0) && _identityRegistry != address(0) && _compliance != address(0) - , InvalidArgumentLib.ZeroAddress()); + , InvalidArgumentErrors.ZeroAddress()); require( keccak256(abi.encode(_name)) != keccak256(abi.encode("")) && keccak256(abi.encode(_symbol)) != keccak256(abi.encode("")) - , InvalidArgumentLib.EmptyString()); - require(0 <= _decimals && _decimals <= 18, InvalidArgumentLib.DecimalsBetween0And18()); + , InvalidArgumentErrors.EmptyString()); + require(0 <= _decimals && _decimals <= 18, InvalidArgumentErrors.DecimalsBetween0And18()); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); @@ -105,7 +105,7 @@ contract TokenProxy is AbstractProxy { _onchainID ) ); - require(success, CommonLib.InitializationFailed()); + require(success, CommonErrors.InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/TrustedIssuersRegistryProxy.sol b/contracts/proxy/TrustedIssuersRegistryProxy.sol index 7b69cfb4..542c6919 100644 --- a/contracts/proxy/TrustedIssuersRegistryProxy.sol +++ b/contracts/proxy/TrustedIssuersRegistryProxy.sol @@ -64,14 +64,14 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; -import "../libraries/errors/InvalidArgumentLib.sol"; -import "../libraries/errors/CommonLib.sol"; +import "../libraries/errors/InvalidArgumentErrors.sol"; +import "../libraries/errors/CommonErrors.sol"; contract TrustedIssuersRegistryProxy is AbstractProxy { constructor(address implementationAuthority) { - require(implementationAuthority != address(0), InvalidArgumentLib.ZeroAddress()); + require(implementationAuthority != address(0), InvalidArgumentErrors.ZeroAddress()); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); @@ -79,7 +79,7 @@ contract TrustedIssuersRegistryProxy is AbstractProxy { // solhint-disable-next-line avoid-low-level-calls (bool success, ) = logic.delegatecall(abi.encodeWithSignature("init()")); - require(success, CommonLib.InitializationFailed()); + require(success, CommonErrors.InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/authority/IAFactory.sol b/contracts/proxy/authority/IAFactory.sol index c45b3b4d..f33a2466 100644 --- a/contracts/proxy/authority/IAFactory.sol +++ b/contracts/proxy/authority/IAFactory.sol @@ -74,6 +74,10 @@ contract IAFactory is IIAFactory { /// mapping allowing to know if an IA was deployed by the factory or not mapping(address => bool) private _deployedByFactory; + /// Errors + + error OnlyReferenceIACanDeploy(); + /// functions constructor (address trexFactory) { @@ -84,8 +88,8 @@ contract IAFactory is IIAFactory { * @dev See {IIAFactory-deployIA}. */ function deployIA(address _token) external override returns (address){ - if (ITREXFactory(_trexFactory).getImplementationAuthority() != msg.sender) { - revert("only reference IA can deploy");} + require(ITREXFactory(_trexFactory).getImplementationAuthority() == msg.sender, + OnlyReferenceIACanDeploy()); TREXImplementationAuthority _newIA = new TREXImplementationAuthority(false, ITREXImplementationAuthority(msg.sender).getTREXFactory(), address(this)); _newIA.fetchVersion(ITREXImplementationAuthority(msg.sender).getCurrentVersion()); diff --git a/contracts/proxy/authority/TREXImplementationAuthority.sol b/contracts/proxy/authority/TREXImplementationAuthority.sol index 1e35795a..088e4d53 100644 --- a/contracts/proxy/authority/TREXImplementationAuthority.sol +++ b/contracts/proxy/authority/TREXImplementationAuthority.sol @@ -68,10 +68,27 @@ import "../../token/IToken.sol"; import "../interface/IProxy.sol"; import "../../factory/ITREXFactory.sol"; import "./IIAFactory.sol"; -import "../../libraries/errors/InvalidArgumentLib.sol"; +import "../../libraries/errors/InvalidArgumentErrors.sol"; contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { + /// variables + + /// current version + Version private _currentVersion; + + /// mapping to get contracts of each version + mapping(bytes32 => TREXContracts) private _contracts; + + /// reference ImplementationAuthority used by the TREXFactory + bool private _reference; + + /// address of TREXFactory contract + address private _trexFactory; + + /// address of factory for TREXImplementationAuthority contracts + address private _iaFactory; + /// Errors error CallerNotOwnerOfAllImpactedContracts(); @@ -82,6 +99,8 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { error NewIAIsNotAReferenceContract(); + error NonExistingVersion(); + error OnlyReferenceContractCanAddVersion(); error OnlyReferenceContractCanCall(); @@ -90,24 +109,11 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { error VersionAlreadyFetched(); - error VersionOfNewIAMustBeTheSameAsCurrentIA(); - - /// variables - - /// current version - Version private _currentVersion; - - /// mapping to get contracts of each version - mapping(bytes32 => TREXContracts) private _contracts; - - /// reference ImplementationAuthority used by the TREXFactory - bool private _reference; + error VersionAlreadyExists(); - /// address of TREXFactory contract - address private _trexFactory; + error VersionAlreadyInUse(); - /// address of factory for TREXImplementationAuthority contracts - address private _iaFactory; + error VersionOfNewIAMustBeTheSameAsCurrentIA(); /// functions @@ -167,9 +173,8 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { */ function fetchVersion(Version calldata _version) external override { require(!isReferenceContract(), CannotCallOnReferenceContract()); - if (_contracts[_versionToBytes(_version)].tokenImplementation != address(0)) { - revert VersionAlreadyFetched(); - } + require(_contracts[_versionToBytes(_version)].tokenImplementation == address(0), VersionAlreadyFetched()); + _contracts[_versionToBytes(_version)] = ITREXImplementationAuthority(getReferenceContract()).getContracts(_version); emit TREXVersionFetched(_version, _contracts[_versionToBytes(_version)]); @@ -180,10 +185,8 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { */ // solhint-disable-next-line code-complexity, function-max-lines function changeImplementationAuthority(address _token, address _newImplementationAuthority) external override { - require(_token != address(0), InvalidArgumentLib.ZeroAddress()); - if(_newImplementationAuthority == address(0) && !isReferenceContract()){ - revert OnlyReferenceContractCanDeployNewIA(); - } + require(_token != address(0), InvalidArgumentErrors.ZeroAddress()); + require(_newImplementationAuthority != address(0) || isReferenceContract(), OnlyReferenceContractCanDeployNewIA()); address _ir = address(IToken(_token).identityRegistry()); address _mc = address(IToken(_token).compliance()); @@ -192,35 +195,31 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { address _tir = address(IIdentityRegistry(_ir).issuersRegistry()); // calling this function requires ownership of ALL contracts of the T-REX suite - if( - Ownable(_token).owner() != msg.sender - || Ownable(_ir).owner() != msg.sender - || Ownable(_mc).owner() != msg.sender - || Ownable(_irs).owner() != msg.sender - || Ownable(_ctr).owner() != msg.sender - || Ownable(_tir).owner() != msg.sender) { - revert CallerNotOwnerOfAllImpactedContracts(); - } + require( + Ownable(_token).owner() == msg.sender + && Ownable(_ir).owner() == msg.sender + && Ownable(_mc).owner() == msg.sender + && Ownable(_irs).owner() == msg.sender + && Ownable(_ctr).owner() == msg.sender + && Ownable(_tir).owner() == msg.sender, + CallerNotOwnerOfAllImpactedContracts()); if(_newImplementationAuthority == address(0)) { _newImplementationAuthority = IIAFactory(_iaFactory).deployIA(_token); } else { - if( - _versionToBytes(ITREXImplementationAuthority(_newImplementationAuthority).getCurrentVersion()) != - _versionToBytes(_currentVersion)) { - revert VersionOfNewIAMustBeTheSameAsCurrentIA(); - } - if( - ITREXImplementationAuthority(_newImplementationAuthority).isReferenceContract() && - _newImplementationAuthority != getReferenceContract()) { - revert NewIAIsNotAReferenceContract(); - } - if( - !IIAFactory(_iaFactory).deployedByFactory(_newImplementationAuthority) && - _newImplementationAuthority != getReferenceContract()) { - revert InvalidIA(); - } + require( + _versionToBytes(ITREXImplementationAuthority(_newImplementationAuthority).getCurrentVersion()) == + _versionToBytes(_currentVersion), + VersionOfNewIAMustBeTheSameAsCurrentIA()); + require( + !ITREXImplementationAuthority(_newImplementationAuthority).isReferenceContract() || + _newImplementationAuthority == getReferenceContract(), + NewIAIsNotAReferenceContract()); + require( + IIAFactory(_iaFactory).deployedByFactory(_newImplementationAuthority) || + _newImplementationAuthority == getReferenceContract(), + InvalidIA()); } IProxy(_token).setImplementationAuthority(_newImplementationAuthority); @@ -303,9 +302,8 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { */ function addTREXVersion(Version calldata _version, TREXContracts calldata _trex) public override onlyOwner { require(isReferenceContract(), OnlyReferenceContractCanAddVersion()); - if (_contracts[_versionToBytes(_version)].tokenImplementation != address(0)) { - revert("version already exists"); - } + require(_contracts[_versionToBytes(_version)].tokenImplementation == address(0), VersionAlreadyExists()); + require( _trex.ctrImplementation != address(0) && _trex.irImplementation != address(0) @@ -313,7 +311,8 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { && _trex.mcImplementation != address(0) && _trex.tirImplementation != address(0) && _trex.tokenImplementation != address(0) - , InvalidArgumentLib.ZeroAddress()); + , InvalidArgumentErrors.ZeroAddress()); + _contracts[_versionToBytes(_version)] = _trex; emit TREXVersionAdded(_version, _trex); } @@ -322,12 +321,9 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { * @dev See {ITREXImplementationAuthority-useTREXVersion}. */ function useTREXVersion(Version calldata _version) public override onlyOwner { - if (_versionToBytes(_version) == _versionToBytes(_currentVersion)) { - revert("version already in use"); - } - if (_contracts[_versionToBytes(_version)].tokenImplementation == address(0)) { - revert("invalid argument - non existing version"); - } + require(_versionToBytes(_version) != _versionToBytes(_currentVersion), VersionAlreadyInUse()); + require(_contracts[_versionToBytes(_version)].tokenImplementation != address(0), NonExistingVersion()); + _currentVersion = _version; emit VersionUpdated(_version); } diff --git a/contracts/registry/implementation/IdentityRegistry.sol b/contracts/registry/implementation/IdentityRegistry.sol index d7537873..e9b84e8b 100644 --- a/contracts/registry/implementation/IdentityRegistry.sol +++ b/contracts/registry/implementation/IdentityRegistry.sol @@ -71,7 +71,7 @@ import "../interface/IIdentityRegistry.sol"; import "../../roles/AgentRoleUpgradeable.sol"; import "../interface/IIdentityRegistryStorage.sol"; import "../storage/IRStorage.sol"; -import "../../libraries/errors/InvalidArgumentLib.sol"; +import "../../libraries/errors/InvalidArgumentErrors.sol"; contract IdentityRegistry is IIdentityRegistry, AgentRoleUpgradeable, IRStorage { @@ -94,7 +94,7 @@ contract IdentityRegistry is IIdentityRegistry, AgentRoleUpgradeable, IRStorage _trustedIssuersRegistry != address(0) && _claimTopicsRegistry != address(0) && _identityStorage != address(0) - , InvalidArgumentLib.ZeroAddress()); + , InvalidArgumentErrors.ZeroAddress()); _tokenTopicsRegistry = IClaimTopicsRegistry(_claimTopicsRegistry); _tokenIssuersRegistry = ITrustedIssuersRegistry(_trustedIssuersRegistry); _tokenIdentityStorage = IIdentityRegistryStorage(_identityStorage); diff --git a/contracts/registry/implementation/IdentityRegistryStorage.sol b/contracts/registry/implementation/IdentityRegistryStorage.sol index 925f1e2f..387c0470 100644 --- a/contracts/registry/implementation/IdentityRegistryStorage.sol +++ b/contracts/registry/implementation/IdentityRegistryStorage.sol @@ -67,7 +67,7 @@ import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; import "../../roles/AgentRoleUpgradeable.sol"; import "../interface/IIdentityRegistryStorage.sol"; import "../storage/IRSStorage.sol"; -import "../../libraries/errors/InvalidArgumentLib.sol"; +import "../../libraries/errors/InvalidArgumentErrors.sol"; contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeable, IRSStorage { @@ -97,7 +97,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab require( _userAddress != address(0) && address(_identity) != address(0) - , InvalidArgumentLib.ZeroAddress()); + , InvalidArgumentErrors.ZeroAddress()); require(address(_identities[_userAddress].identityContract) == address(0), AddressAlreadyStored()); _identities[_userAddress].identityContract = _identity; _identities[_userAddress].investorCountry = _country; @@ -111,7 +111,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab require( _userAddress != address(0) && address(_identity) != address(0) - , InvalidArgumentLib.ZeroAddress()); + , InvalidArgumentErrors.ZeroAddress()); require(address(_identities[_userAddress].identityContract) != address(0), AddressNotYetStored()); IIdentity oldIdentity = _identities[_userAddress].identityContract; _identities[_userAddress].identityContract = _identity; @@ -122,7 +122,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab * @dev See {IIdentityRegistryStorage-modifyStoredInvestorCountry}. */ function modifyStoredInvestorCountry(address _userAddress, uint16 _country) external override onlyAgent { - require(_userAddress != address(0), InvalidArgumentLib.ZeroAddress()); + require(_userAddress != address(0), InvalidArgumentErrors.ZeroAddress()); require(address(_identities[_userAddress].identityContract) != address(0), AddressNotYetStored()); _identities[_userAddress].investorCountry = _country; emit CountryModified(_userAddress, _country); @@ -132,7 +132,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab * @dev See {IIdentityRegistryStorage-removeIdentityFromStorage}. */ function removeIdentityFromStorage(address _userAddress) external override onlyAgent { - require(_userAddress != address(0), InvalidArgumentLib.ZeroAddress()); + require(_userAddress != address(0), InvalidArgumentErrors.ZeroAddress()); require(address(_identities[_userAddress].identityContract) != address(0), AddressNotYetStored()); IIdentity oldIdentity = _identities[_userAddress].identityContract; delete _identities[_userAddress]; @@ -143,7 +143,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab * @dev See {IIdentityRegistryStorage-bindIdentityRegistry}. */ function bindIdentityRegistry(address _identityRegistry) external override { - require(_identityRegistry != address(0), InvalidArgumentLib.ZeroAddress()); + require(_identityRegistry != address(0), InvalidArgumentErrors.ZeroAddress()); require(_identityRegistries.length < 300, CannotBindMoreThan300IRTo1IRS()); addAgent(_identityRegistry); _identityRegistries.push(_identityRegistry); @@ -154,7 +154,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab * @dev See {IIdentityRegistryStorage-unbindIdentityRegistry}. */ function unbindIdentityRegistry(address _identityRegistry) external override { - require(_identityRegistry != address(0), InvalidArgumentLib.ZeroAddress()); + require(_identityRegistry != address(0), InvalidArgumentErrors.ZeroAddress()); require(_identityRegistries.length > 0, IdentityRegistryNotStored()); uint256 length = _identityRegistries.length; for (uint256 i = 0; i < length; i++) { diff --git a/contracts/registry/implementation/TrustedIssuersRegistry.sol b/contracts/registry/implementation/TrustedIssuersRegistry.sol index 4a461ba0..ae3afe74 100644 --- a/contracts/registry/implementation/TrustedIssuersRegistry.sol +++ b/contracts/registry/implementation/TrustedIssuersRegistry.sol @@ -67,7 +67,7 @@ import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../interface/ITrustedIssuersRegistry.sol"; import "../storage/TIRStorage.sol"; -import "../../libraries/errors/InvalidArgumentLib.sol"; +import "../../libraries/errors/InvalidArgumentErrors.sol"; contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, TIRStorage { @@ -97,7 +97,7 @@ contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, * @dev See {ITrustedIssuersRegistry-addTrustedIssuer}. */ function addTrustedIssuer(IClaimIssuer _trustedIssuer, uint256[] calldata _claimTopics) external override onlyOwner { - require(address(_trustedIssuer) != address(0), InvalidArgumentLib.ZeroAddress()); + require(address(_trustedIssuer) != address(0), InvalidArgumentErrors.ZeroAddress()); require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length == 0, TrustedIssuerAlreadyExists()); require(_claimTopics.length > 0, TrustedClaimTopicsCannotBeEmpty()); require(_claimTopics.length <= 15, CannotHaveMoreThan15ClaimTopics()); @@ -114,7 +114,7 @@ contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, * @dev See {ITrustedIssuersRegistry-removeTrustedIssuer}. */ function removeTrustedIssuer(IClaimIssuer _trustedIssuer) external override onlyOwner { - require(address(_trustedIssuer) != address(0), InvalidArgumentLib.ZeroAddress()); + require(address(_trustedIssuer) != address(0), InvalidArgumentErrors.ZeroAddress()); require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length != 0, NotATrustedIssuer()); uint256 length = _trustedIssuers.length; for (uint256 i = 0; i < length; i++) { @@ -147,7 +147,7 @@ contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, * @dev See {ITrustedIssuersRegistry-updateIssuerClaimTopics}. */ function updateIssuerClaimTopics(IClaimIssuer _trustedIssuer, uint256[] calldata _claimTopics) external override onlyOwner { - require(address(_trustedIssuer) != address(0), InvalidArgumentLib.ZeroAddress()); + require(address(_trustedIssuer) != address(0), InvalidArgumentErrors.ZeroAddress()); require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length != 0, NotATrustedIssuer()); require(_claimTopics.length <= 15, CannotHaveMoreThan15ClaimTopics()); require(_claimTopics.length > 0, ClaimTopicsCannotBeEmpty()); diff --git a/contracts/roles/AgentRole.sol b/contracts/roles/AgentRole.sol index 8935d065..48cd6e76 100644 --- a/contracts/roles/AgentRole.sol +++ b/contracts/roles/AgentRole.sol @@ -66,8 +66,8 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts/access/Ownable.sol"; import "./Roles.sol"; -import "../libraries/errors/InvalidArgumentLib.sol"; -import "../libraries/errors/RoleLib.sol"; +import "../libraries/errors/InvalidArgumentErrors.sol"; +import "../libraries/errors/RoleErrors.sol"; contract AgentRole is Ownable { using Roles for Roles.Role; @@ -78,18 +78,18 @@ contract AgentRole is Ownable { event AgentRemoved(address indexed _agent); modifier onlyAgent() { - require(isAgent(msg.sender), RoleLib.CallerDoesNotHaveAgentRole()); + require(isAgent(msg.sender), RoleErrors.CallerDoesNotHaveAgentRole()); _; } function addAgent(address _agent) public onlyOwner { - require(_agent != address(0), InvalidArgumentLib.ZeroAddress()); + require(_agent != address(0), InvalidArgumentErrors.ZeroAddress()); _agents.add(_agent); emit AgentAdded(_agent); } function removeAgent(address _agent) public onlyOwner { - require(_agent != address(0), InvalidArgumentLib.ZeroAddress()); + require(_agent != address(0), InvalidArgumentErrors.ZeroAddress()); _agents.remove(_agent); emit AgentRemoved(_agent); } diff --git a/contracts/roles/AgentRoleUpgradeable.sol b/contracts/roles/AgentRoleUpgradeable.sol index 040080c4..f0484178 100644 --- a/contracts/roles/AgentRoleUpgradeable.sol +++ b/contracts/roles/AgentRoleUpgradeable.sol @@ -66,8 +66,8 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "./Roles.sol"; -import "../libraries/errors/InvalidArgumentLib.sol"; -import "../libraries/errors/RoleLib.sol"; +import "../libraries/errors/InvalidArgumentErrors.sol"; +import "../libraries/errors/RoleErrors.sol"; contract AgentRoleUpgradeable is OwnableUpgradeable { using Roles for Roles.Role; @@ -78,18 +78,18 @@ contract AgentRoleUpgradeable is OwnableUpgradeable { event AgentRemoved(address indexed _agent); modifier onlyAgent() { - require(isAgent(msg.sender), RoleLib.CallerDoesNotHaveAgentRole()); + require(isAgent(msg.sender), RoleErrors.CallerDoesNotHaveAgentRole()); _; } function addAgent(address _agent) public onlyOwner { - require(_agent != address(0), InvalidArgumentLib.ZeroAddress()); + require(_agent != address(0), InvalidArgumentErrors.ZeroAddress()); _agents.add(_agent); emit AgentAdded(_agent); } function removeAgent(address _agent) public onlyOwner { - require(_agent != address(0), InvalidArgumentLib.ZeroAddress()); + require(_agent != address(0), InvalidArgumentErrors.ZeroAddress()); _agents.remove(_agent); emit AgentRemoved(_agent); } diff --git a/contracts/roles/Roles.sol b/contracts/roles/Roles.sol index edca53f2..da63a02f 100644 --- a/contracts/roles/Roles.sol +++ b/contracts/roles/Roles.sol @@ -63,8 +63,8 @@ pragma solidity 0.8.26; -import "../libraries/errors/InvalidArgumentLib.sol"; -import "../libraries/errors/RoleLib.sol"; +import "../libraries/errors/InvalidArgumentErrors.sol"; +import "../libraries/errors/RoleErrors.sol"; /** * @title Roles @@ -79,7 +79,7 @@ library Roles { * @dev Give an account access to this role. */ function add(Role storage role, address account) internal { - require(!has(role, account), RoleLib.AccountAlreadyHasRole()); + require(!has(role, account), RoleErrors.AccountAlreadyHasRole()); role.bearer[account] = true; } @@ -87,7 +87,7 @@ library Roles { * @dev Remove an account's access to this role. */ function remove(Role storage role, address account) internal { - require(has(role, account), RoleLib.AccountDoesNotHaveRole()); + require(has(role, account), RoleErrors.AccountDoesNotHaveRole()); role.bearer[account] = false; } @@ -96,7 +96,7 @@ library Roles { * @return bool */ function has(Role storage role, address account) internal view returns (bool) { - require(account != address(0), InvalidArgumentLib.ZeroAddress()); + require(account != address(0), InvalidArgumentErrors.ZeroAddress()); return role.bearer[account]; } } diff --git a/contracts/roles/permissioning/agent/AgentManager.sol b/contracts/roles/permissioning/agent/AgentManager.sol index c7c63fdc..ac3b3d74 100644 --- a/contracts/roles/permissioning/agent/AgentManager.sol +++ b/contracts/roles/permissioning/agent/AgentManager.sol @@ -68,7 +68,7 @@ import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; import "../../../token/IToken.sol"; import "../../../registry/interface/IIdentityRegistry.sol"; import "./AgentRoles.sol"; -import "../../../libraries/errors/RoleLib.sol"; +import "../../../libraries/errors/RoleErrors.sol"; contract AgentManager is AgentRoles { /// @dev the token managed by this AgentManager contract @@ -95,7 +95,7 @@ contract AgentManager is AgentRoles { require( isTransferManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleLib.SenderIsNotTransferManager() + RoleErrors.SenderIsNotTransferManager() ); token.forcedTransfer(_from, _to, _amount); } @@ -117,7 +117,7 @@ contract AgentManager is AgentRoles { require( isTransferManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleLib.SenderIsNotTransferManager() + RoleErrors.SenderIsNotTransferManager() ); token.batchForcedTransfer(_fromList, _toList, _amounts); } @@ -134,7 +134,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleLib.SenderIsNotFreezer()); + , RoleErrors.SenderIsNotFreezer()); token.pause(); } @@ -150,7 +150,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleLib.SenderIsNotFreezer()); + , RoleErrors.SenderIsNotFreezer()); token.unpause(); } @@ -170,7 +170,7 @@ contract AgentManager is AgentRoles { require( isSupplyModifier(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleLib.SenderIsNotSupplyModifier() + RoleErrors.SenderIsNotSupplyModifier() ); token.mint(_to, _amount); } @@ -191,7 +191,7 @@ contract AgentManager is AgentRoles { require( isSupplyModifier(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleLib.SenderIsNotSupplyModifier() + RoleErrors.SenderIsNotSupplyModifier() ); token.batchMint(_toList, _amounts); } @@ -213,7 +213,7 @@ contract AgentManager is AgentRoles { isSupplyModifier( address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleLib.SenderIsNotSupplyModifier() + , RoleErrors.SenderIsNotSupplyModifier() ); token.burn(_userAddress, _amount); } @@ -234,7 +234,7 @@ contract AgentManager is AgentRoles { require( isSupplyModifier(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleLib.SenderIsNotSupplyModifier() + , RoleErrors.SenderIsNotSupplyModifier() ); token.batchBurn(_userAddresses, _amounts); } @@ -255,7 +255,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleLib.SenderIsNotFreezer()); + , RoleErrors.SenderIsNotFreezer()); token.setAddressFrozen(_userAddress, _freeze); } @@ -275,7 +275,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleLib.SenderIsNotFreezer()); + , RoleErrors.SenderIsNotFreezer()); token.batchSetAddressFrozen(_userAddresses, _freeze); } @@ -295,7 +295,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleLib.SenderIsNotFreezer()); + , RoleErrors.SenderIsNotFreezer()); token.freezePartialTokens(_userAddress, _amount); } @@ -315,7 +315,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleLib.SenderIsNotFreezer()); + , RoleErrors.SenderIsNotFreezer()); token.batchFreezePartialTokens(_userAddresses, _amounts); } @@ -335,7 +335,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleLib.SenderIsNotFreezer()); + , RoleErrors.SenderIsNotFreezer()); token.unfreezePartialTokens(_userAddress, _amount); } @@ -355,7 +355,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleLib.SenderIsNotFreezer()); + , RoleErrors.SenderIsNotFreezer()); token.batchUnfreezePartialTokens(_userAddresses, _amounts); } @@ -376,7 +376,7 @@ contract AgentManager is AgentRoles { require( isRecoveryAgent(address(_managerOnchainID)) && _managerOnchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleLib.SenderIsNotRecoveryAgent() + , RoleErrors.SenderIsNotRecoveryAgent() ); token.recoveryAddress(_lostWallet, _newWallet, _onchainID); } @@ -398,7 +398,7 @@ contract AgentManager is AgentRoles { require( isWhiteListManager(address(_managerOnchainID)) && _managerOnchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleLib.SenderIsNotWhiteListManager() + , RoleErrors.SenderIsNotWhiteListManager() ); token.identityRegistry().registerIdentity(_userAddress, _onchainID, _country); } @@ -419,7 +419,7 @@ contract AgentManager is AgentRoles { require( isWhiteListManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleLib.SenderIsNotWhiteListManager() + , RoleErrors.SenderIsNotWhiteListManager() ); token.identityRegistry().updateIdentity(_userAddress, _identity); } @@ -440,7 +440,7 @@ contract AgentManager is AgentRoles { require( isWhiteListManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleLib.SenderIsNotWhiteListManager() + , RoleErrors.SenderIsNotWhiteListManager() ); token.identityRegistry().updateCountry(_userAddress, _country); } @@ -457,7 +457,7 @@ contract AgentManager is AgentRoles { require( isWhiteListManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleLib.SenderIsNotWhiteListManager() + , RoleErrors.SenderIsNotWhiteListManager() ); token.identityRegistry().deleteIdentity(_userAddress); } diff --git a/contracts/roles/permissioning/agent/AgentRoles.sol b/contracts/roles/permissioning/agent/AgentRoles.sol index f08683b6..6acfc28b 100644 --- a/contracts/roles/permissioning/agent/AgentRoles.sol +++ b/contracts/roles/permissioning/agent/AgentRoles.sol @@ -66,7 +66,7 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts/access/Ownable.sol"; import "../../Roles.sol"; -import "../../../libraries/errors/RoleLib.sol"; +import "../../../libraries/errors/RoleErrors.sol"; contract AgentRoles is Ownable { using Roles for Roles.Role; @@ -89,7 +89,7 @@ contract AgentRoles is Ownable { /// modifiers modifier onlyAdmin() { - require(owner() == msg.sender || isAgentAdmin(_msgSender()), RoleLib.SenderIsNotAdmin()); + require(owner() == msg.sender || isAgentAdmin(_msgSender()), RoleErrors.SenderIsNotAdmin()); _; } diff --git a/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol b/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol index cc709639..1f9e5524 100644 --- a/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol +++ b/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol @@ -66,7 +66,7 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../../Roles.sol"; -import "../../../libraries/errors/RoleLib.sol"; +import "../../../libraries/errors/RoleErrors.sol"; contract AgentRolesUpgradeable is OwnableUpgradeable @@ -91,7 +91,7 @@ contract AgentRolesUpgradeable is OwnableUpgradeable /// modifiers modifier onlyAdmin() { - require(owner() == msg.sender || isAgentAdmin(_msgSender()), RoleLib.SenderIsNotAdmin()); + require(owner() == msg.sender || isAgentAdmin(_msgSender()), RoleErrors.SenderIsNotAdmin()); _; } diff --git a/contracts/roles/permissioning/owner/OwnerManager.sol b/contracts/roles/permissioning/owner/OwnerManager.sol index c748e8fe..70c8cf8a 100644 --- a/contracts/roles/permissioning/owner/OwnerManager.sol +++ b/contracts/roles/permissioning/owner/OwnerManager.sol @@ -72,7 +72,7 @@ import "./OwnerRoles.sol"; import "../../AgentRole.sol"; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; -import "../../../libraries/errors/RoleLib.sol"; +import "../../../libraries/errors/RoleErrors.sol"; contract OwnerManager is OwnerRoles { /// @dev the token that is managed by this OwnerManager Contract @@ -105,7 +105,7 @@ contract OwnerManager is OwnerRoles { function callSetIdentityRegistry(address _identityRegistry, IIdentity _onchainID) external { require( isRegistryAddressSetter(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleLib.SenderIsNotRegistryAddressSetter() + RoleErrors.SenderIsNotRegistryAddressSetter() ); token.setIdentityRegistry(_identityRegistry); } @@ -121,7 +121,7 @@ contract OwnerManager is OwnerRoles { function callSetCompliance(address _compliance, IIdentity _onchainID) external { require( isComplianceSetter(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleLib.SenderIsNotComplianceSetter() + RoleErrors.SenderIsNotComplianceSetter() ); token.setCompliance(_compliance); } @@ -136,7 +136,7 @@ contract OwnerManager is OwnerRoles { function callComplianceFunction(bytes calldata callData, IIdentity _onchainID) external { require( isComplianceManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleLib.SenderIsNotComplianceManager() + RoleErrors.SenderIsNotComplianceManager() ); address target = address(token.compliance()); @@ -181,7 +181,7 @@ contract OwnerManager is OwnerRoles { function callSetTokenName(string calldata _name, IIdentity _onchainID) external { require( isTokenInfoManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleLib.SenderIsNotTokenInformationManager() + RoleErrors.SenderIsNotTokenInformationManager() ); token.setName(_name); } @@ -197,7 +197,7 @@ contract OwnerManager is OwnerRoles { function callSetTokenSymbol(string calldata _symbol, IIdentity _onchainID) external { require( isTokenInfoManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleLib.SenderIsNotTokenInformationManager() + RoleErrors.SenderIsNotTokenInformationManager() ); token.setSymbol(_symbol); } @@ -213,7 +213,7 @@ contract OwnerManager is OwnerRoles { function callSetTokenOnchainID(address _tokenOnchainID, IIdentity _onchainID) external { require( isTokenInfoManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleLib.SenderIsNotTokenInformationManager() + RoleErrors.SenderIsNotTokenInformationManager() ); token.setOnchainID(_tokenOnchainID); } @@ -229,7 +229,7 @@ contract OwnerManager is OwnerRoles { function callSetClaimTopicsRegistry(address _claimTopicsRegistry, IIdentity _onchainID) external { require( isRegistryAddressSetter(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleLib.SenderIsNotRegistryAddressSetter() + RoleErrors.SenderIsNotRegistryAddressSetter() ); token.identityRegistry().setClaimTopicsRegistry(_claimTopicsRegistry); } @@ -245,7 +245,7 @@ contract OwnerManager is OwnerRoles { function callSetTrustedIssuersRegistry(address _trustedIssuersRegistry, IIdentity _onchainID) external { require( isRegistryAddressSetter(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleLib.SenderIsNotRegistryAddressSetter() + RoleErrors.SenderIsNotRegistryAddressSetter() ); token.identityRegistry().setTrustedIssuersRegistry(_trustedIssuersRegistry); } @@ -265,7 +265,7 @@ contract OwnerManager is OwnerRoles { ) external { require( isIssuersRegistryManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleLib.SenderIsNotIssuersRegistryManager() + RoleErrors.SenderIsNotIssuersRegistryManager() ); token.identityRegistry().issuersRegistry().addTrustedIssuer(_trustedIssuer, _claimTopics); } @@ -281,7 +281,7 @@ contract OwnerManager is OwnerRoles { function callRemoveTrustedIssuer(IClaimIssuer _trustedIssuer, IIdentity _onchainID) external { require( isIssuersRegistryManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleLib.SenderIsNotIssuersRegistryManager() + RoleErrors.SenderIsNotIssuersRegistryManager() ); token.identityRegistry().issuersRegistry().removeTrustedIssuer(_trustedIssuer); } @@ -301,7 +301,7 @@ contract OwnerManager is OwnerRoles { ) external { require( isIssuersRegistryManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleLib.SenderIsNotIssuersRegistryManager() + RoleErrors.SenderIsNotIssuersRegistryManager() ); token.identityRegistry().issuersRegistry().updateIssuerClaimTopics(_trustedIssuer, _claimTopics); } @@ -317,7 +317,7 @@ contract OwnerManager is OwnerRoles { function callAddClaimTopic(uint256 _claimTopic, IIdentity _onchainID) external { require( isClaimRegistryManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleLib.SenderIsNotClaimRegistryManager() + RoleErrors.SenderIsNotClaimRegistryManager() ); token.identityRegistry().topicsRegistry().addClaimTopic(_claimTopic); } @@ -333,7 +333,7 @@ contract OwnerManager is OwnerRoles { function callRemoveClaimTopic(uint256 _claimTopic, IIdentity _onchainID) external { require( isClaimRegistryManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleLib.SenderIsNotClaimRegistryManager() + RoleErrors.SenderIsNotClaimRegistryManager() ); token.identityRegistry().topicsRegistry().removeClaimTopic(_claimTopic); } diff --git a/contracts/roles/permissioning/owner/OwnerRoles.sol b/contracts/roles/permissioning/owner/OwnerRoles.sol index 9560f8a9..64cabbcc 100644 --- a/contracts/roles/permissioning/owner/OwnerRoles.sol +++ b/contracts/roles/permissioning/owner/OwnerRoles.sol @@ -66,7 +66,7 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts/access/Ownable.sol"; import "../../Roles.sol"; -import "../../../libraries/errors/RoleLib.sol"; +import "../../../libraries/errors/RoleErrors.sol"; contract OwnerRoles is Ownable { using Roles for Roles.Role; @@ -89,7 +89,7 @@ contract OwnerRoles is Ownable { /// modifiers modifier onlyAdmin() { - require(owner() == msg.sender || isOwnerAdmin(_msgSender()), RoleLib.SenderIsNotAdmin()); + require(owner() == msg.sender || isOwnerAdmin(_msgSender()), RoleErrors.SenderIsNotAdmin()); _; } diff --git a/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol b/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol index e3782be1..e4e1e65d 100644 --- a/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol +++ b/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol @@ -66,7 +66,7 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../../Roles.sol"; -import "../../../libraries/errors/RoleLib.sol"; +import "../../../libraries/errors/RoleErrors.sol"; contract OwnerRolesUpgradeable is OwnableUpgradeable @@ -91,7 +91,7 @@ contract OwnerRolesUpgradeable is OwnableUpgradeable /// modifiers modifier onlyAdmin() { - require(owner() == msg.sender || isOwnerAdmin(_msgSender()), RoleLib.SenderIsNotAdmin()); + require(owner() == msg.sender || isOwnerAdmin(_msgSender()), RoleErrors.SenderIsNotAdmin()); _; } diff --git a/contracts/token/Token.sol b/contracts/token/Token.sol index 7bcbc9e2..cfd27c0d 100755 --- a/contracts/token/Token.sol +++ b/contracts/token/Token.sol @@ -67,8 +67,8 @@ import "./IToken.sol"; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; import "./TokenStorage.sol"; import "../roles/AgentRoleUpgradeable.sol"; -import "../libraries/errors/InvalidArgumentLib.sol"; -import "../libraries/errors/CommonLib.sol"; +import "../libraries/errors/InvalidArgumentErrors.sol"; +import "../libraries/errors/CommonErrors.sol"; contract Token is IToken, AgentRoleUpgradeable, TokenStorage { @@ -80,25 +80,31 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { error AlreadyInitialized(); + error AmountAboveFrozenTokens(uint256 amount, uint256 maxAmount); + error FrozenWallet(); + error ComplianceNotFollowed(); + error NoTokenToRecover(); error RecoveryNotPossible(); error TransferNotPossible(); + error UnverifiedIdentity(); + /// modifiers /// @dev Modifier to make a function callable only when the contract is not paused. modifier whenNotPaused() { - require(!_tokenPaused, CommonLib.EnforcedPause()); + require(!_tokenPaused, CommonErrors.EnforcedPause()); _; } /// @dev Modifier to make a function callable only when the contract is paused. modifier whenPaused() { - require(_tokenPaused, CommonLib.ExpectedPause()); + require(_tokenPaused, CommonErrors.ExpectedPause()); _; } @@ -132,12 +138,12 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { require( _identityRegistry != address(0) && _compliance != address(0) - , InvalidArgumentLib.ZeroAddress()); + , InvalidArgumentErrors.ZeroAddress()); require( keccak256(abi.encode(_name)) != keccak256(abi.encode("")) && keccak256(abi.encode(_symbol)) != keccak256(abi.encode("")) - , InvalidArgumentLib.EmptyString()); - require(0 <= _decimals && _decimals <= 18, InvalidArgumentLib.DecimalsBetween0And18()); + , InvalidArgumentErrors.EmptyString()); + require(0 <= _decimals && _decimals <= 18, InvalidArgumentErrors.DecimalsBetween0And18()); __Ownable_init(); _tokenName = _name; _tokenSymbol = _symbol; @@ -177,7 +183,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-setName}. */ function setName(string calldata _name) external override onlyOwner { - require(keccak256(abi.encode(_name)) != keccak256(abi.encode("")), InvalidArgumentLib.EmptyString()); + require(keccak256(abi.encode(_name)) != keccak256(abi.encode("")), InvalidArgumentErrors.EmptyString()); _tokenName = _name; emit UpdatedTokenInformation(_tokenName, _tokenSymbol, _tokenDecimals, _TOKEN_VERSION, _tokenOnchainID); } @@ -186,7 +192,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-setSymbol}. */ function setSymbol(string calldata _symbol) external override onlyOwner { - require(keccak256(abi.encode(_symbol)) != keccak256(abi.encode("")), InvalidArgumentLib.EmptyString()); + require(keccak256(abi.encode(_symbol)) != keccak256(abi.encode("")), InvalidArgumentErrors.EmptyString()); _tokenSymbol = _symbol; emit UpdatedTokenInformation(_tokenName, _tokenSymbol, _tokenDecimals, _TOKEN_VERSION, _tokenOnchainID); } @@ -268,7 +274,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { require(!_frozen[_to] && !_frozen[_from], FrozenWallet()); uint256 balance = balanceOf(_from) - (_frozenTokens[_from]); - require(_amount <= balance, CommonLib.ERC20InsufficientBalance(_from, balance, _amount)); + require(_amount <= balance, CommonErrors.ERC20InsufficientBalance(_from, balance, _amount)); if (_tokenIdentityRegistry.isVerified(_to) && _tokenCompliance.canTransfer(_from, _to, _amount)) { _approve(_from, msg.sender, _allowances[_from][msg.sender] - (_amount)); _transfer(_from, _to, _amount); @@ -464,13 +470,15 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { */ function transfer(address _to, uint256 _amount) public override whenNotPaused returns (bool) { require(!_frozen[_to] && !_frozen[msg.sender], FrozenWallet()); - require(_amount <= balanceOf(msg.sender) - (_frozenTokens[msg.sender]), "Insufficient Balance"); + uint256 balance = balanceOf(msg.sender) - _frozenTokens[msg.sender]; + require(_amount <= balance, CommonErrors.ERC20InsufficientBalance(msg.sender, balance, _amount)); if (_tokenIdentityRegistry.isVerified(_to) && _tokenCompliance.canTransfer(msg.sender, _to, _amount)) { _transfer(msg.sender, _to, _amount); _tokenCompliance.transferred(msg.sender, _to, _amount); return true; } - revert("Transfer not possible"); + + revert TransferNotPossible(); } /** @@ -484,7 +492,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { if(getAgentRestrictions(msg.sender).disableForceTransfer) { revert AgentNotAuthorized(msg.sender, "forceTransfer disabled"); } - require(balanceOf(_from) >= _amount, "sender balance too low"); + require(balanceOf(_from) >= _amount, CommonErrors.ERC20InsufficientBalance(_from, balanceOf(_from), _amount)); uint256 freeBalance = balanceOf(_from) - (_frozenTokens[_from]); if (_amount > freeBalance) { uint256 tokensToUnfreeze = _amount - (freeBalance); @@ -503,11 +511,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-mint}. */ function mint(address _to, uint256 _amount) public override onlyAgent { - if(getAgentRestrictions(msg.sender).disableMint) { - revert AgentNotAuthorized(msg.sender, "mint disabled"); - } - require(_tokenIdentityRegistry.isVerified(_to), "Identity is not verified."); - require(_tokenCompliance.canTransfer(address(0), _to, _amount), "Compliance not followed"); + require(!getAgentRestrictions(msg.sender).disableMint, AgentNotAuthorized(msg.sender, "mint disabled")); + require(_tokenIdentityRegistry.isVerified(_to), UnverifiedIdentity()); + require(_tokenCompliance.canTransfer(address(0), _to, _amount), ComplianceNotFollowed()); _mint(_to, _amount); _tokenCompliance.created(_to, _amount); } @@ -516,10 +522,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-burn}. */ function burn(address _userAddress, uint256 _amount) public override onlyAgent { - if(getAgentRestrictions(msg.sender).disableBurn) { - revert AgentNotAuthorized(msg.sender, "burn disabled"); - } - require(balanceOf(_userAddress) >= _amount, "cannot burn more than balance"); + require(!getAgentRestrictions(msg.sender).disableBurn, AgentNotAuthorized(msg.sender, "burn disabled")); + require(balanceOf(_userAddress) >= _amount, + CommonErrors.ERC20InsufficientBalance(_userAddress, balanceOf(_userAddress), _amount)); uint256 freeBalance = balanceOf(_userAddress) - _frozenTokens[_userAddress]; if (_amount > freeBalance) { uint256 tokensToUnfreeze = _amount - (freeBalance); @@ -534,9 +539,8 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-setAddressFrozen}. */ function setAddressFrozen(address _userAddress, bool _freeze) public override onlyAgent { - if(getAgentRestrictions(msg.sender).disableAddressFreeze) { - revert AgentNotAuthorized(msg.sender, "address freeze disabled"); - } + require(!getAgentRestrictions(msg.sender).disableAddressFreeze, + AgentNotAuthorized(msg.sender, "address freeze disabled")); _frozen[_userAddress] = _freeze; emit AddressFrozen(_userAddress, _freeze, msg.sender); @@ -546,11 +550,11 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-freezePartialTokens}. */ function freezePartialTokens(address _userAddress, uint256 _amount) public override onlyAgent { - if(getAgentRestrictions(msg.sender).disablePartialFreeze) { - revert AgentNotAuthorized(msg.sender, "partial freeze disabled"); - } + require(!getAgentRestrictions(msg.sender).disablePartialFreeze, + AgentNotAuthorized(msg.sender, "partial freeze disabled")); uint256 balance = balanceOf(_userAddress); - require(balance >= _frozenTokens[_userAddress] + _amount, "Amount exceeds available balance"); + require(balance >= _frozenTokens[_userAddress] + _amount, + CommonErrors.ERC20InsufficientBalance(_userAddress, balance, _amount)); _frozenTokens[_userAddress] = _frozenTokens[_userAddress] + (_amount); emit TokensFrozen(_userAddress, _amount); } @@ -559,10 +563,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-unfreezePartialTokens}. */ function unfreezePartialTokens(address _userAddress, uint256 _amount) public override onlyAgent { - if(getAgentRestrictions(msg.sender).disablePartialFreeze) { - revert AgentNotAuthorized(msg.sender, "partial freeze disabled"); - } - require(_frozenTokens[_userAddress] >= _amount, "Amount should be less than or equal to frozen tokens"); + require(!getAgentRestrictions(msg.sender).disablePartialFreeze, + AgentNotAuthorized(msg.sender, "partial freeze disabled")); + require(_frozenTokens[_userAddress] >= _amount, AmountAboveFrozenTokens(_amount, _frozenTokens[_userAddress])); _frozenTokens[_userAddress] = _frozenTokens[_userAddress] - (_amount); emit TokensUnfrozen(_userAddress, _amount); } @@ -609,8 +612,8 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { address _to, uint256 _amount ) internal virtual { - require(_from != address(0), CommonLib.ERC20InvalidSpender(_from)); - require(_to != address(0), CommonLib.ERC20InvalidReceiver(_to)); + require(_from != address(0), CommonErrors.ERC20InvalidSpender(_from)); + require(_to != address(0), CommonErrors.ERC20InvalidReceiver(_to)); _beforeTokenTransfer(_from, _to, _amount); @@ -623,7 +626,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {ERC20-_mint}. */ function _mint(address _userAddress, uint256 _amount) internal virtual { - require(_userAddress != address(0), CommonLib.ERC20InvalidReceiver(_userAddress)); + require(_userAddress != address(0), CommonErrors.ERC20InvalidReceiver(_userAddress)); _beforeTokenTransfer(address(0), _userAddress, _amount); @@ -636,7 +639,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {ERC20-_burn}. */ function _burn(address _userAddress, uint256 _amount) internal virtual { - require(_userAddress != address(0), CommonLib.ERC20InvalidSpender(_userAddress)); + require(_userAddress != address(0), CommonErrors.ERC20InvalidSpender(_userAddress)); _beforeTokenTransfer(_userAddress, address(0), _amount); @@ -653,8 +656,8 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { address _spender, uint256 _amount ) internal virtual { - require(_owner != address(0), "ERC20: approve from the zero address"); - require(_spender != address(0), "ERC20: approve to the zero address"); + require(_owner != address(0), CommonErrors.ERC20InvalidSender(_owner)); + require(_spender != address(0), CommonErrors.ERC20InvalidSpender(_spender)); _allowances[_owner][_spender] = _amount; emit Approval(_owner, _spender, _amount); diff --git a/test/agentManager.test.ts b/test/agentManager.test.ts index 685b9b95..f7a3082e 100644 --- a/test/agentManager.test.ts +++ b/test/agentManager.test.ts @@ -2,7 +2,6 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { expect } from 'chai'; import { ethers } from 'hardhat'; import { deployFullSuiteFixture } from './fixtures/deploy-full-suite.fixture'; -import { agent } from '../typechain-types/contracts/roles/permissioning'; describe('AgentManager', () => { describe('.callForceTransfer', () => { @@ -134,7 +133,10 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callPause(aliceIdentity.target)).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); + await expect(agentManager.connect(aliceWallet).callPause(aliceIdentity.target)).to.be.revertedWithCustomError( + agentManager, + 'SenderIsNotFreezer', + ); }); }); @@ -148,7 +150,10 @@ describe('AgentManager', () => { await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - await expect(agentManager.connect(anotherWallet).callPause(aliceIdentity.target)).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); + await expect(agentManager.connect(anotherWallet).callPause(aliceIdentity.target)).to.be.revertedWithCustomError( + agentManager, + 'SenderIsNotFreezer', + ); }); }); @@ -179,7 +184,10 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callUnpause(aliceIdentity.target)).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); + await expect(agentManager.connect(aliceWallet).callUnpause(aliceIdentity.target)).to.be.revertedWithCustomError( + agentManager, + 'SenderIsNotFreezer', + ); }); }); @@ -193,7 +201,10 @@ describe('AgentManager', () => { await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - await expect(agentManager.connect(anotherWallet).callUnpause(aliceIdentity.target)).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); + await expect(agentManager.connect(anotherWallet).callUnpause(aliceIdentity.target)).to.be.revertedWithCustomError( + agentManager, + 'SenderIsNotFreezer', + ); }); }); @@ -427,10 +438,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callSetAddressFrozen(aliceIdentity.target, true, aliceIdentity.target)).to.be.revertedWithCustomError( - agentManager, - 'SenderIsNotFreezer', - ); + await expect( + agentManager.connect(aliceWallet).callSetAddressFrozen(aliceIdentity.target, true, aliceIdentity.target), + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); }); }); @@ -444,10 +454,9 @@ describe('AgentManager', () => { await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - await expect(agentManager.connect(anotherWallet).callSetAddressFrozen(aliceIdentity.target, true, aliceIdentity.target)).to.be.revertedWithCustomError( - agentManager, - 'SenderIsNotFreezer', - ); + await expect( + agentManager.connect(anotherWallet).callSetAddressFrozen(aliceIdentity.target, true, aliceIdentity.target), + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); }); }); @@ -531,10 +540,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callFreezePartialTokens(aliceIdentity.target, 100, aliceIdentity.target)).to.be.revertedWithCustomError( - agentManager, - 'SenderIsNotFreezer', - ); + await expect( + agentManager.connect(aliceWallet).callFreezePartialTokens(aliceIdentity.target, 100, aliceIdentity.target), + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); }); }); @@ -548,10 +556,9 @@ describe('AgentManager', () => { await agentManager.connect(tokenAdmin).addFreezer(aliceIdentity.target); - await expect(agentManager.connect(anotherWallet).callFreezePartialTokens(aliceIdentity.target, 100, aliceIdentity.target)).to.be.revertedWithCustomError( - agentManager, - 'SenderIsNotFreezer', - ); + await expect( + agentManager.connect(anotherWallet).callFreezePartialTokens(aliceIdentity.target, 100, aliceIdentity.target), + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); }); }); @@ -634,10 +641,9 @@ describe('AgentManager', () => { identities: { aliceIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(agentManager.connect(aliceWallet).callUnfreezePartialTokens(aliceIdentity.target, 100, aliceIdentity.target)).to.be.revertedWithCustomError( - agentManager, - 'SenderIsNotFreezer', - ); + await expect( + agentManager.connect(aliceWallet).callUnfreezePartialTokens(aliceIdentity.target, 100, aliceIdentity.target), + ).to.be.revertedWithCustomError(agentManager, 'SenderIsNotFreezer'); }); }); diff --git a/test/agentRole.test.ts b/test/agentRole.test.ts index 8c3a482e..7d022461 100644 --- a/test/agentRole.test.ts +++ b/test/agentRole.test.ts @@ -53,7 +53,10 @@ describe('AgentRole', () => { } = await loadFixture(deployAgentFixture); await agentRole.connect(ownerWallet).addAgent(aliceWallet.address); - await expect(agentRole.connect(ownerWallet).addAgent(aliceWallet.address)).to.be.revertedWithCustomError(agentRole, 'AccountAlreadyHasRole'); + await expect(agentRole.connect(ownerWallet).addAgent(aliceWallet.address)).to.be.revertedWithCustomError( + agentRole, + 'AccountAlreadyHasRole', + ); }); }); @@ -105,7 +108,10 @@ describe('AgentRole', () => { contracts: { agentRole }, } = await loadFixture(deployAgentFixture); - await expect(agentRole.connect(ownerWallet).removeAgent(aliceWallet.address)).to.be.revertedWithCustomError(agentRole, 'AccountDoesNotHaveRole'); + await expect(agentRole.connect(ownerWallet).removeAgent(aliceWallet.address)).to.be.revertedWithCustomError( + agentRole, + 'AccountDoesNotHaveRole', + ); }); }); diff --git a/test/authorities/trex-implementation-authority.test.ts b/test/authorities/trex-implementation-authority.test.ts index 38aed713..2d388428 100644 --- a/test/authorities/trex-implementation-authority.test.ts +++ b/test/authorities/trex-implementation-authority.test.ts @@ -3,7 +3,6 @@ import { expect } from 'chai'; import { ethers } from 'hardhat'; import { deployFullSuiteFixture } from '../fixtures/deploy-full-suite.fixture'; -import { compliance } from '../../typechain-types/contracts'; describe('TrexImplementationAuthority', () => { describe('.setTREXFactory()', () => { @@ -57,7 +56,10 @@ describe('TrexImplementationAuthority', () => { deployer, ); - await expect(trexImplementationAuthority.setTREXFactory(trexFactory.target)).to.be.revertedWithCustomError(trexImplementationAuthority, 'OnlyReferenceContractCanCall'); + await expect(trexImplementationAuthority.setTREXFactory(trexFactory.target)).to.be.revertedWithCustomError( + trexImplementationAuthority, + 'OnlyReferenceContractCanCall', + ); }); }); @@ -134,7 +136,10 @@ describe('TrexImplementationAuthority', () => { patch: 0, }; - await expect(trexImplementationAuthority.fetchVersion(versionStruct)).to.be.revertedWithCustomError(trexImplementationAuthority, 'CannotCallOnReferenceContract'); + await expect(trexImplementationAuthority.fetchVersion(versionStruct)).to.be.revertedWithCustomError( + trexImplementationAuthority, + 'CannotCallOnReferenceContract', + ); }); }); @@ -162,7 +167,10 @@ describe('TrexImplementationAuthority', () => { await otherTrexImplementationAuthority.fetchVersion(versionStruct); - await expect(otherTrexImplementationAuthority.fetchVersion(versionStruct)).to.be.revertedWithCustomError(otherTrexImplementationAuthority, 'VersionAlreadyFetched'); + await expect(otherTrexImplementationAuthority.fetchVersion(versionStruct)).to.be.revertedWithCustomError( + otherTrexImplementationAuthority, + 'VersionAlreadyFetched', + ); }); }); @@ -284,7 +292,10 @@ describe('TrexImplementationAuthority', () => { mcImplementation: implementations.modularComplianceImplementation.target, }; - await expect(trexImplementationAuthority.addTREXVersion(versionStruct, contractsStruct)).to.be.revertedWith('version already exists'); + await expect(trexImplementationAuthority.addTREXVersion(versionStruct, contractsStruct)).to.be.revertedWithCustomError( + trexImplementationAuthority, + 'VersionAlreadyExists', + ); }); }); @@ -311,7 +322,7 @@ describe('TrexImplementationAuthority', () => { await expect(trexImplementationAuthority.addTREXVersion(versionStruct, contractsStruct)).to.be.revertedWithCustomError( trexImplementationAuthority, - 'ZeroAddress' + 'ZeroAddress', ); }); }); @@ -352,7 +363,10 @@ describe('TrexImplementationAuthority', () => { patch: 0, }; - await expect(trexImplementationAuthority.useTREXVersion(versionStruct)).to.be.revertedWith('version already in use'); + await expect(trexImplementationAuthority.useTREXVersion(versionStruct)).to.be.revertedWithCustomError( + trexImplementationAuthority, + 'VersionAlreadyInUse', + ); }); }); @@ -368,7 +382,10 @@ describe('TrexImplementationAuthority', () => { patch: 1, }; - await expect(trexImplementationAuthority.useTREXVersion(versionStruct)).to.be.revertedWith('invalid argument - non existing version'); + await expect(trexImplementationAuthority.useTREXVersion(versionStruct)).to.be.revertedWithCustomError( + trexImplementationAuthority, + 'NonExistingVersion', + ); }); }); }); @@ -382,10 +399,9 @@ describe('TrexImplementationAuthority', () => { authorities: { trexImplementationAuthority }, } = await loadFixture(deployFullSuiteFixture); - await expect(trexImplementationAuthority.changeImplementationAuthority(ethers.ZeroAddress, anotherWallet.address)).to.be.revertedWithCustomError( - trexImplementationAuthority, - 'ZeroAddress' - ); + await expect( + trexImplementationAuthority.changeImplementationAuthority(ethers.ZeroAddress, anotherWallet.address), + ).to.be.revertedWithCustomError(trexImplementationAuthority, 'ZeroAddress'); }); }); @@ -407,10 +423,9 @@ describe('TrexImplementationAuthority', () => { deployer, ); - await expect(otherTrexImplementationAuthority.changeImplementationAuthority(token.target, ethers.ZeroAddress)).to.be.revertedWithCustomError( - otherTrexImplementationAuthority, - 'OnlyReferenceContractCanDeployNewIA', - ); + await expect( + otherTrexImplementationAuthority.changeImplementationAuthority(token.target, ethers.ZeroAddress), + ).to.be.revertedWithCustomError(otherTrexImplementationAuthority, 'OnlyReferenceContractCanDeployNewIA'); }); }); diff --git a/test/compliance.test.ts b/test/compliance.test.ts index f4268b59..f8f547d7 100644 --- a/test/compliance.test.ts +++ b/test/compliance.test.ts @@ -43,7 +43,10 @@ describe('ModularCompliance', () => { await compliance.bindToken(token.target); - await expect(compliance.connect(anotherWallet).bindToken(token.target)).to.be.revertedWithCustomError(compliance, 'OnlyOwnerOrTokenCanCall'); + await expect(compliance.connect(anotherWallet).bindToken(token.target)).to.be.revertedWithCustomError( + compliance, + 'OnlyOwnerOrTokenCanCall', + ); }); }); @@ -90,7 +93,10 @@ describe('ModularCompliance', () => { suite: { token, compliance }, } = await loadFixture(deploySuiteWithModularCompliancesFixture); - await expect(compliance.connect(anotherWallet).unbindToken(token.target)).to.be.revertedWithCustomError(compliance, 'OnlyOwnerOrTokenCanCall'); + await expect(compliance.connect(anotherWallet).unbindToken(token.target)).to.be.revertedWithCustomError( + compliance, + 'OnlyOwnerOrTokenCanCall', + ); }); }); @@ -322,7 +328,7 @@ describe('ModularCompliance', () => { await expect(compliance.connect(charlieWallet).transferred(ethers.ZeroAddress, bobWallet.address, 10)).to.be.revertedWithCustomError( compliance, - 'ZeroAddress' + 'ZeroAddress', ); }); }); @@ -336,7 +342,7 @@ describe('ModularCompliance', () => { await expect(compliance.connect(charlieWallet).transferred(aliceWallet.address, ethers.ZeroAddress, 10)).to.be.revertedWithCustomError( compliance, - 'ZeroAddress' + 'ZeroAddress', ); }); }); diff --git a/test/compliances/module-conditional-transfer.test.ts b/test/compliances/module-conditional-transfer.test.ts index da2d5970..cd42c424 100644 --- a/test/compliances/module-conditional-transfer.test.ts +++ b/test/compliances/module-conditional-transfer.test.ts @@ -321,7 +321,10 @@ describe('ConditionalTransferModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithConditionalTransferModule); - await expect(conditionalTransferModule.moduleBurnAction(anotherWallet.address, 10)).to.be.revertedWithCustomError(conditionalTransferModule, 'OnlyBoundComplianceCanCall'); + await expect(conditionalTransferModule.moduleBurnAction(anotherWallet.address, 10)).to.be.revertedWithCustomError( + conditionalTransferModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -355,7 +358,10 @@ describe('ConditionalTransferModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithConditionalTransferModule); - await expect(conditionalTransferModule.moduleMintAction(anotherWallet.address, 10)).to.be.revertedWithCustomError(conditionalTransferModule, 'OnlyBoundComplianceCanCall'); + await expect(conditionalTransferModule.moduleMintAction(anotherWallet.address, 10)).to.be.revertedWithCustomError( + conditionalTransferModule, + 'OnlyBoundComplianceCanCall', + ); }); }); diff --git a/test/compliances/module-country-allow.test.ts b/test/compliances/module-country-allow.test.ts index baf461d0..920a2f5b 100644 --- a/test/compliances/module-country-allow.test.ts +++ b/test/compliances/module-country-allow.test.ts @@ -139,7 +139,10 @@ describe('CountryAllowModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(anotherWallet).batchAllowCountries([42, 66])).to.be.revertedWithCustomError(countryAllowModule, 'OnlyBoundComplianceCanCall'); + await expect(countryAllowModule.connect(anotherWallet).batchAllowCountries([42, 66])).to.be.revertedWithCustomError( + countryAllowModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -150,7 +153,10 @@ describe('CountryAllowModule', () => { accounts: { deployer }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(deployer).batchAllowCountries([42, 66])).to.be.revertedWithCustomError(countryAllowModule, 'OnlyBoundComplianceCanCall'); + await expect(countryAllowModule.connect(deployer).batchAllowCountries([42, 66])).to.be.revertedWithCustomError( + countryAllowModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -185,7 +191,10 @@ describe('CountryAllowModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(anotherWallet).batchDisallowCountries([42, 66])).to.be.revertedWithCustomError(countryAllowModule, 'OnlyBoundComplianceCanCall'); + await expect(countryAllowModule.connect(anotherWallet).batchDisallowCountries([42, 66])).to.be.revertedWithCustomError( + countryAllowModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -196,7 +205,10 @@ describe('CountryAllowModule', () => { accounts: { deployer }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(deployer).batchDisallowCountries([42, 66])).to.be.revertedWithCustomError(countryAllowModule, 'OnlyBoundComplianceCanCall'); + await expect(countryAllowModule.connect(deployer).batchDisallowCountries([42, 66])).to.be.revertedWithCustomError( + countryAllowModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -233,7 +245,10 @@ describe('CountryAllowModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(anotherWallet).addAllowedCountry(42)).to.be.revertedWithCustomError(countryAllowModule, 'OnlyBoundComplianceCanCall'); + await expect(countryAllowModule.connect(anotherWallet).addAllowedCountry(42)).to.be.revertedWithCustomError( + countryAllowModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -244,7 +259,10 @@ describe('CountryAllowModule', () => { accounts: { deployer }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(deployer).addAllowedCountry(42)).to.be.revertedWithCustomError(countryAllowModule, 'OnlyBoundComplianceCanCall'); + await expect(countryAllowModule.connect(deployer).addAllowedCountry(42)).to.be.revertedWithCustomError( + countryAllowModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -306,7 +324,10 @@ describe('CountryAllowModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(anotherWallet).removeAllowedCountry(42)).to.be.revertedWithCustomError(countryAllowModule, 'OnlyBoundComplianceCanCall'); + await expect(countryAllowModule.connect(anotherWallet).removeAllowedCountry(42)).to.be.revertedWithCustomError( + countryAllowModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -317,7 +338,10 @@ describe('CountryAllowModule', () => { accounts: { deployer }, } = await loadFixture(deployComplianceWithCountryAllowModule); - await expect(countryAllowModule.connect(deployer).removeAllowedCountry(42)).to.be.revertedWithCustomError(countryAllowModule, 'OnlyBoundComplianceCanCall'); + await expect(countryAllowModule.connect(deployer).removeAllowedCountry(42)).to.be.revertedWithCustomError( + countryAllowModule, + 'OnlyBoundComplianceCanCall', + ); }); }); diff --git a/test/compliances/module-country-restrict.test.ts b/test/compliances/module-country-restrict.test.ts index 00277ea7..8b02d1f4 100644 --- a/test/compliances/module-country-restrict.test.ts +++ b/test/compliances/module-country-restrict.test.ts @@ -120,7 +120,10 @@ describe('CountryRestrictModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect(countryRestrictModule.connect(anotherWallet).addCountryRestriction(42)).to.be.revertedWithCustomError(countryRestrictModule, 'OnlyBoundComplianceCanCall'); + await expect(countryRestrictModule.connect(anotherWallet).addCountryRestriction(42)).to.be.revertedWithCustomError( + countryRestrictModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -131,7 +134,10 @@ describe('CountryRestrictModule', () => { accounts: { deployer }, } = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect(countryRestrictModule.connect(deployer).addCountryRestriction(42)).to.be.revertedWithCustomError(countryRestrictModule, 'OnlyBoundComplianceCanCall'); + await expect(countryRestrictModule.connect(deployer).addCountryRestriction(42)).to.be.revertedWithCustomError( + countryRestrictModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -191,7 +197,10 @@ describe('CountryRestrictModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect(countryRestrictModule.connect(anotherWallet).removeCountryRestriction(42)).to.be.revertedWithCustomError(countryRestrictModule, 'OnlyBoundComplianceCanCall'); + await expect(countryRestrictModule.connect(anotherWallet).removeCountryRestriction(42)).to.be.revertedWithCustomError( + countryRestrictModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -202,7 +211,10 @@ describe('CountryRestrictModule', () => { accounts: { deployer }, } = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect(countryRestrictModule.connect(deployer).removeCountryRestriction(42)).to.be.revertedWithCustomError(countryRestrictModule, 'OnlyBoundComplianceCanCall'); + await expect(countryRestrictModule.connect(deployer).removeCountryRestriction(42)).to.be.revertedWithCustomError( + countryRestrictModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -262,7 +274,10 @@ describe('CountryRestrictModule', () => { accounts: { anotherWallet }, } = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect(countryRestrictModule.connect(anotherWallet).batchRestrictCountries([42])).to.be.revertedWithCustomError(countryRestrictModule, 'OnlyBoundComplianceCanCall'); + await expect(countryRestrictModule.connect(anotherWallet).batchRestrictCountries([42])).to.be.revertedWithCustomError( + countryRestrictModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -273,7 +288,10 @@ describe('CountryRestrictModule', () => { accounts: { deployer }, } = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect(countryRestrictModule.connect(deployer).batchRestrictCountries([42])).to.be.revertedWithCustomError(countryRestrictModule, 'OnlyBoundComplianceCanCall'); + await expect(countryRestrictModule.connect(deployer).batchRestrictCountries([42])).to.be.revertedWithCustomError( + countryRestrictModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -371,7 +389,10 @@ describe('CountryRestrictModule', () => { accounts: { deployer }, } = await loadFixture(deployComplianceWithCountryRestrictModule); - await expect(countryRestrictModule.connect(deployer).batchUnrestrictCountries([42])).to.be.revertedWithCustomError(countryRestrictModule, 'OnlyBoundComplianceCanCall'); + await expect(countryRestrictModule.connect(deployer).batchUnrestrictCountries([42])).to.be.revertedWithCustomError( + countryRestrictModule, + 'OnlyBoundComplianceCanCall', + ); }); }); diff --git a/test/compliances/module-exchange-monthly-limits.test.ts b/test/compliances/module-exchange-monthly-limits.test.ts index 9581ab0b..af8500b0 100644 --- a/test/compliances/module-exchange-monthly-limits.test.ts +++ b/test/compliances/module-exchange-monthly-limits.test.ts @@ -150,7 +150,8 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { await expect(context.contracts.complianceModule.setExchangeMonthlyLimit(exchangeID, 1)).to.revertedWithCustomError( context.contracts.complianceModule, - 'OnlyBoundComplianceCanCall'); + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -302,7 +303,7 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { await expect(context.contracts.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWithCustomError( context.contracts.complianceModule, - 'OnlyBoundComplianceCanCall' + 'OnlyBoundComplianceCanCall', ); }); }); diff --git a/test/compliances/module-max-balance.test.ts b/test/compliances/module-max-balance.test.ts index 7b2d6238..52bc1969 100644 --- a/test/compliances/module-max-balance.test.ts +++ b/test/compliances/module-max-balance.test.ts @@ -87,7 +87,10 @@ describe('Compliance Module: MaxBalance', () => { it('should revert', async () => { const context = await loadFixture(deployMaxBalanceFullSuite); - await expect(context.suite.complianceModule.setMaxBalance(100)).to.revertedWithCustomError(context.suite.complianceModule, 'OnlyBoundComplianceCanCall'); + await expect(context.suite.complianceModule.setMaxBalance(100)).to.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -319,7 +322,10 @@ describe('Compliance Module: MaxBalance', () => { const from = context.accounts.aliceWallet.address; const to = context.accounts.bobWallet.address; - await expect(context.suite.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWithCustomError(context.suite.complianceModule, 'OnlyBoundComplianceCanCall'); + await expect(context.suite.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -407,7 +413,10 @@ describe('Compliance Module: MaxBalance', () => { const context = await loadFixture(deployMaxBalanceFullSuite); const to = context.accounts.bobWallet.address; - await expect(context.suite.complianceModule.moduleMintAction(to, 10)).to.revertedWithCustomError(context.suite.complianceModule, 'OnlyBoundComplianceCanCall'); + await expect(context.suite.complianceModule.moduleMintAction(to, 10)).to.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -460,7 +469,10 @@ describe('Compliance Module: MaxBalance', () => { const context = await loadFixture(deployMaxBalanceFullSuite); const from = context.accounts.bobWallet.address; - await expect(context.suite.complianceModule.moduleBurnAction(from, 10)).to.revertedWithCustomError(context.suite.complianceModule, 'OnlyBoundComplianceCanCall'); + await expect(context.suite.complianceModule.moduleBurnAction(from, 10)).to.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -503,7 +515,10 @@ describe('Compliance Module: MaxBalance', () => { context.suite.complianceModule.target, ); - await expect(context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.target)).to.revertedWithCustomError(context.suite.complianceModule, 'IdentityNotFound'); + await expect(context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.target)).to.revertedWithCustomError( + context.suite.complianceModule, + 'IdentityNotFound', + ); }); }); diff --git a/test/compliances/module-supply-limit.test.ts b/test/compliances/module-supply-limit.test.ts index 02a34bd4..b514f09c 100644 --- a/test/compliances/module-supply-limit.test.ts +++ b/test/compliances/module-supply-limit.test.ts @@ -146,7 +146,10 @@ describe('Compliance Module: SupplyLimit', () => { it('should revert', async () => { const context = await loadFixture(deploySupplyLimitFixture); - await expect(context.suite.complianceModule.setSupplyLimit(100)).to.revertedWithCustomError(context.suite.complianceModule, 'OnlyBoundComplianceCanCall'); + await expect(context.suite.complianceModule.setSupplyLimit(100)).to.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', + ); }); }); diff --git a/test/compliances/module-time-exchange-limits.test.ts b/test/compliances/module-time-exchange-limits.test.ts index 474a8951..6a7a43f8 100644 --- a/test/compliances/module-time-exchange-limits.test.ts +++ b/test/compliances/module-time-exchange-limits.test.ts @@ -401,7 +401,10 @@ describe('Compliance Module: TimeExchangeLimits', () => { const from = context.accounts.aliceWallet.address; const to = context.accounts.bobWallet.address; - await expect(context.contracts.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWithCustomError(context.contracts.complianceModule, 'OnlyBoundComplianceCanCall'); + await expect(context.contracts.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWithCustomError( + context.contracts.complianceModule, + 'OnlyBoundComplianceCanCall', + ); }); }); diff --git a/test/compliances/module-time-transfer-limits.test.ts b/test/compliances/module-time-transfer-limits.test.ts index 94f0a97c..52c08cca 100644 --- a/test/compliances/module-time-transfer-limits.test.ts +++ b/test/compliances/module-time-transfer-limits.test.ts @@ -279,7 +279,10 @@ describe('Compliance Module: TimeTransferLimits', () => { const from = context.accounts.aliceWallet.address; const to = context.accounts.bobWallet.address; - await expect(context.contracts.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWithCustomError(context.contracts.complianceModule, 'OnlyBoundComplianceCanCall'); + await expect(context.contracts.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWithCustomError( + context.contracts.complianceModule, + 'OnlyBoundComplianceCanCall', + ); }); }); diff --git a/test/compliances/module-transfer-fees.test.ts b/test/compliances/module-transfer-fees.test.ts index aa44612e..28a7fed3 100644 --- a/test/compliances/module-transfer-fees.test.ts +++ b/test/compliances/module-transfer-fees.test.ts @@ -220,7 +220,10 @@ describe('Compliance Module: TransferFees', () => { const from = context.accounts.aliceWallet.address; const to = context.accounts.bobWallet.address; - await expect(context.suite.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWithCustomError(context.suite.complianceModule, 'OnlyBoundComplianceCanCall'); + await expect(context.suite.complianceModule.moduleTransferAction(from, to, 10)).to.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', + ); }); }); diff --git a/test/dva.test.ts b/test/dva.test.ts index 0cd12453..3821faf3 100644 --- a/test/dva.test.ts +++ b/test/dva.test.ts @@ -250,7 +250,7 @@ describe('DVATransferManager', () => { context.suite.transferManager .connect(context.accounts.aliceWallet) .initiateTransfer(context.suite.token.target, context.accounts.bobWallet.address, 100000), - ).to.be.revertedWith('Amount exceeds available balance'); + ).to.be.revertedWithCustomError(context.suite.token, 'ERC20InsufficientBalance'); }); }); diff --git a/test/dvd.test.ts b/test/dvd.test.ts index 9df53571..2169d9e5 100644 --- a/test/dvd.test.ts +++ b/test/dvd.test.ts @@ -333,7 +333,10 @@ describe('DVDTransferManager', () => { accounts: { charlieWallet }, } = await loadFixture(deployFullSuiteWithTransferManager); - await expect(transferManager.connect(charlieWallet).cancelDVDTransfer(ethers.ZeroHash)).to.be.revertedWithCustomError(transferManager, 'TransferIDDoesNotExist'); + await expect(transferManager.connect(charlieWallet).cancelDVDTransfer(ethers.ZeroHash)).to.be.revertedWithCustomError( + transferManager, + 'TransferIDDoesNotExist', + ); }); }); @@ -362,7 +365,10 @@ describe('DVDTransferManager', () => { const tx = await transferManager.connect(aliceWallet).cancelDVDTransfer(transferId); await expect(tx).to.emit(transferManager, 'DVDTransferCancelled').withArgs(transferId); - await expect(transferManager.connect(aliceWallet).cancelDVDTransfer(transferId)).to.be.revertedWithCustomError(transferManager, 'TransferIDDoesNotExist'); + await expect(transferManager.connect(aliceWallet).cancelDVDTransfer(transferId)).to.be.revertedWithCustomError( + transferManager, + 'TransferIDDoesNotExist', + ); }); }); @@ -376,7 +382,10 @@ describe('DVDTransferManager', () => { const tx = await transferManager.connect(bobWallet).cancelDVDTransfer(transferId); await expect(tx).to.emit(transferManager, 'DVDTransferCancelled').withArgs(transferId); - await expect(transferManager.connect(bobWallet).cancelDVDTransfer(transferId)).to.be.revertedWithCustomError(transferManager, 'TransferIDDoesNotExist'); + await expect(transferManager.connect(bobWallet).cancelDVDTransfer(transferId)).to.be.revertedWithCustomError( + transferManager, + 'TransferIDDoesNotExist', + ); }); }); @@ -390,7 +399,10 @@ describe('DVDTransferManager', () => { const tx = await transferManager.connect(deployer).cancelDVDTransfer(transferId); await expect(tx).to.emit(transferManager, 'DVDTransferCancelled').withArgs(transferId); - await expect(transferManager.connect(deployer).cancelDVDTransfer(transferId)).to.be.revertedWithCustomError(transferManager, 'TransferIDDoesNotExist'); + await expect(transferManager.connect(deployer).cancelDVDTransfer(transferId)).to.be.revertedWithCustomError( + transferManager, + 'TransferIDDoesNotExist', + ); }); }); @@ -404,7 +416,10 @@ describe('DVDTransferManager', () => { const tx = await transferManager.connect(deployer).cancelDVDTransfer(transferId); await expect(tx).to.emit(transferManager, 'DVDTransferCancelled').withArgs(transferId); - await expect(transferManager.connect(deployer).cancelDVDTransfer(transferId)).to.be.revertedWithCustomError(transferManager, 'TransferIDDoesNotExist'); + await expect(transferManager.connect(deployer).cancelDVDTransfer(transferId)).to.be.revertedWithCustomError( + transferManager, + 'TransferIDDoesNotExist', + ); }); }); }); @@ -417,7 +432,10 @@ describe('DVDTransferManager', () => { accounts: { charlieWallet }, } = await loadFixture(deployFullSuiteWithTransferManager); - await expect(transferManager.connect(charlieWallet).takeDVDTransfer(ethers.ZeroHash)).to.be.revertedWithCustomError(transferManager, 'TransferIDDoesNotExist'); + await expect(transferManager.connect(charlieWallet).takeDVDTransfer(ethers.ZeroHash)).to.be.revertedWithCustomError( + transferManager, + 'TransferIDDoesNotExist', + ); }); }); @@ -453,7 +471,10 @@ describe('DVDTransferManager', () => { await expect(tx).to.emit(erc20A, 'Transfer').withArgs(aliceWallet.address, charlieWallet.address, 10); await expect(tx).to.emit(erc20B, 'Transfer').withArgs(bobWallet.address, aliceWallet.address, 490); await expect(tx).to.emit(erc20B, 'Transfer').withArgs(bobWallet.address, davidWallet.address, 10); - await expect(transferManager.connect(bobWallet).takeDVDTransfer(transferId)).to.be.revertedWithCustomError(transferManager, 'TransferIDDoesNotExist'); + await expect(transferManager.connect(bobWallet).takeDVDTransfer(transferId)).to.be.revertedWithCustomError( + transferManager, + 'TransferIDDoesNotExist', + ); }); }); @@ -469,7 +490,10 @@ describe('DVDTransferManager', () => { await expect(tx).to.emit(transferManager, 'DVDTransferExecuted').withArgs(transferId); await expect(tx).to.emit(erc20A, 'Transfer').withArgs(aliceWallet.address, bobWallet.address, 1000); await expect(tx).to.emit(erc20B, 'Transfer').withArgs(bobWallet.address, aliceWallet.address, 500); - await expect(transferManager.connect(bobWallet).takeDVDTransfer(transferId)).to.be.revertedWithCustomError(transferManager, 'TransferIDDoesNotExist'); + await expect(transferManager.connect(bobWallet).takeDVDTransfer(transferId)).to.be.revertedWithCustomError( + transferManager, + 'TransferIDDoesNotExist', + ); }); }); }); diff --git a/test/factory.test.ts b/test/factory.test.ts index 4f1aa31e..a465c1cb 100644 --- a/test/factory.test.ts +++ b/test/factory.test.ts @@ -100,7 +100,7 @@ describe('TREXFactory', () => { issuerClaims: [], }, ), - ).to.be.revertedWith('token already deployed'); + ).to.be.revertedWithCustomError(trexFactory, 'TokenAlreadyDeployed'); }); }); @@ -132,7 +132,7 @@ describe('TREXFactory', () => { issuerClaims: [], }, ), - ).to.be.revertedWith('claim pattern not valid'); + ).to.be.revertedWithCustomError(trexFactory, 'InvalidClaimPattern'); }); }); @@ -164,7 +164,7 @@ describe('TREXFactory', () => { issuerClaims: Array.from({ length: 6 }, () => []), }, ), - ).to.be.revertedWith('max 5 claim issuers at deployment'); + ).to.be.revertedWithCustomError(trexFactory, 'MaxClaimIssuersReached'); }); }); @@ -196,7 +196,7 @@ describe('TREXFactory', () => { issuerClaims: [], }, ), - ).to.be.revertedWith('max 5 claim topics at deployment'); + ).to.be.revertedWithCustomError(trexFactory, 'MaxClaimTopicsReached'); }); }); @@ -228,7 +228,7 @@ describe('TREXFactory', () => { issuerClaims: [], }, ), - ).to.be.revertedWith('max 5 agents at deployment'); + ).to.be.revertedWithCustomError(trexFactory, 'MaxAgentsReached'); }); }); @@ -260,7 +260,7 @@ describe('TREXFactory', () => { issuerClaims: [], }, ), - ).to.be.revertedWith('max 30 module actions at deployment'); + ).to.be.revertedWithCustomError(trexFactory, 'MaxModuleActionsReached'); }); }); @@ -292,7 +292,7 @@ describe('TREXFactory', () => { issuerClaims: [], }, ), - ).to.be.revertedWith('invalid compliance pattern'); + ).to.be.revertedWithCustomError(trexFactory, 'InvalidCompliancePattern'); }); }); diff --git a/test/registries/claim-topics-registry.test.ts b/test/registries/claim-topics-registry.test.ts index 47995ac7..9e411a60 100644 --- a/test/registries/claim-topics-registry.test.ts +++ b/test/registries/claim-topics-registry.test.ts @@ -37,7 +37,10 @@ describe('ClaimTopicsRegistry', () => { await Promise.all(Array.from({ length: 14 }, (_, i) => i).map((i) => claimTopicsRegistry.addClaimTopic(i))); - await expect(claimTopicsRegistry.connect(deployer).addClaimTopic(14)).to.be.revertedWithCustomError(claimTopicsRegistry, 'CannotRequireMoreThan15Topics'); + await expect(claimTopicsRegistry.connect(deployer).addClaimTopic(14)).to.be.revertedWithCustomError( + claimTopicsRegistry, + 'CannotRequireMoreThan15Topics', + ); }); }); @@ -50,7 +53,10 @@ describe('ClaimTopicsRegistry', () => { await claimTopicsRegistry.addClaimTopic(1); - await expect(claimTopicsRegistry.connect(deployer).addClaimTopic(1)).to.be.revertedWithCustomError(claimTopicsRegistry, 'ClaimTopicAlreadyExists'); + await expect(claimTopicsRegistry.connect(deployer).addClaimTopic(1)).to.be.revertedWithCustomError( + claimTopicsRegistry, + 'ClaimTopicAlreadyExists', + ); }); }); }); diff --git a/test/registries/identity-registry-storage.test.ts b/test/registries/identity-registry-storage.test.ts index bc310468..76b9ea03 100644 --- a/test/registries/identity-registry-storage.test.ts +++ b/test/registries/identity-registry-storage.test.ts @@ -154,10 +154,9 @@ describe('IdentityRegistryStorage', () => { accounts: { anotherWallet, charlieWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistryStorage.connect(anotherWallet).modifyStoredInvestorCountry(charlieWallet.address, 42)).to.be.revertedWithCustomError( - identityRegistryStorage, - 'CallerDoesNotHaveAgentRole', - ); + await expect( + identityRegistryStorage.connect(anotherWallet).modifyStoredInvestorCountry(charlieWallet.address, 42), + ).to.be.revertedWithCustomError(identityRegistryStorage, 'CallerDoesNotHaveAgentRole'); }); }); @@ -187,10 +186,9 @@ describe('IdentityRegistryStorage', () => { await identityRegistryStorage.addAgent(tokenAgent.address); - await expect(identityRegistryStorage.connect(tokenAgent).modifyStoredInvestorCountry(charlieWallet.address, 42)).to.be.revertedWithCustomError( - identityRegistryStorage, - 'AddressNotYetStored', - ); + await expect( + identityRegistryStorage.connect(tokenAgent).modifyStoredInvestorCountry(charlieWallet.address, 42), + ).to.be.revertedWithCustomError(identityRegistryStorage, 'AddressNotYetStored'); }); }); }); diff --git a/test/registries/identity-registry.test.ts b/test/registries/identity-registry.test.ts index a1974bd1..addc90d5 100644 --- a/test/registries/identity-registry.test.ts +++ b/test/registries/identity-registry.test.ts @@ -44,10 +44,9 @@ describe('IdentityRegistry', () => { identities: { bobIdentity, charlieIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistry.connect(anotherWallet).updateIdentity(bobIdentity.target, charlieIdentity.target)).to.be.revertedWithCustomError( - identityRegistry, - 'CallerDoesNotHaveAgentRole', - ); + await expect( + identityRegistry.connect(anotherWallet).updateIdentity(bobIdentity.target, charlieIdentity.target), + ).to.be.revertedWithCustomError(identityRegistry, 'CallerDoesNotHaveAgentRole'); }); }); }); @@ -93,10 +92,9 @@ describe('IdentityRegistry', () => { accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(identityRegistry.connect(anotherWallet).registerIdentity(ethers.ZeroAddress, ethers.ZeroAddress, 0)).to.be.revertedWithCustomError( - identityRegistry, - 'CallerDoesNotHaveAgentRole', - ); + await expect( + identityRegistry.connect(anotherWallet).registerIdentity(ethers.ZeroAddress, ethers.ZeroAddress, 0), + ).to.be.revertedWithCustomError(identityRegistry, 'CallerDoesNotHaveAgentRole'); }); }); }); diff --git a/test/registries/trusted-issuers-registry.test.ts b/test/registries/trusted-issuers-registry.test.ts index acaf652a..ab32950f 100644 --- a/test/registries/trusted-issuers-registry.test.ts +++ b/test/registries/trusted-issuers-registry.test.ts @@ -2,7 +2,6 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { expect } from 'chai'; import { ethers } from 'hardhat'; import { deployFullSuiteFixture } from '../fixtures/deploy-full-suite.fixture'; -import { TestUpgradedCountryAllowModule__factory } from '../../typechain-types'; describe('TrustedIssuersRegistry', () => { describe('.addTrustedIssuer()', () => { @@ -128,7 +127,7 @@ describe('TrustedIssuersRegistry', () => { await expect(trustedIssuersRegistry.connect(deployer).removeTrustedIssuer(ethers.ZeroAddress)).to.be.revertedWithCustomError( trustedIssuersRegistry, - 'ZeroAddress' + 'ZeroAddress', ); }); }); @@ -142,7 +141,8 @@ describe('TrustedIssuersRegistry', () => { await expect(trustedIssuersRegistry.connect(deployer).removeTrustedIssuer(deployer.address)).to.be.revertedWithCustomError( trustedIssuersRegistry, - 'NotATrustedIssuer'); + 'NotATrustedIssuer', + ); }); }); @@ -197,7 +197,7 @@ describe('TrustedIssuersRegistry', () => { await expect(trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(ethers.ZeroAddress, [10])).to.be.revertedWithCustomError( trustedIssuersRegistry, - 'ZeroAddress' + 'ZeroAddress', ); }); }); @@ -225,10 +225,9 @@ describe('TrustedIssuersRegistry', () => { const claimTopics = Array.from({ length: 16 }, (_, i) => i); - await expect(trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(claimIssuerContract.target, claimTopics)).to.be.revertedWithCustomError( - trustedIssuersRegistry, - 'CannotHaveMoreThan15ClaimTopics', - ); + await expect( + trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(claimIssuerContract.target, claimTopics), + ).to.be.revertedWithCustomError(trustedIssuersRegistry, 'CannotHaveMoreThan15ClaimTopics'); }); }); @@ -239,10 +238,9 @@ describe('TrustedIssuersRegistry', () => { accounts: { deployer }, } = await loadFixture(deployFullSuiteFixture); - await expect(trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(claimIssuerContract.target, [])).to.be.revertedWithCustomError( - trustedIssuersRegistry, - 'ClaimTopicsCannotBeEmpty', - ); + await expect( + trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(claimIssuerContract.target, []), + ).to.be.revertedWithCustomError(trustedIssuersRegistry, 'ClaimTopicsCannotBeEmpty'); }); }); diff --git a/test/token/token-information.test.ts b/test/token/token-information.test.ts index 08a967ee..2d45d2af 100644 --- a/test/token/token-information.test.ts +++ b/test/token/token-information.test.ts @@ -283,7 +283,7 @@ describe('Token - Information', () => { accounts: { anotherWallet }, } = await loadFixture(deployFullSuiteFixture); await expect(token.connect(anotherWallet).freezePartialTokens(anotherWallet.address, 1)).to.be.revertedWithCustomError( - token, + token, 'CallerDoesNotHaveAgentRole', ); }); @@ -296,8 +296,9 @@ describe('Token - Information', () => { suite: { token }, accounts: { tokenAgent, anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(tokenAgent).freezePartialTokens(anotherWallet.address, 1)).to.be.revertedWith( - 'Amount exceeds available balance', + await expect(token.connect(tokenAgent).freezePartialTokens(anotherWallet.address, 1)).to.be.revertedWithCustomError( + token, + 'ERC20InsufficientBalance', ); }); }); @@ -325,8 +326,9 @@ describe('Token - Information', () => { suite: { token }, accounts: { tokenAgent, anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(tokenAgent).unfreezePartialTokens(anotherWallet.address, 1)).to.be.revertedWith( - 'Amount should be less than or equal to frozen tokens', + await expect(token.connect(tokenAgent).unfreezePartialTokens(anotherWallet.address, 1)).to.be.revertedWithCustomError( + token, + 'AmountAboveFrozenTokens', ); }); }); diff --git a/test/token/token-recovery.test.ts b/test/token/token-recovery.test.ts index fdbd5ec9..bafa30ea 100644 --- a/test/token/token-recovery.test.ts +++ b/test/token/token-recovery.test.ts @@ -17,10 +17,9 @@ describe('Token - Recovery', () => { .connect(bobWallet) .addKey(ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address'], [anotherWallet.address])), 1, 1); - await expect(token.connect(anotherWallet).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target)).to.be.revertedWithCustomError( - token, - 'CallerDoesNotHaveAgentRole', - ); + await expect( + token.connect(anotherWallet).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target), + ).to.be.revertedWithCustomError(token, 'CallerDoesNotHaveAgentRole'); }); }); @@ -63,10 +62,9 @@ describe('Token - Recovery', () => { await token.connect(bobWallet).transfer(aliceWallet.address, await token.balanceOf(bobWallet.address)); - await expect(token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target)).to.be.revertedWithCustomError( - token, - 'NoTokenToRecover', - ); + await expect( + token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target), + ).to.be.revertedWithCustomError(token, 'NoTokenToRecover'); }); }); @@ -78,10 +76,9 @@ describe('Token - Recovery', () => { identities: { bobIdentity }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target)).to.be.revertedWithCustomError( - token, - 'RecoveryNotPossible', - ); + await expect( + token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target), + ).to.be.revertedWithCustomError(token, 'RecoveryNotPossible'); }); }); diff --git a/test/token/token-transfer.test.ts b/test/token/token-transfer.test.ts index e063185c..dcaa013f 100644 --- a/test/token/token-transfer.test.ts +++ b/test/token/token-transfer.test.ts @@ -99,7 +99,10 @@ describe('Token - Transfers', () => { const balance = await token.balanceOf(aliceWallet.address); - await expect(token.connect(aliceWallet).transfer(bobWallet.address, balance + 1000n)).to.be.revertedWith('Insufficient Balance'); + await expect(token.connect(aliceWallet).transfer(bobWallet.address, balance + 1000n)).to.be.revertedWithCustomError( + token, + 'ERC20InsufficientBalance', + ); }); }); @@ -113,7 +116,10 @@ describe('Token - Transfers', () => { const balance = await token.balanceOf(aliceWallet.address); await token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, balance - 100n); - await expect(token.connect(aliceWallet).transfer(bobWallet.address, balance)).to.be.revertedWith('Insufficient Balance'); + await expect(token.connect(aliceWallet).transfer(bobWallet.address, balance)).to.be.revertedWithCustomError( + token, + 'ERC20InsufficientBalance', + ); }); }); @@ -124,7 +130,7 @@ describe('Token - Transfers', () => { accounts: { aliceWallet, anotherWallet }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(aliceWallet).transfer(anotherWallet.address, 100)).to.be.revertedWith('Transfer not possible'); + await expect(token.connect(aliceWallet).transfer(anotherWallet.address, 100)).to.be.revertedWithCustomError(token, 'TransferNotPossible'); }); }); @@ -139,7 +145,7 @@ describe('Token - Transfers', () => { await compliance.addModule(complianceModuleA.target); await token.setCompliance(compliance.target); - await expect(token.connect(aliceWallet).transfer(bobWallet.address, 100)).to.be.revertedWith('Transfer not possible'); + await expect(token.connect(aliceWallet).transfer(bobWallet.address, 100)).to.be.revertedWithCustomError(token, 'TransferNotPossible'); }); }); @@ -179,7 +185,10 @@ describe('Token - Transfers', () => { await token.connect(tokenAgent).pause(); - await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWithCustomError(token, 'EnforcedPause'); + await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWithCustomError( + token, + 'EnforcedPause', + ); }); }); @@ -192,7 +201,10 @@ describe('Token - Transfers', () => { await token.connect(tokenAgent).setAddressFrozen(aliceWallet.address, true); - await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWithCustomError(token, 'FrozenWallet'); + await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWithCustomError( + token, + 'FrozenWallet', + ); }); }); @@ -205,7 +217,10 @@ describe('Token - Transfers', () => { await token.connect(tokenAgent).setAddressFrozen(bobWallet.address, true); - await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWithCustomError(token, 'FrozenWallet'); + await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)).to.be.revertedWithCustomError( + token, + 'FrozenWallet', + ); }); }); @@ -339,8 +354,9 @@ describe('Token - Transfers', () => { const balance = await token.balanceOf(aliceWallet.address); - await expect(token.connect(tokenAgent).forcedTransfer(aliceWallet.address, bobWallet.address, balance + 1000n)).to.be.revertedWith( - 'sender balance too low', + await expect(token.connect(tokenAgent).forcedTransfer(aliceWallet.address, bobWallet.address, balance + 1000n)).to.be.revertedWithCustomError( + token, + 'ERC20InsufficientBalance', ); }); }); @@ -437,7 +453,7 @@ describe('Token - Transfers', () => { accounts: { anotherWallet, tokenAgent }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(tokenAgent).mint(anotherWallet.address, 100)).to.be.revertedWith('Identity is not verified.'); + await expect(token.connect(tokenAgent).mint(anotherWallet.address, 100)).to.be.revertedWithCustomError(token, 'UnverifiedIdentity'); }); }); @@ -452,7 +468,7 @@ describe('Token - Transfers', () => { await compliance.addModule(complianceModuleA.target); await token.setCompliance(compliance.target); - await expect(token.connect(tokenAgent).mint(aliceWallet.address, 100)).to.be.revertedWith('Compliance not followed'); + await expect(token.connect(tokenAgent).mint(aliceWallet.address, 100)).to.be.revertedWithCustomError(token, 'ComplianceNotFollowed'); }); }); }); @@ -499,7 +515,10 @@ describe('Token - Transfers', () => { const balance = await token.balanceOf(aliceWallet.address); - await expect(token.connect(tokenAgent).burn(aliceWallet.address, balance + 1000n)).to.be.revertedWith('cannot burn more than balance'); + await expect(token.connect(tokenAgent).burn(aliceWallet.address, balance + 1000n)).to.be.revertedWithCustomError( + token, + 'ERC20InsufficientBalance', + ); }); }); @@ -571,8 +590,9 @@ describe('Token - Transfers', () => { accounts: { aliceWallet, tokenAgent }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, 999999999999)).to.be.revertedWith( - 'Amount exceeds available balance', + await expect(token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, 999999999999)).to.be.revertedWithCustomError( + token, + 'ERC20InsufficientBalance', ); }); }); @@ -637,8 +657,9 @@ describe('Token - Transfers', () => { accounts: { aliceWallet, tokenAgent }, } = await loadFixture(deployFullSuiteFixture); - await expect(token.connect(tokenAgent).unfreezePartialTokens(aliceWallet.address, 5000)).to.be.revertedWith( - 'Amount should be less than or equal to frozen tokens', + await expect(token.connect(tokenAgent).unfreezePartialTokens(aliceWallet.address, 5000)).to.be.revertedWithCustomError( + token, + 'AmountAboveFrozenTokens', ); }); }); From e5eef3fcba751b2a6f8fb3374af69d88380ebb1b Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Thu, 4 Jul 2024 16:34:45 +0200 Subject: [PATCH 26/55] =?UTF-8?q?=E2=99=BB()=20TREX-132=20Update=20after?= =?UTF-8?q?=20review=201=20+=20rebase=20on=20develop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/DVD/DVDTransferManager.sol | 62 +++++------- .../compliance/modular/ModularCompliance.sol | 78 ++++++++------- .../modular/modules/AbstractModule.sol | 18 ++-- .../modules/AbstractModuleUpgradeable.sol | 18 ++-- .../modules/ConditionalTransferModule.sol | 15 ++- .../modular/modules/CountryAllowModule.sol | 18 +++- .../modular/modules/CountryRestrictModule.sol | 37 +++++--- .../modules/ExchangeMonthlyLimitsModule.sol | 5 +- .../modular/modules/MaxBalanceModule.sol | 46 ++++++--- .../modules/TimeExchangeLimitsModule.sol | 9 +- .../modules/TimeTransfersLimitsModule.sol | 4 +- .../modular/modules/TransferFeesModule.sol | 24 +++-- .../{libraries => }/errors/CommonErrors.sol | 95 +++++++++---------- .../errors/ComplianceErrors.sol | 26 +++-- .../errors/InvalidArgumentErrors.sol | 30 +++--- .../{libraries => }/errors/RoleErrors.sol | 50 ++++++---- contracts/factory/TREXFactory.sol | 51 ++++++---- contracts/factory/TREXGateway.sol | 22 +++-- contracts/proxy/AbstractProxy.sol | 15 +-- contracts/proxy/ClaimTopicsRegistryProxy.sol | 8 +- contracts/proxy/IdentityRegistryProxy.sol | 6 +- .../proxy/IdentityRegistryStorageProxy.sol | 6 +- contracts/proxy/ModularComplianceProxy.sol | 8 +- contracts/proxy/TokenProxy.sol | 12 +-- .../proxy/TrustedIssuersRegistryProxy.sol | 8 +- .../authority/TREXImplementationAuthority.sol | 69 +++++++------- .../implementation/ClaimTopicsRegistry.sol | 15 +-- .../implementation/IdentityRegistry.sol | 4 +- .../IdentityRegistryStorage.sol | 33 ++++--- .../implementation/TrustedIssuersRegistry.sol | 44 +++++---- contracts/roles/AgentRole.sol | 10 +- contracts/roles/AgentRoleUpgradeable.sol | 10 +- contracts/roles/Roles.sol | 10 +- .../permissioning/agent/AgentManager.sol | 40 ++++---- .../roles/permissioning/agent/AgentRoles.sol | 4 +- .../agent/AgentRolesUpgradeable.sol | 4 +- .../permissioning/owner/OwnerManager.sol | 28 +++--- .../roles/permissioning/owner/OwnerRoles.sol | 4 +- .../owner/OwnerRolesUpgradeable.sol | 4 +- contracts/token/Token.sol | 80 +++++++++------- .../trex-implementation-authority.test.ts | 6 +- test/compliance.test.ts | 8 +- .../module-conditional-transfer.test.ts | 2 +- .../module-country-restrict.test.ts | 4 +- test/dvd.test.ts | 4 +- test/registries/claim-topics-registry.test.ts | 2 +- .../identity-registry-storage.test.ts | 2 +- .../trusted-issuers-registry.test.ts | 8 +- 48 files changed, 593 insertions(+), 473 deletions(-) rename contracts/{libraries => }/errors/CommonErrors.sol (65%) rename contracts/{libraries => }/errors/ComplianceErrors.sol (80%) rename contracts/{libraries => }/errors/InvalidArgumentErrors.sol (85%) rename contracts/{libraries => }/errors/RoleErrors.sol (74%) diff --git a/contracts/DVD/DVDTransferManager.sol b/contracts/DVD/DVDTransferManager.sol index 2bd359cd..5becb607 100644 --- a/contracts/DVD/DVDTransferManager.sol +++ b/contracts/DVD/DVDTransferManager.sol @@ -70,8 +70,22 @@ pragma solidity 0.8.26; import "../roles/AgentRole.sol"; import "../token/IToken.sol"; -import "../libraries/errors/CommonErrors.sol"; -import "../libraries/errors/InvalidArgumentErrors.sol"; +import "../errors/CommonErrors.sol"; +import "../errors/InvalidArgumentErrors.sol"; + +/// Errors + +// @dev Thrown when the fee settings are invalid. +error InvalidFeeSettings(); + +// @dev Thrown when the transfer ID doesn't exist. +error TransferIDDoesNotExist(); + +// @dev Thrown when the transfer is not done by counterpart or owner. +error TransferOnlyByCounterpartOrOwner(); + +// @dev Thrown when the cancel is not done by counterpart, owner or agent. +error CancelOnlyByCounterpartOrOwnerOrAgent(); contract DVDTransferManager is Ownable { @@ -157,18 +171,6 @@ contract DVDTransferManager is Ownable { address fee1Wallet, address fee2Wallet); - /// Errors - - error FeeWalletCannotBeZeroAddress(uint256 walletIndex); - - error InvalidFeeSettings(); - - error TransferIDDoesNotExist(); - - error TransferOnlyByCounterpartOrOwner(); - - error CancelOnlyByCounterpartOrOwnerOrAgent(); - /// functions // initiates the nonce at 0 @@ -207,23 +209,20 @@ contract DVDTransferManager is Ownable { msg.sender == owner() || isTREXOwner(_token1, msg.sender) || isTREXOwner(_token2, msg.sender) - , CommonErrors.OwnableUnauthorizedAccount(msg.sender)); + , OwnableUnauthorizedAccount(msg.sender)); require( IERC20(_token1).totalSupply() != 0 && IERC20(_token2).totalSupply() != 0 - , InvalidArgumentErrors.AddressNotERC20(IERC20(_token1).totalSupply() != 0 ? _token2 : _token1)); + , AddressNotERC20(IERC20(_token1).totalSupply() != 0 ? _token2 : _token1)); require( _fee1 <= 10**_feeBase && _fee2 <= 10**_feeBase && _feeBase <= 5 && _feeBase >= 2 , InvalidFeeSettings()); - if (_fee1 > 0) { - require(_fee1Wallet != address(0), FeeWalletCannotBeZeroAddress(1)); - } - if (_fee2 > 0) { - require(_fee2Wallet != address(0), FeeWalletCannotBeZeroAddress(2)); - } + require(_fee1 == 0 || _fee1Wallet != address(0), ZeroAddress()); + require(_fee2 == 0 || _fee2Wallet != address(0), ZeroAddress()); + bytes32 _parity = calculateParity(_token1, _token2); Fee memory parityFee; parityFee.token1Fee = _fee1; @@ -265,13 +264,13 @@ contract DVDTransferManager is Ownable { address _token2, uint256 _token2Amount) external { uint256 balance = IERC20(_token1).balanceOf(msg.sender); - require(balance >= _token1Amount, CommonErrors.ERC20InsufficientBalance(msg.sender, balance, _token1Amount)); + require(balance >= _token1Amount, ERC20InsufficientBalance(msg.sender, balance, _token1Amount)); uint256 allowance = IERC20(_token1).allowance(msg.sender, address(this)); - require(allowance >= _token1Amount, CommonErrors.ERC20InsufficientAllowance(msg.sender, allowance, _token1Amount)); + require(allowance >= _token1Amount, ERC20InsufficientAllowance(msg.sender, allowance, _token1Amount)); - require (_counterpart != address(0), InvalidArgumentErrors.ZeroAddress()); - require(IERC20(_token2).totalSupply() != 0, InvalidArgumentErrors.AddressNotERC20(_token2)); + require (_counterpart != address(0), ZeroAddress()); + require(IERC20(_token2).totalSupply() != 0, AddressNotERC20(_token2)); Delivery memory token1; token1.counterpart = msg.sender; token1.token = _token1; @@ -338,16 +337,7 @@ contract DVDTransferManager is Ownable { isTREXAgent(token1.token, msg.sender) || isTREXAgent(token2.token, msg.sender) , TransferOnlyByCounterpartOrOwner()); - - uint256 balance = token2Contract.balanceOf(token2.counterpart); - require( - balance >= token2.amount - , CommonErrors.ERC20InsufficientBalance(token2.counterpart, balance, token2.amount)); - - uint256 allowance = token2Contract.allowance(token2.counterpart, address(this)); - require( - allowance >= token2.amount - , CommonErrors.ERC20InsufficientAllowance(token2.counterpart, allowance, token2.amount)); + // @dev balance and allowance not checked here, as it is done in transferFrom TxFees memory fees = calculateFee(_transferID); if (fees.txFee1 != 0) { diff --git a/contracts/compliance/modular/ModularCompliance.sol b/contracts/compliance/modular/ModularCompliance.sol index f3ac5d57..cffc915a 100644 --- a/contracts/compliance/modular/ModularCompliance.sol +++ b/contracts/compliance/modular/ModularCompliance.sol @@ -67,26 +67,29 @@ import "../../token/IToken.sol"; import "./IModularCompliance.sol"; import "./MCStorage.sol"; import "./modules/IModule.sol"; -import "../../libraries/errors/InvalidArgumentErrors.sol"; +import "../../errors/ComplianceErrors.sol"; +import "../../errors/InvalidArgumentErrors.sol"; +/// errors -contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage { - - /// errors - - error AddressNotATokenBoundToComplianceContract(); +/// @dev Thrown when trying to add more than max modules. +/// @param maxValue maximum number of modules. +error MaxModulesReached(uint256 maxValue); - error CannotAddMoreThan25Modules(); +/// @dev Thrown when module is already bound. +error ModuleAlreadyBound(); - error ComplianceNotSuitableForBindingToModule(); +/// @dev Thrown when module is not bound. +error ModuleNotBound(); - error ModuleAlreadyBound(); +/// @dev Thrown when called by other than owner or token. +error OnlyOwnerOrTokenCanCall(); - error ModuleNotBound(); +/// @dev Thrown when token is not bound. +error TokenNotBound(); - error OnlyOwnerOrTokenCanCall(); - error TokenNotBound(); +contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage { /// modifiers @@ -107,7 +110,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage */ function bindToken(address _token) external override { require(owner() == msg.sender || (_tokenBound == address(0) && msg.sender == _token), OnlyOwnerOrTokenCanCall()); - require(_token != address(0), InvalidArgumentErrors.ZeroAddress()); + require(_token != address(0), ZeroAddress()); _tokenBound = _token; emit TokenBound(_token); } @@ -118,7 +121,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage function unbindToken(address _token) external override { require(owner() == msg.sender || msg.sender == _token , OnlyOwnerOrTokenCanCall()); require(_token == _tokenBound, TokenNotBound()); - require(_token != address(0), InvalidArgumentErrors.ZeroAddress()); + require(_token != address(0), ZeroAddress()); delete _tokenBound; emit TokenUnbound(_token); } @@ -127,13 +130,12 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage * @dev See {IModularCompliance-addModule}. */ function addModule(address _module) external override onlyOwner { - require(_module != address(0), InvalidArgumentErrors.ZeroAddress()); + require(_module != address(0), ZeroAddress()); require(!_moduleBound[_module], ModuleAlreadyBound()); - require(_modules.length <= 24, CannotAddMoreThan25Modules()); + require(_modules.length <= 24, MaxModulesReached(25)); IModule module = IModule(_module); - if (!module.isPlugAndPlay()) { - require(module.canComplianceBind(address(this)), ComplianceNotSuitableForBindingToModule()); - } + require(module.isPlugAndPlay() || module.canComplianceBind(address(this)), + ComplianceNotSuitableForBindingToModule(_module)); module.bindCompliance(address(this)); _modules.push(_module); @@ -145,7 +147,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage * @dev See {IModularCompliance-removeModule}. */ function removeModule(address _module) external override onlyOwner { - require(_module != address(0), InvalidArgumentErrors.ZeroAddress()); + require(_module != address(0), ZeroAddress()); require(_moduleBound[_module], ModuleNotBound()); uint256 length = _modules.length; for (uint256 i = 0; i < length; i++) { @@ -167,8 +169,8 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage require( _from != address(0) && _to != address(0) - , InvalidArgumentErrors.ZeroAddress()); - require(_value > 0, InvalidArgumentErrors.NoValue()); + , ZeroAddress()); + require(_value > 0, ZeroValue()); uint256 length = _modules.length; for (uint256 i = 0; i < length; i++) { IModule(_modules[i]).moduleTransferAction(_from, _to, _value); @@ -179,8 +181,8 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage * @dev See {IModularCompliance-created}. */ function created(address _to, uint256 _value) external onlyToken override { - require(_to != address(0), InvalidArgumentErrors.ZeroAddress()); - require(_value > 0, InvalidArgumentErrors.NoValue()); + require(_to != address(0), ZeroAddress()); + require(_value > 0, ZeroValue()); uint256 length = _modules.length; for (uint256 i = 0; i < length; i++) { IModule(_modules[i]).moduleMintAction(_to, _value); @@ -191,8 +193,8 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage * @dev See {IModularCompliance-destroyed}. */ function destroyed(address _from, uint256 _value) external onlyToken override { - require(_from != address(0), InvalidArgumentErrors.ZeroAddress()); - require(_value > 0, InvalidArgumentErrors.NoValue()); + require(_from != address(0), ZeroAddress()); + require(_value > 0, ZeroValue()); uint256 length = _modules.length; for (uint256 i = 0; i < length; i++) { IModule(_modules[i]).moduleBurnAction(_from, _value); @@ -212,12 +214,24 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage // calldata twice to memory (the second being a "memcopy loop"). // solhint-disable-next-line no-inline-assembly assembly { - let freeMemoryPointer := mload(0x40) - calldatacopy(freeMemoryPointer, callData.offset, callData.length) - if iszero(call(gas(), _module, 0, freeMemoryPointer, callData.length, 0, 0)) - { - returndatacopy(0, 0, returndatasize()) - revert(0, returndatasize()) + let freeMemoryPointer := mload(0x40) // Load the free memory pointer from memory location 0x40 + + // Copy callData from calldata to the free memory location + calldatacopy(freeMemoryPointer, callData.offset, callData.length) + + if iszero( // Check if the call returns zero (indicating failure) + call( // Perform the external call + gas(), // Provide all available gas + _module, // Address of the target module + 0, // No ether is sent with the call + freeMemoryPointer, // Input data starts at the free memory pointer + callData.length, // Input data length + 0, // Output data location (not used) + 0 // Output data size (not used) + ) + ) { + returndatacopy(0, 0, returndatasize()) // Copy return data to memory starting at position 0 + revert(0, returndatasize()) // Revert the transaction with the return data } } diff --git a/contracts/compliance/modular/modules/AbstractModule.sol b/contracts/compliance/modular/modules/AbstractModule.sol index 4c15ec0b..c7552e83 100644 --- a/contracts/compliance/modular/modules/AbstractModule.sol +++ b/contracts/compliance/modular/modules/AbstractModule.sol @@ -63,8 +63,8 @@ pragma solidity 0.8.26; import "./IModule.sol"; -import "../../../libraries/errors/InvalidArgumentErrors.sol"; -import "../../../libraries/errors/ComplianceErrors.sol"; +import "../../../errors/InvalidArgumentErrors.sol"; +import "../../../errors/ComplianceErrors.sol"; abstract contract AbstractModule is IModule { @@ -75,7 +75,7 @@ abstract contract AbstractModule is IModule { * @dev Throws if `_compliance` is not a bound compliance contract address. */ modifier onlyBoundCompliance(address _compliance) { - require(_complianceBound[_compliance], ComplianceErrors.ComplianceNotBound()); + require(_complianceBound[_compliance], ComplianceNotBound()); _; } @@ -83,7 +83,7 @@ abstract contract AbstractModule is IModule { * @dev Throws if called from an address that is not a bound compliance contract. */ modifier onlyComplianceCall() { - require(_complianceBound[msg.sender], ComplianceErrors.OnlyBoundComplianceCanCall()); + require(_complianceBound[msg.sender], OnlyBoundComplianceCanCall()); _; } @@ -91,9 +91,9 @@ abstract contract AbstractModule is IModule { * @dev See {IModule-bindCompliance}. */ function bindCompliance(address _compliance) external override { - require(_compliance != address(0), InvalidArgumentErrors.ZeroAddress()); - require(!_complianceBound[_compliance], ComplianceErrors.ComplianceAlreadyBound()); - require(msg.sender == _compliance, ComplianceErrors.OnlyComplianceContractCanCall()); + require(_compliance != address(0), ZeroAddress()); + require(!_complianceBound[_compliance], ComplianceAlreadyBound()); + require(msg.sender == _compliance, OnlyComplianceContractCanCall()); _complianceBound[_compliance] = true; emit ComplianceBound(_compliance); } @@ -102,8 +102,8 @@ abstract contract AbstractModule is IModule { * @dev See {IModule-unbindCompliance}. */ function unbindCompliance(address _compliance) external onlyComplianceCall override { - require(_compliance != address(0), InvalidArgumentErrors.ZeroAddress()); - require(msg.sender == _compliance, ComplianceErrors.OnlyComplianceContractCanCall()); + require(_compliance != address(0), ZeroAddress()); + require(msg.sender == _compliance, OnlyComplianceContractCanCall()); _complianceBound[_compliance] = false; emit ComplianceUnbound(_compliance); } diff --git a/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol index b74d2fcb..31898009 100644 --- a/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol +++ b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol @@ -66,8 +66,8 @@ import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "./IModule.sol"; -import "../../../libraries/errors/InvalidArgumentErrors.sol"; -import "../../../libraries/errors/ComplianceErrors.sol"; +import "../../../errors/InvalidArgumentErrors.sol"; +import "../../../errors/ComplianceErrors.sol"; abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUpgradeable, UUPSUpgradeable { @@ -85,7 +85,7 @@ abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUp */ modifier onlyBoundCompliance(address _compliance) { AbstractModuleStorage storage s = _getAbstractModuleStorage(); - require(s.complianceBound[_compliance], ComplianceErrors.ComplianceNotBound()); + require(s.complianceBound[_compliance], ComplianceNotBound()); _; } @@ -94,7 +94,7 @@ abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUp */ modifier onlyComplianceCall() { AbstractModuleStorage storage s = _getAbstractModuleStorage(); - require(s.complianceBound[msg.sender], ComplianceErrors.OnlyBoundComplianceCanCall()); + require(s.complianceBound[msg.sender], OnlyBoundComplianceCanCall()); _; } @@ -103,9 +103,9 @@ abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUp */ function bindCompliance(address _compliance) external override { AbstractModuleStorage storage s = _getAbstractModuleStorage(); - require(_compliance != address(0), InvalidArgumentErrors.ZeroAddress()); - require(!s.complianceBound[_compliance], ComplianceErrors.ComplianceAlreadyBound()); - require(msg.sender == _compliance, ComplianceErrors.OnlyComplianceContractCanCall()); + require(_compliance != address(0), ZeroAddress()); + require(!s.complianceBound[_compliance], ComplianceAlreadyBound()); + require(msg.sender == _compliance, OnlyComplianceContractCanCall()); s.complianceBound[_compliance] = true; emit ComplianceBound(_compliance); } @@ -115,8 +115,8 @@ abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUp */ function unbindCompliance(address _compliance) external onlyComplianceCall override { AbstractModuleStorage storage s = _getAbstractModuleStorage(); - require(_compliance != address(0), InvalidArgumentErrors.ZeroAddress()); - require(msg.sender == _compliance, ComplianceErrors.OnlyComplianceContractCanCall()); + require(_compliance != address(0), ZeroAddress()); + require(msg.sender == _compliance, OnlyComplianceContractCanCall()); s.complianceBound[_compliance] = false; emit ComplianceUnbound(_compliance); } diff --git a/contracts/compliance/modular/modules/ConditionalTransferModule.sol b/contracts/compliance/modular/modules/ConditionalTransferModule.sol index 6eb19a0f..95437ee1 100644 --- a/contracts/compliance/modular/modules/ConditionalTransferModule.sol +++ b/contracts/compliance/modular/modules/ConditionalTransferModule.sol @@ -73,6 +73,15 @@ import "../../../token/IToken.sol"; import "../../../roles/AgentRole.sol"; import "./AbstractModuleUpgradeable.sol"; +/// Errors + +/// @dev Thrown when a tranfer is not approved. +/// @param _from the address of the transfer sender. +/// @param _to the address of the transfer receiver. +/// @param _amount the amount of tokens that `_from` was allowed to send to `_to`. +error TransferNotApproved(address _from, address _to, uint _amount); + + /** * this module allows to require the pre-validation of a transfer before allowing it to be executed */ @@ -100,10 +109,6 @@ contract ConditionalTransferModule is AbstractModuleUpgradeable { */ event ApprovalRemoved(address _from, address _to, uint _amount, address _token); - /// Errors - - error NotApproved(); - /** * @dev initializes the contract and sets the initial state. * @notice This function should only be called once during the contract deployment. @@ -235,7 +240,7 @@ contract ConditionalTransferModule is AbstractModuleUpgradeable { */ function unApproveTransfer(address _from, address _to, uint _amount) public onlyComplianceCall { bytes32 transferHash = calculateTransferHash(_from, _to, _amount, IModularCompliance(msg.sender).getTokenBound()); - require(_transfersApproved[msg.sender][transferHash] > 0, NotApproved()); + require(_transfersApproved[msg.sender][transferHash] > 0, TransferNotApproved(_from, _to, _amount)); _transfersApproved[msg.sender][transferHash]--; emit ApprovalRemoved(_from, _to, _amount, IModularCompliance(msg.sender).getTokenBound()); diff --git a/contracts/compliance/modular/modules/CountryAllowModule.sol b/contracts/compliance/modular/modules/CountryAllowModule.sol index 3902c73d..5de0afc5 100644 --- a/contracts/compliance/modular/modules/CountryAllowModule.sol +++ b/contracts/compliance/modular/modules/CountryAllowModule.sol @@ -72,6 +72,19 @@ import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; import "./AbstractModuleUpgradeable.sol"; +/// Errors + +/// @dev Thrown when a country is already allowed. +/// @param _compliance compliance contract address. +/// @param _country country code. +error CountryAlreadyAllowed(address _compliance, uint16 _country); + +/// @dev Thrown when a country is not allowed. +/// @param _compliance compliance contract address. +/// @param _country country code. +error CountryNotAllowed(address _compliance, uint16 _country); + + contract CountryAllowModule is AbstractModuleUpgradeable { /// Mapping between country and their allowance status per compliance contract mapping(address => mapping(uint16 => bool)) private _allowedCountries; @@ -91,11 +104,6 @@ contract CountryAllowModule is AbstractModuleUpgradeable { */ event CountryUnallowed(address _compliance, uint16 _country); - /// Custom Errors - - error CountryAlreadyAllowed(address _compliance, uint16 _country); - error CountryNotAllowed(address _compliance, uint16 _country); - /// functions /** diff --git a/contracts/compliance/modular/modules/CountryRestrictModule.sol b/contracts/compliance/modular/modules/CountryRestrictModule.sol index 4d9cecdf..11f39d8b 100644 --- a/contracts/compliance/modular/modules/CountryRestrictModule.sol +++ b/contracts/compliance/modular/modules/CountryRestrictModule.sol @@ -72,6 +72,23 @@ import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; import "./AbstractModuleUpgradeable.sol"; +/// Errors + +/// @dev Thrown when a country is already restricted. +/// @param _compliance compliance contract address. +/// @param _country country code. +error CountryAlreadyRestricted(address _compliance, uint16 _country); + +/// @dev Thrown when a country is not restricted. +/// @param _compliance compliance contract address. +/// @param _country country code. +error CountryNotRestricted(address _compliance, uint16 _country); + +/// @dev Thrown when max number of countries is reached in batch. +/// @param _max maximum number in batch. +error MaxCountriesInBatchReached(uint256 _max); + + contract CountryRestrictModule is AbstractModuleUpgradeable { /// Mapping between country and their restriction status per compliance contract @@ -91,14 +108,6 @@ contract CountryRestrictModule is AbstractModuleUpgradeable { */ event RemovedRestrictedCountry(address indexed _compliance, uint16 _country); - /// errors - - error CountryAlreadyRestricted(); - - error CountryNotRestricted(); - - error Max195CountriesInBatch(); - /// Functions /** @@ -117,7 +126,7 @@ contract CountryRestrictModule is AbstractModuleUpgradeable { * emits an `AddedRestrictedCountry` event */ function addCountryRestriction(uint16 _country) external onlyComplianceCall { - require((_restrictedCountries[msg.sender])[_country] == false, CountryAlreadyRestricted()); + require((_restrictedCountries[msg.sender])[_country] == false, CountryAlreadyRestricted(msg.sender, _country)); (_restrictedCountries[msg.sender])[_country] = true; emit AddedRestrictedCountry(msg.sender, _country); } @@ -131,7 +140,7 @@ contract CountryRestrictModule is AbstractModuleUpgradeable { * emits an `RemovedRestrictedCountry` event */ function removeCountryRestriction(uint16 _country) external onlyComplianceCall { - require((_restrictedCountries[msg.sender])[_country] == true, CountryNotRestricted()); + require((_restrictedCountries[msg.sender])[_country] == true, CountryNotRestricted(msg.sender, _country)); (_restrictedCountries[msg.sender])[_country] = false; emit RemovedRestrictedCountry(msg.sender, _country); } @@ -146,9 +155,9 @@ contract CountryRestrictModule is AbstractModuleUpgradeable { * emits _countries.length `AddedRestrictedCountry` events */ function batchRestrictCountries(uint16[] calldata _countries) external onlyComplianceCall { - require(_countries.length < 195, Max195CountriesInBatch()); + require(_countries.length < 195, MaxCountriesInBatchReached(195)); for (uint256 i = 0; i < _countries.length; i++) { - require(!(_restrictedCountries[msg.sender])[_countries[i]], CountryAlreadyRestricted()); + require(!(_restrictedCountries[msg.sender])[_countries[i]], CountryAlreadyRestricted(msg.sender, _countries[i])); (_restrictedCountries[msg.sender])[_countries[i]] = true; emit AddedRestrictedCountry(msg.sender, _countries[i]); } @@ -164,9 +173,9 @@ contract CountryRestrictModule is AbstractModuleUpgradeable { * emits _countries.length `RemovedRestrictedCountry` events */ function batchUnrestrictCountries(uint16[] calldata _countries) external onlyComplianceCall { - require(_countries.length < 195, Max195CountriesInBatch()); + require(_countries.length < 195, MaxCountriesInBatchReached(195)); for (uint256 i = 0; i < _countries.length; i++) { - require((_restrictedCountries[msg.sender])[_countries[i]], CountryNotRestricted()); + require((_restrictedCountries[msg.sender])[_countries[i]], CountryNotRestricted(msg.sender, _countries[i])); (_restrictedCountries[msg.sender])[_countries[i]] = false; emit RemovedRestrictedCountry(msg.sender, _countries[i]); } diff --git a/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol b/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol index cf9d88a1..0eb9cc11 100644 --- a/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol +++ b/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol @@ -73,6 +73,7 @@ import "../../../token/IToken.sol"; import "../../../roles/AgentRole.sol"; import "./AbstractModuleUpgradeable.sol"; + contract ExchangeMonthlyLimitsModule is AbstractModuleUpgradeable { /// Struct of transfer Counters struct ExchangeTransferCounter { @@ -112,10 +113,6 @@ contract ExchangeMonthlyLimitsModule is AbstractModuleUpgradeable { */ event ExchangeIDRemoved(address _exchangeID); - error ONCHAINIDAlreadyTaggedAsExchange(address _exchangeID); - - error ONCHAINIDNotTaggedAsExchange(address _exchangeID); - /** * @dev initializes the contract and sets the initial state. * @notice This function should only be called once during the contract deployment. diff --git a/contracts/compliance/modular/modules/MaxBalanceModule.sol b/contracts/compliance/modular/modules/MaxBalanceModule.sol index 6f4d30bf..fdb589e4 100644 --- a/contracts/compliance/modular/modules/MaxBalanceModule.sol +++ b/contracts/compliance/modular/modules/MaxBalanceModule.sol @@ -73,6 +73,33 @@ import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; import "./AbstractModuleUpgradeable.sol"; +/// errors + +/// @dev Thrown when +/// @param _compliance compliance contract address. +/// @param _value value. +/// @param _max maximum value. +error MaxBalanceExceeded(address _compliance, uint256 _value, uint256 _max); + +/// @dev Thrown when preset values are invalid. +/// @param _compliance compliance contract address. +/// @param _id array of ids. +/// @param _balance array of balances. +error InvalidPresetValues(address _compliance, address[] _id, uint256[] _balance); + +/// @dev Thrown when called by other than compliance owner. +/// @param _compliance compliance contract address. +error OnlyComplianceOwnerCanCall(address _compliance); + +/// @dev Thrown when the token is already bound. +/// @param _compliance compliance contract address. +error TokenAlreadyBound(address _compliance); + +/// @dev Thrown when identity not found in the identity registry. +/// @param _userAddress address of user. +error IdentityNotFound(address _userAddress); + + contract MaxBalanceModule is AbstractModuleUpgradeable { /// state variables @@ -98,17 +125,6 @@ contract MaxBalanceModule is AbstractModuleUpgradeable { event IDBalancePreSet(address indexed _compliance, address indexed _id, uint256 _balance); - /// errors - error MaxBalanceExceeded(address _compliance, uint256 _value); - - error InvalidPresetValues(address _compliance, address[] _id, uint256[] _balance); - - error OnlyComplianceOwnerCanCall(address _compliance); - - error TokenAlreadyBound(address _compliance); - - error IdentityNotFound(); - /// functions /** @@ -188,7 +204,8 @@ contract MaxBalanceModule is AbstractModuleUpgradeable { address _idTo = _getIdentity(msg.sender, _to); _IDBalance[msg.sender][_idTo] += _value; _IDBalance[msg.sender][_idFrom] -= _value; - require(_IDBalance[msg.sender][_idTo] <= _maxBalance[msg.sender], MaxBalanceExceeded(msg.sender, _value)); + require(_IDBalance[msg.sender][_idTo] <= _maxBalance[msg.sender], + MaxBalanceExceeded(msg.sender, _value, _maxBalance[msg.sender])); } /** @@ -198,7 +215,8 @@ contract MaxBalanceModule is AbstractModuleUpgradeable { function moduleMintAction(address _to, uint256 _value) external override onlyComplianceCall { address _idTo = _getIdentity(msg.sender, _to); _IDBalance[msg.sender][_idTo] += _value; - require(_IDBalance[msg.sender][_idTo] <= _maxBalance[msg.sender], MaxBalanceExceeded(msg.sender, _value)); + require(_IDBalance[msg.sender][_idTo] <= _maxBalance[msg.sender], + MaxBalanceExceeded(msg.sender, _value, _maxBalance[msg.sender])); } /** @@ -294,7 +312,7 @@ contract MaxBalanceModule is AbstractModuleUpgradeable { function _getIdentity(address _compliance, address _userAddress) internal view returns (address) { address identity = address(IToken(IModularCompliance(_compliance).getTokenBound()) .identityRegistry().identity(_userAddress)); - require(identity != address(0), IdentityNotFound()); + require(identity != address(0), IdentityNotFound(_userAddress)); return identity; } } diff --git a/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol b/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol index ba947ae7..9ab4e076 100644 --- a/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol +++ b/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol @@ -73,6 +73,7 @@ import "../../../token/IToken.sol"; import "../../../roles/AgentRole.sol"; import "./AbstractModuleUpgradeable.sol"; + contract TimeExchangeLimitsModule is AbstractModuleUpgradeable { /// Struct of transfer Counters struct ExchangeTransferCounter { @@ -127,14 +128,6 @@ contract TimeExchangeLimitsModule is AbstractModuleUpgradeable { */ event ExchangeIDRemoved(address _exchangeID); - /// Errors - - error ONCHAINIDAlreadyTaggedAsExchange(address _exchangeID); - - error ONCHAINIDNotTaggedAsExchange(address _exchangeID); - - error LimitsArraySizeExceeded(address compliance, uint arraySize); - /** * @dev initializes the contract and sets the initial state. * @notice This function should only be called once during the contract deployment. diff --git a/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol b/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol index e6c43306..64f2845d 100644 --- a/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol +++ b/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol @@ -72,6 +72,8 @@ import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; import "../../../roles/AgentRole.sol"; import "./AbstractModuleUpgradeable.sol"; +import "../../../errors/InvalidArgumentErrors.sol"; + contract TimeTransfersLimitsModule is AbstractModuleUpgradeable { /// Struct of transfer Counters @@ -108,8 +110,6 @@ contract TimeTransfersLimitsModule is AbstractModuleUpgradeable { */ event TimeTransferLimitUpdated(address indexed compliance, uint32 limitTime, uint256 limitValue); - error LimitsArraySizeExceeded(address compliance, uint arraySize); - /** * @dev initializes the contract and sets the initial state. * @notice This function should only be called once during the contract deployment. diff --git a/contracts/compliance/modular/modules/TransferFeesModule.sol b/contracts/compliance/modular/modules/TransferFeesModule.sol index a51b7fa0..7b2a8566 100644 --- a/contracts/compliance/modular/modules/TransferFeesModule.sol +++ b/contracts/compliance/modular/modules/TransferFeesModule.sol @@ -73,6 +73,22 @@ import "../../../token/IToken.sol"; import "../../../roles/AgentRole.sol"; import "./AbstractModuleUpgradeable.sol"; +/// Errors + +/// @dev Thrown when fee rate is out of range. +/// @param _compliance compliance contract address. +/// @param _rate rate value. +error FeeRateIsOutOfRange(address _compliance, uint256 _rate); + +/// @dev Thrown when the collector address is not verified. +/// @param _compliance compliance contract address. +/// @param _collector collector contract address. +error CollectorAddressIsNotVerified(address _compliance, address _collector); + +/// @dev Thrown when transfer fee collection failed. +error TransferFeeCollectionFailed(); + + contract TransferFeesModule is AbstractModuleUpgradeable { /// Struct of fees struct Fee { @@ -92,14 +108,6 @@ contract TransferFeesModule is AbstractModuleUpgradeable { */ event FeeUpdated(address indexed compliance, uint256 _rate, address _collector); - /// Errors - - error FeeRateIsOutOfRange(address compliance, uint256 rate); - - error CollectorAddressIsNotVerified(address compliance, address collector); - - error TransferFeeCollectionFailed(); - /** * @dev initializes the contract and sets the initial state. * @notice This function should only be called once during the contract deployment. diff --git a/contracts/libraries/errors/CommonErrors.sol b/contracts/errors/CommonErrors.sol similarity index 65% rename from contracts/libraries/errors/CommonErrors.sol rename to contracts/errors/CommonErrors.sol index ca0f43bd..fc9b9249 100644 --- a/contracts/libraries/errors/CommonErrors.sol +++ b/contracts/errors/CommonErrors.sol @@ -64,63 +64,60 @@ pragma solidity 0.8.26; +/// @dev Thrown when initialization has failed. +error InitializationFailed(); -library CommonErrors { +/// @dev Thrown when the implementation authority is invalid. +error InvalidImplementationAuthority(); - error InitializationFailed(); - /// @dev We must use OpenZeppelin libs when upgrading to v >= 5 for errors below +/// @dev We must use OpenZeppelin libs when upgrading to v >= 5 for errors below - /** - * @dev The caller account is not authorized to perform an operation. - */ - error OwnableUnauthorizedAccount(address account); - - /** - * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. - * @param spender Address that may be allowed to operate on tokens without being their owner. - * @param allowance Amount of tokens a `spender` is allowed to operate with. - * @param needed Minimum amount required to perform a transfer. - */ - error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); - - /** - * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. - * @param sender Address whose tokens are being transferred. - * @param balance Current balance for the interacting account. - * @param needed Minimum amount required to perform a transfer. - */ - error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); - - /** - * @dev Indicates a failure with the token `receiver`. Used in transfers. - * @param receiver Address to which tokens are being transferred. - */ - error ERC20InvalidReceiver(address receiver); - - /** - * @dev Indicates a failure with the token `sender`. Used in transfers. - * @param sender Address whose tokens are being transferred. - */ - error ERC20InvalidSender(address sender); +/** +* @dev The caller account is not authorized to perform an operation. +*/ +error OwnableUnauthorizedAccount(address account); - /** - * @dev Indicates a failure with the `spender` to be approved. Used in approvals. - * @param spender Address that may be allowed to operate on tokens without being their owner. - */ - error ERC20InvalidSpender(address spender); +/** +* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. +* @param spender Address that may be allowed to operate on tokens without being their owner. +* @param allowance Amount of tokens a `spender` is allowed to operate with. +* @param needed Minimum amount required to perform a transfer. +*/ +error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); +/** +* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. +* @param sender Address whose tokens are being transferred. +* @param balance Current balance for the interacting account. +* @param needed Minimum amount required to perform a transfer. +*/ +error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); +/** +* @dev Indicates a failure with the token `receiver`. Used in transfers. +* @param receiver Address to which tokens are being transferred. +*/ +error ERC20InvalidReceiver(address receiver); - /** - * @dev The operation failed because the contract is paused. - */ - error EnforcedPause(); +/** +* @dev Indicates a failure with the token `sender`. Used in transfers. +* @param sender Address whose tokens are being transferred. +*/ +error ERC20InvalidSender(address sender); - /** - * @dev The operation failed because the contract is not paused. - */ - error ExpectedPause(); +/** +* @dev Indicates a failure with the `spender` to be approved. Used in approvals. +* @param spender Address that may be allowed to operate on tokens without being their owner. +*/ +error ERC20InvalidSpender(address spender); -} +/** +* @dev The operation failed because the contract is paused. +*/ +error EnforcedPause(); +/** +* @dev The operation failed because the contract is not paused. +*/ +error ExpectedPause(); diff --git a/contracts/libraries/errors/ComplianceErrors.sol b/contracts/errors/ComplianceErrors.sol similarity index 80% rename from contracts/libraries/errors/ComplianceErrors.sol rename to contracts/errors/ComplianceErrors.sol index 025b3092..3a227d66 100644 --- a/contracts/libraries/errors/ComplianceErrors.sol +++ b/contracts/errors/ComplianceErrors.sol @@ -64,16 +64,30 @@ pragma solidity 0.8.26; +/// @dev Thrown when address is not a token bound to compliance contract. +error AddressNotATokenBoundToComplianceContract(); -library ComplianceErrors { +/// @dev Thrown when compliance is already bound. +error ComplianceAlreadyBound(); - error ComplianceAlreadyBound(); +/// @dev Thrown when compliance is not bound. +error ComplianceNotBound(); - error ComplianceNotBound(); +/// @dev Thrown when coompliance is not suitable for binding to module. +/// @param module Address of the module. +error ComplianceNotSuitableForBindingToModule(address module); - error OnlyBoundComplianceCanCall(); +/// @dev Thrown when exchange already tagged. +/// @param _exchangeID ONCHAINID of the exchange. +error ONCHAINIDAlreadyTaggedAsExchange(address _exchangeID); - error OnlyComplianceContractCanCall(); +/// @dev Thrown when exchange is not tagged. +/// @param _exchangeID ONCHAINID of the exchange. +error ONCHAINIDNotTaggedAsExchange(address _exchangeID); -} +/// @dev Thrown when call by otther than bound compliance. +error OnlyBoundComplianceCanCall(); + +/// @dev Thrown when call by other than compliance contract. +error OnlyComplianceContractCanCall(); diff --git a/contracts/libraries/errors/InvalidArgumentErrors.sol b/contracts/errors/InvalidArgumentErrors.sol similarity index 85% rename from contracts/libraries/errors/InvalidArgumentErrors.sol rename to contracts/errors/InvalidArgumentErrors.sol index 22b99ae8..33a1afab 100644 --- a/contracts/libraries/errors/InvalidArgumentErrors.sol +++ b/contracts/errors/InvalidArgumentErrors.sol @@ -64,22 +64,24 @@ pragma solidity 0.8.26; -library InvalidArgumentErrors { +/// @dev Thrown when the address is not an ERC20. +/// @param token address of the token. +error AddressNotERC20(address token); - /// @notice Thrown when the address is not an ERC20. - error AddressNotERC20(address token); +/// @dev Thrown when limits array size exceeded. +/// @param _compliance compliance contract address. +/// @param _arraySize array size. +error LimitsArraySizeExceeded(address _compliance, uint _arraySize); - error DecimalsBetween0And18(); +/// @dev Thrown when invalid decimals is set. +/// @param _decimals number of decimals +error DecimalsOutOfRange(uint256 _decimals); - /// @notice Thrown when the string passed is empty. - error EmptyString(); +/// @dev Thrown when the string passed is empty. +error EmptyString(); - error InvalidImplementationAuthority(); - - /// @notice Thrown when token amount is zero. - error NoValue(); - - /// @notice Thrown when the address passed is the zero address. - error ZeroAddress(); -} +/// @dev Thrown when token amount is zero. +error ZeroValue(); +/// @dev Thrown when the address passed is the zero address. +error ZeroAddress(); diff --git a/contracts/libraries/errors/RoleErrors.sol b/contracts/errors/RoleErrors.sol similarity index 74% rename from contracts/libraries/errors/RoleErrors.sol rename to contracts/errors/RoleErrors.sol index 1b1ec92c..40580557 100644 --- a/contracts/libraries/errors/RoleErrors.sol +++ b/contracts/errors/RoleErrors.sol @@ -63,37 +63,47 @@ pragma solidity 0.8.26; +/// @dev Thrown when account already has role. +error AccountAlreadyHasRole(); -library RoleErrors { +/// @dev Thrown when account doesn't have role. +error AccountDoesNotHaveRole(); - error AccountAlreadyHasRole(); +/// @dev Thrown when caller doesn't have agent role. +error CallerDoesNotHaveAgentRole(); - error AccountDoesNotHaveRole(); +/// @dev Thrown when sender is not admin. +error SenderIsNotAdmin(); - error CallerDoesNotHaveAgentRole(); +/// @dev Thrown when sender is not claim registry manager. +error SenderIsNotClaimRegistryManager(); - error SenderIsNotAdmin(); +/// @dev Thrown when sender is not comp^liance manager. +error SenderIsNotComplianceManager(); - error SenderIsNotClaimRegistryManager(); +/// @dev Thrown when sender is not complikance setter. +error SenderIsNotComplianceSetter(); - error SenderIsNotComplianceManager(); +/// @dev Thrown when sender is not freezer. +error SenderIsNotFreezer(); - error SenderIsNotComplianceSetter(); +/// @dev Thrown when sender is not issuer registry manager. +error SenderIsNotIssuersRegistryManager(); - error SenderIsNotFreezer(); +/// @dev Thrown when sender is not recovery agent. +error SenderIsNotRecoveryAgent(); - error SenderIsNotIssuersRegistryManager(); +/// @dev Thrown when sender is not registry address setter. +error SenderIsNotRegistryAddressSetter(); - error SenderIsNotRecoveryAgent(); +/// @dev Thrown when sender is not supply modifier. +error SenderIsNotSupplyModifier(); - error SenderIsNotRegistryAddressSetter(); +/// @dev Thrown when sender is not token information manager. +error SenderIsNotTokenInformationManager(); - error SenderIsNotSupplyModifier(); +/// @dev Thrown when sender is not transfer manager. +error SenderIsNotTransferManager(); - error SenderIsNotTokenInformationManager(); - - error SenderIsNotTransferManager(); - - error SenderIsNotWhiteListManager(); - -} +/// @dev Thrown when sender is not whitelist manager. +error SenderIsNotWhiteListManager(); diff --git a/contracts/factory/TREXFactory.sol b/contracts/factory/TREXFactory.sol index 895c4ecd..da195b18 100644 --- a/contracts/factory/TREXFactory.sol +++ b/contracts/factory/TREXFactory.sol @@ -77,7 +77,35 @@ import "../proxy/TrustedIssuersRegistryProxy.sol"; import "../proxy/ModularComplianceProxy.sol"; import "./ITREXFactory.sol"; import "@onchain-id/solidity/contracts/factory/IIdFactory.sol"; -import "../libraries/errors/InvalidArgumentErrors.sol"; +import "../errors/CommonErrors.sol"; +import "../errors/InvalidArgumentErrors.sol"; + +/// Errors + +/// @dev Thrown when claim pattern is invalid. +error InvalidClaimPattern(); + +/// @dev Thrown when compliance pattern is invalid. +error InvalidCompliancePattern(); + +/// @dev Thrown when maximum number of claim issuers is reached. +/// @param _max max value. +error MaxClaimIssuersReached(uint256 _max); + +/// @dev Thrown when maximum number of claim topicsis reached. +/// @param _max max value. +error MaxClaimTopicsReached(uint256 _max); + +/// @dev Thrown when maximum number of agetns is reached. +/// @param _max max value. +error MaxAgentsReached(uint256 _max); + +/// @dev Thrown when maximum number of module actions reached. +/// @param _max max value. +error MaxModuleActionsReached(uint256 _max); + +/// @dev Thrown when token is already deployed. +error TokenAlreadyDeployed(); contract TREXFactory is ITREXFactory, Ownable { @@ -91,23 +119,6 @@ contract TREXFactory is ITREXFactory, Ownable { /// mapping containing info about the token contracts corresponding to salt already used for CREATE2 deployments mapping(string => address) public tokenDeployed; - /// Errors - - error InvalidClaimPattern(); - - error InvalidCompliancePattern(); - - error InvalidImplementationAuthority(); - - error MaxClaimIssuersReached(uint256 max); - - error MaxClaimTopicsReached(uint256 max); - - error MaxAgentsReached(uint256 max); - - error MaxModuleActionsReached(uint256 max); - - error TokenAlreadyDeployed(); /// constructor is setting the implementation authority and the Identity Factory of the TREX factory constructor(address implementationAuthority_, address idFactory_) { @@ -221,7 +232,7 @@ contract TREXFactory is ITREXFactory, Ownable { * @dev See {ITREXFactory-setImplementationAuthority}. */ function setImplementationAuthority(address implementationAuthority_) public override onlyOwner { - require(implementationAuthority_ != address(0), InvalidArgumentErrors.ZeroAddress()); + require(implementationAuthority_ != address(0), ZeroAddress()); // should not be possible to set an implementation authority that is not complete require( (ITREXImplementationAuthority(implementationAuthority_)).getTokenImplementation() != address(0) @@ -239,7 +250,7 @@ contract TREXFactory is ITREXFactory, Ownable { * @dev See {ITREXFactory-setIdFactory}. */ function setIdFactory(address idFactory_) public override onlyOwner { - require(idFactory_ != address(0), InvalidArgumentErrors.ZeroAddress()); + require(idFactory_ != address(0), ZeroAddress()); _idFactory = idFactory_; emit IdFactorySet(idFactory_); } diff --git a/contracts/factory/TREXGateway.sol b/contracts/factory/TREXGateway.sol index c431a086..6128cea6 100644 --- a/contracts/factory/TREXGateway.sol +++ b/contracts/factory/TREXGateway.sol @@ -65,8 +65,10 @@ import "./ITREXGateway.sol"; import "../roles/AgentRole.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "../libraries/errors/InvalidArgumentErrors.sol"; -import "../libraries/errors/RoleErrors.sol"; +import "../errors/InvalidArgumentErrors.sol"; +import "../errors/RoleErrors.sol"; + +/// Errors /// The Public Deployment Status is already set properly error PublicDeploymentAlreadyEnabled(); @@ -132,7 +134,7 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-setFactory}. */ function setFactory(address factory) external override onlyOwner { - require(factory != address(0), InvalidArgumentErrors.ZeroAddress()); + require(factory != address(0), ZeroAddress()); _factory = factory; emit FactorySet(factory); @@ -177,7 +179,7 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-setDeploymentFee}. */ function setDeploymentFee(uint256 _fee, address _feeToken, address _feeCollector) external override onlyOwner { - require(_feeToken != address(0) && _feeCollector != address(0), InvalidArgumentErrors.ZeroAddress()); + require(_feeToken != address(0) && _feeCollector != address(0), ZeroAddress()); _deploymentFee.fee = _fee; _deploymentFee.feeToken = _feeToken; @@ -189,7 +191,7 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-batchAddDeployer}. */ function batchAddDeployer(address[] calldata deployers) external override { - require(isAgent(msg.sender) || msg.sender == owner(), RoleErrors.SenderIsNotAdmin()); + require(isAgent(msg.sender) || msg.sender == owner(), SenderIsNotAdmin()); require(deployers.length <= 500, BatchMaxLengthExceeded(500)); for (uint256 i = 0; i < deployers.length; i++) { @@ -204,7 +206,7 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-addDeployer}. */ function addDeployer(address deployer) external override { - require(isAgent(msg.sender) || msg.sender == owner(), RoleErrors.SenderIsNotAdmin()); + require(isAgent(msg.sender) || msg.sender == owner(), SenderIsNotAdmin()); require(!isDeployer(deployer), DeployerAlreadyExists(deployer)); _deployers[deployer] = true; @@ -215,7 +217,7 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-batchRemoveDeployer}. */ function batchRemoveDeployer(address[] calldata deployers) external override { - require(isAgent(msg.sender) || msg.sender == owner(), RoleErrors.SenderIsNotAdmin()); + require(isAgent(msg.sender) || msg.sender == owner(), SenderIsNotAdmin()); require(deployers.length <= 500, BatchMaxLengthExceeded(500)); for (uint256 i = 0; i < deployers.length; i++) { @@ -230,7 +232,7 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-removeDeployer}. */ function removeDeployer(address deployer) external override { - require(isAgent(msg.sender) || msg.sender == owner(), RoleErrors.SenderIsNotAdmin()); + require(isAgent(msg.sender) || msg.sender == owner(), SenderIsNotAdmin()); require(isDeployer(deployer), DeployerDoesNotExist(deployer)); delete _deployers[deployer]; @@ -241,7 +243,7 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-batchApplyFeeDiscount}. */ function batchApplyFeeDiscount(address[] calldata deployers, uint16[] calldata discounts) external override { - require(isAgent(msg.sender) || msg.sender == owner(), RoleErrors.SenderIsNotAdmin()); + require(isAgent(msg.sender) || msg.sender == owner(), SenderIsNotAdmin()); require(deployers.length <= 500, BatchMaxLengthExceeded(500)); for (uint256 i = 0; i < deployers.length; i++) { @@ -256,7 +258,7 @@ contract TREXGateway is ITREXGateway, AgentRole { * @dev See {ITREXGateway-applyFeeDiscount}. */ function applyFeeDiscount(address deployer, uint16 discount) external override { - require(isAgent(msg.sender) || msg.sender == owner(), RoleErrors.SenderIsNotAdmin()); + require(isAgent(msg.sender) || msg.sender == owner(), SenderIsNotAdmin()); require(discount <= 10000, DiscountOutOfRange()); _feeDiscount[deployer] = discount; diff --git a/contracts/proxy/AbstractProxy.sol b/contracts/proxy/AbstractProxy.sol index 5d268a23..cf5a2064 100644 --- a/contracts/proxy/AbstractProxy.sol +++ b/contracts/proxy/AbstractProxy.sol @@ -65,20 +65,23 @@ pragma solidity 0.8.26; import "./interface/IProxy.sol"; import "./authority/ITREXImplementationAuthority.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import "../libraries/errors/InvalidArgumentErrors.sol"; +import "../errors/CommonErrors.sol"; +import "../errors/InvalidArgumentErrors.sol"; -abstract contract AbstractProxy is IProxy, Initializable { +/// Errors + +/// @dev Thrown when called by other than the current implementation authority. +error OnlyCurrentImplementationAuthorityCanCall(); - /// Errors - error OnlyCurrentImplementationAuthorityCanCall(); +abstract contract AbstractProxy is IProxy, Initializable { /** * @dev See {IProxy-setImplementationAuthority}. */ function setImplementationAuthority(address _newImplementationAuthority) external override { require(msg.sender == getImplementationAuthority(), OnlyCurrentImplementationAuthorityCanCall()); - require(_newImplementationAuthority != address(0), InvalidArgumentErrors.ZeroAddress()); + require(_newImplementationAuthority != address(0), ZeroAddress()); require( (ITREXImplementationAuthority(_newImplementationAuthority)).getTokenImplementation() != address(0) && (ITREXImplementationAuthority(_newImplementationAuthority)).getCTRImplementation() != address(0) @@ -86,7 +89,7 @@ abstract contract AbstractProxy is IProxy, Initializable { && (ITREXImplementationAuthority(_newImplementationAuthority)).getIRSImplementation() != address(0) && (ITREXImplementationAuthority(_newImplementationAuthority)).getMCImplementation() != address(0) && (ITREXImplementationAuthority(_newImplementationAuthority)).getTIRImplementation() != address(0) - , InvalidArgumentErrors.InvalidImplementationAuthority()); + , InvalidImplementationAuthority()); _storeImplementationAuthority(_newImplementationAuthority); emit ImplementationAuthoritySet(_newImplementationAuthority); } diff --git a/contracts/proxy/ClaimTopicsRegistryProxy.sol b/contracts/proxy/ClaimTopicsRegistryProxy.sol index 2b4b517c..25b29c52 100644 --- a/contracts/proxy/ClaimTopicsRegistryProxy.sol +++ b/contracts/proxy/ClaimTopicsRegistryProxy.sol @@ -63,13 +63,13 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; -import "../libraries/errors/InvalidArgumentErrors.sol"; -import "../libraries/errors/CommonErrors.sol"; +import "../errors/InvalidArgumentErrors.sol"; +import "../errors/CommonErrors.sol"; contract ClaimTopicsRegistryProxy is AbstractProxy { constructor(address implementationAuthority) { - require(implementationAuthority != address(0), InvalidArgumentErrors.ZeroAddress()); + require(implementationAuthority != address(0), ZeroAddress()); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); @@ -77,7 +77,7 @@ contract ClaimTopicsRegistryProxy is AbstractProxy { // solhint-disable-next-line avoid-low-level-calls (bool success, ) = logic.delegatecall(abi.encodeWithSignature("init()")); - require(success, CommonErrors.InitializationFailed()); + require(success, InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/IdentityRegistryProxy.sol b/contracts/proxy/IdentityRegistryProxy.sol index 7e8086c6..301de9ea 100644 --- a/contracts/proxy/IdentityRegistryProxy.sol +++ b/contracts/proxy/IdentityRegistryProxy.sol @@ -63,7 +63,7 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; -import "../libraries/errors/CommonErrors.sol"; +import "../errors/CommonErrors.sol"; contract IdentityRegistryProxy is AbstractProxy { @@ -78,7 +78,7 @@ contract IdentityRegistryProxy is AbstractProxy { && _trustedIssuersRegistry != address(0) && _claimTopicsRegistry != address(0) && _identityStorage != address(0) - , InvalidArgumentErrors.ZeroAddress()); + , ZeroAddress()); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); @@ -91,7 +91,7 @@ contract IdentityRegistryProxy is AbstractProxy { _trustedIssuersRegistry, _claimTopicsRegistry, _identityStorage)); - require(success, CommonErrors.InitializationFailed()); + require(success, InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/IdentityRegistryStorageProxy.sol b/contracts/proxy/IdentityRegistryStorageProxy.sol index 277bb1cb..17bbc028 100644 --- a/contracts/proxy/IdentityRegistryStorageProxy.sol +++ b/contracts/proxy/IdentityRegistryStorageProxy.sol @@ -63,12 +63,12 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; -import "../libraries/errors/CommonErrors.sol"; +import "../errors/CommonErrors.sol"; contract IdentityRegistryStorageProxy is AbstractProxy { constructor(address implementationAuthority) { - require(implementationAuthority != address(0), InvalidArgumentErrors.ZeroAddress()); + require(implementationAuthority != address(0), ZeroAddress()); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); @@ -76,7 +76,7 @@ contract IdentityRegistryStorageProxy is AbstractProxy { // solhint-disable-next-line avoid-low-level-calls (bool success, ) = logic.delegatecall(abi.encodeWithSignature("init()")); - require(success, CommonErrors.InitializationFailed()); + require(success, InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/ModularComplianceProxy.sol b/contracts/proxy/ModularComplianceProxy.sol index 1814d28c..973b72d2 100644 --- a/contracts/proxy/ModularComplianceProxy.sol +++ b/contracts/proxy/ModularComplianceProxy.sol @@ -63,14 +63,14 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; -import "../libraries/errors/CommonErrors.sol"; -import "../libraries/errors/InvalidArgumentErrors.sol"; +import "../errors/CommonErrors.sol"; +import "../errors/InvalidArgumentErrors.sol"; contract ModularComplianceProxy is AbstractProxy { constructor(address implementationAuthority) { - require(implementationAuthority != address(0), InvalidArgumentErrors.ZeroAddress()); + require(implementationAuthority != address(0), ZeroAddress()); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); @@ -78,7 +78,7 @@ contract ModularComplianceProxy is AbstractProxy { // solhint-disable-next-line avoid-low-level-calls (bool success, ) = logic.delegatecall(abi.encodeWithSignature("init()")); - require(success, CommonErrors.InitializationFailed()); + require(success, InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/TokenProxy.sol b/contracts/proxy/TokenProxy.sol index 3dcbb92a..30897cdc 100644 --- a/contracts/proxy/TokenProxy.sol +++ b/contracts/proxy/TokenProxy.sol @@ -63,8 +63,8 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; -import "../libraries/errors/InvalidArgumentErrors.sol"; -import "../libraries/errors/CommonErrors.sol"; +import "../errors/InvalidArgumentErrors.sol"; +import "../errors/CommonErrors.sol"; contract TokenProxy is AbstractProxy { @@ -82,12 +82,12 @@ contract TokenProxy is AbstractProxy { implementationAuthority != address(0) && _identityRegistry != address(0) && _compliance != address(0) - , InvalidArgumentErrors.ZeroAddress()); + , ZeroAddress()); require( keccak256(abi.encode(_name)) != keccak256(abi.encode("")) && keccak256(abi.encode(_symbol)) != keccak256(abi.encode("")) - , InvalidArgumentErrors.EmptyString()); - require(0 <= _decimals && _decimals <= 18, InvalidArgumentErrors.DecimalsBetween0And18()); + , EmptyString()); + require(0 <= _decimals && _decimals <= 18, DecimalsOutOfRange(_decimals)); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); @@ -105,7 +105,7 @@ contract TokenProxy is AbstractProxy { _onchainID ) ); - require(success, CommonErrors.InitializationFailed()); + require(success, InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/TrustedIssuersRegistryProxy.sol b/contracts/proxy/TrustedIssuersRegistryProxy.sol index 542c6919..634a8888 100644 --- a/contracts/proxy/TrustedIssuersRegistryProxy.sol +++ b/contracts/proxy/TrustedIssuersRegistryProxy.sol @@ -64,14 +64,14 @@ pragma solidity 0.8.26; import "./AbstractProxy.sol"; -import "../libraries/errors/InvalidArgumentErrors.sol"; -import "../libraries/errors/CommonErrors.sol"; +import "../errors/InvalidArgumentErrors.sol"; +import "../errors/CommonErrors.sol"; contract TrustedIssuersRegistryProxy is AbstractProxy { constructor(address implementationAuthority) { - require(implementationAuthority != address(0), InvalidArgumentErrors.ZeroAddress()); + require(implementationAuthority != address(0), ZeroAddress()); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); @@ -79,7 +79,7 @@ contract TrustedIssuersRegistryProxy is AbstractProxy { // solhint-disable-next-line avoid-low-level-calls (bool success, ) = logic.delegatecall(abi.encodeWithSignature("init()")); - require(success, CommonErrors.InitializationFailed()); + require(success, InitializationFailed()); } // solhint-disable-next-line no-complex-fallback diff --git a/contracts/proxy/authority/TREXImplementationAuthority.sol b/contracts/proxy/authority/TREXImplementationAuthority.sol index 088e4d53..c3df54cc 100644 --- a/contracts/proxy/authority/TREXImplementationAuthority.sol +++ b/contracts/proxy/authority/TREXImplementationAuthority.sol @@ -68,7 +68,38 @@ import "../../token/IToken.sol"; import "../interface/IProxy.sol"; import "../../factory/ITREXFactory.sol"; import "./IIAFactory.sol"; -import "../../libraries/errors/InvalidArgumentErrors.sol"; +import "../../errors/CommonErrors.sol"; +import "../../errors/InvalidArgumentErrors.sol"; + +/// Errors + +/// @dev Thrown when caller is not the owner of all impacted contracts. +error CallerNotOwnerOfAllImpactedContracts(); + +/// @dev Thrown when called on reference contract. +error CannotCallOnReferenceContract(); + +/// @dev Thrown when new implementation authority is not a reference contract. +error NewIAIsNotAReferenceContract(); + +/// @dev Thrown when version doesn't exist. +error NonExistingVersion(); + +/// @dev Thrown when called by other than reference contract +error OnlyReferenceContractCanCall(); + +/// @dev Thrown when version is already fetched. +error VersionAlreadyFetched(); + +/// @dev Thrown when version already exists. +error VersionAlreadyExists(); + +/// @dev Thrown when version is already in use. +error VersionAlreadyInUse(); + +/// @dev Thrown when version of new implementation authority is not the same as the current implementation authority version. +error VersionOfNewIAMustBeTheSameAsCurrentIA(); + contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { @@ -89,32 +120,6 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { /// address of factory for TREXImplementationAuthority contracts address private _iaFactory; - /// Errors - - error CallerNotOwnerOfAllImpactedContracts(); - - error CannotCallOnReferenceContract(); - - error InvalidIA(); - - error NewIAIsNotAReferenceContract(); - - error NonExistingVersion(); - - error OnlyReferenceContractCanAddVersion(); - - error OnlyReferenceContractCanCall(); - - error OnlyReferenceContractCanDeployNewIA(); - - error VersionAlreadyFetched(); - - error VersionAlreadyExists(); - - error VersionAlreadyInUse(); - - error VersionOfNewIAMustBeTheSameAsCurrentIA(); - /// functions /** @@ -185,8 +190,8 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { */ // solhint-disable-next-line code-complexity, function-max-lines function changeImplementationAuthority(address _token, address _newImplementationAuthority) external override { - require(_token != address(0), InvalidArgumentErrors.ZeroAddress()); - require(_newImplementationAuthority != address(0) || isReferenceContract(), OnlyReferenceContractCanDeployNewIA()); + require(_token != address(0), ZeroAddress()); + require(_newImplementationAuthority != address(0) || isReferenceContract(), OnlyReferenceContractCanCall()); address _ir = address(IToken(_token).identityRegistry()); address _mc = address(IToken(_token).compliance()); @@ -219,7 +224,7 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { require( IIAFactory(_iaFactory).deployedByFactory(_newImplementationAuthority) || _newImplementationAuthority == getReferenceContract(), - InvalidIA()); + InvalidImplementationAuthority()); } IProxy(_token).setImplementationAuthority(_newImplementationAuthority); @@ -301,7 +306,7 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { * @dev See {ITREXImplementationAuthority-addTREXVersion}. */ function addTREXVersion(Version calldata _version, TREXContracts calldata _trex) public override onlyOwner { - require(isReferenceContract(), OnlyReferenceContractCanAddVersion()); + require(isReferenceContract(), OnlyReferenceContractCanCall()); require(_contracts[_versionToBytes(_version)].tokenImplementation == address(0), VersionAlreadyExists()); require( @@ -311,7 +316,7 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { && _trex.mcImplementation != address(0) && _trex.tirImplementation != address(0) && _trex.tokenImplementation != address(0) - , InvalidArgumentErrors.ZeroAddress()); + , ZeroAddress()); _contracts[_versionToBytes(_version)] = _trex; emit TREXVersionAdded(_version, _trex); diff --git a/contracts/registry/implementation/ClaimTopicsRegistry.sol b/contracts/registry/implementation/ClaimTopicsRegistry.sol index 42e3df2a..2e92295d 100644 --- a/contracts/registry/implementation/ClaimTopicsRegistry.sol +++ b/contracts/registry/implementation/ClaimTopicsRegistry.sol @@ -66,14 +66,17 @@ import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../storage/CTRStorage.sol"; import "../interface/IClaimTopicsRegistry.sol"; -contract ClaimTopicsRegistry is IClaimTopicsRegistry, OwnableUpgradeable, CTRStorage { +/// Errors - /// Errors +/// @dev Thrown when maximum topic number is reached. +/// @param _max maximum numlber of topics. +error MaxTopicsReached(uint256 _max); - error CannotRequireMoreThan15Topics(); +/// @dev Thrown whern claim topic already exists. +error ClaimTopicAlreadyExists(); - error ClaimTopicAlreadyExists(); - + +contract ClaimTopicsRegistry is IClaimTopicsRegistry, OwnableUpgradeable, CTRStorage { function init() external initializer { __Ownable_init(); @@ -84,7 +87,7 @@ contract ClaimTopicsRegistry is IClaimTopicsRegistry, OwnableUpgradeable, CTRSto */ function addClaimTopic(uint256 _claimTopic) external override onlyOwner { uint256 length = _claimTopics.length; - require(length < 15, CannotRequireMoreThan15Topics()); + require(length < 15, MaxTopicsReached(15)); for (uint256 i = 0; i < length; i++) { require(_claimTopics[i] != _claimTopic, ClaimTopicAlreadyExists()); } diff --git a/contracts/registry/implementation/IdentityRegistry.sol b/contracts/registry/implementation/IdentityRegistry.sol index e9b84e8b..363e0825 100644 --- a/contracts/registry/implementation/IdentityRegistry.sol +++ b/contracts/registry/implementation/IdentityRegistry.sol @@ -71,7 +71,7 @@ import "../interface/IIdentityRegistry.sol"; import "../../roles/AgentRoleUpgradeable.sol"; import "../interface/IIdentityRegistryStorage.sol"; import "../storage/IRStorage.sol"; -import "../../libraries/errors/InvalidArgumentErrors.sol"; +import "../../errors/InvalidArgumentErrors.sol"; contract IdentityRegistry is IIdentityRegistry, AgentRoleUpgradeable, IRStorage { @@ -94,7 +94,7 @@ contract IdentityRegistry is IIdentityRegistry, AgentRoleUpgradeable, IRStorage _trustedIssuersRegistry != address(0) && _claimTopicsRegistry != address(0) && _identityStorage != address(0) - , InvalidArgumentErrors.ZeroAddress()); + , ZeroAddress()); _tokenTopicsRegistry = IClaimTopicsRegistry(_claimTopicsRegistry); _tokenIssuersRegistry = ITrustedIssuersRegistry(_trustedIssuersRegistry); _tokenIdentityStorage = IIdentityRegistryStorage(_identityStorage); diff --git a/contracts/registry/implementation/IdentityRegistryStorage.sol b/contracts/registry/implementation/IdentityRegistryStorage.sol index 387c0470..3dffdb42 100644 --- a/contracts/registry/implementation/IdentityRegistryStorage.sol +++ b/contracts/registry/implementation/IdentityRegistryStorage.sol @@ -67,20 +67,25 @@ import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; import "../../roles/AgentRoleUpgradeable.sol"; import "../interface/IIdentityRegistryStorage.sol"; import "../storage/IRSStorage.sol"; -import "../../libraries/errors/InvalidArgumentErrors.sol"; +import "../../errors/InvalidArgumentErrors.sol"; -contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeable, IRSStorage { +/// Errors - /// Errors +/// @dev Thrown when address is already stored +error AddressAlreadyStored(); - error AddressAlreadyStored(); +/// @dev Thrown when address is not yet stored. +error AddressNotYetStored(); - error AddressNotYetStored(); +/// @dev Thrown when identity registry is not stored. +error IdentityRegistryNotStored(); - error IdentityRegistryNotStored(); +/// @dev Thrown when maximum numbe of identity registry by identity registry storage is reached. +/// @param _max miximum number of IR by IRS. +error MaxIRByIRSReached(uint256 _max); - error CannotBindMoreThan300IRTo1IRS(); +contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeable, IRSStorage { function init() external initializer { __Ownable_init(); @@ -97,7 +102,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab require( _userAddress != address(0) && address(_identity) != address(0) - , InvalidArgumentErrors.ZeroAddress()); + , ZeroAddress()); require(address(_identities[_userAddress].identityContract) == address(0), AddressAlreadyStored()); _identities[_userAddress].identityContract = _identity; _identities[_userAddress].investorCountry = _country; @@ -111,7 +116,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab require( _userAddress != address(0) && address(_identity) != address(0) - , InvalidArgumentErrors.ZeroAddress()); + , ZeroAddress()); require(address(_identities[_userAddress].identityContract) != address(0), AddressNotYetStored()); IIdentity oldIdentity = _identities[_userAddress].identityContract; _identities[_userAddress].identityContract = _identity; @@ -122,7 +127,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab * @dev See {IIdentityRegistryStorage-modifyStoredInvestorCountry}. */ function modifyStoredInvestorCountry(address _userAddress, uint16 _country) external override onlyAgent { - require(_userAddress != address(0), InvalidArgumentErrors.ZeroAddress()); + require(_userAddress != address(0), ZeroAddress()); require(address(_identities[_userAddress].identityContract) != address(0), AddressNotYetStored()); _identities[_userAddress].investorCountry = _country; emit CountryModified(_userAddress, _country); @@ -132,7 +137,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab * @dev See {IIdentityRegistryStorage-removeIdentityFromStorage}. */ function removeIdentityFromStorage(address _userAddress) external override onlyAgent { - require(_userAddress != address(0), InvalidArgumentErrors.ZeroAddress()); + require(_userAddress != address(0), ZeroAddress()); require(address(_identities[_userAddress].identityContract) != address(0), AddressNotYetStored()); IIdentity oldIdentity = _identities[_userAddress].identityContract; delete _identities[_userAddress]; @@ -143,8 +148,8 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab * @dev See {IIdentityRegistryStorage-bindIdentityRegistry}. */ function bindIdentityRegistry(address _identityRegistry) external override { - require(_identityRegistry != address(0), InvalidArgumentErrors.ZeroAddress()); - require(_identityRegistries.length < 300, CannotBindMoreThan300IRTo1IRS()); + require(_identityRegistry != address(0), ZeroAddress()); + require(_identityRegistries.length < 300, MaxIRByIRSReached(300)); addAgent(_identityRegistry); _identityRegistries.push(_identityRegistry); emit IdentityRegistryBound(_identityRegistry); @@ -154,7 +159,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab * @dev See {IIdentityRegistryStorage-unbindIdentityRegistry}. */ function unbindIdentityRegistry(address _identityRegistry) external override { - require(_identityRegistry != address(0), InvalidArgumentErrors.ZeroAddress()); + require(_identityRegistry != address(0), ZeroAddress()); require(_identityRegistries.length > 0, IdentityRegistryNotStored()); uint256 length = _identityRegistries.length; for (uint256 i = 0; i < length; i++) { diff --git a/contracts/registry/implementation/TrustedIssuersRegistry.sol b/contracts/registry/implementation/TrustedIssuersRegistry.sol index ae3afe74..bd2e0a93 100644 --- a/contracts/registry/implementation/TrustedIssuersRegistry.sol +++ b/contracts/registry/implementation/TrustedIssuersRegistry.sol @@ -67,25 +67,35 @@ import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../interface/ITrustedIssuersRegistry.sol"; import "../storage/TIRStorage.sol"; -import "../../libraries/errors/InvalidArgumentErrors.sol"; +import "../../errors/InvalidArgumentErrors.sol"; -contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, TIRStorage { +/// Errors + +/// @dev Thrown when claim topics is empty. +error ClaimTopicsCannotBeEmpty(); - /// Errors +/// @dev Thrown when maximum number of claim topics is reached. +/// @param _max maximum number of claim topics. +error MaxClaimTopcisReached(uint256 _max); - error ClaimTopicsCannotBeEmpty(); +/// @dev Thrown when the maximum number of trusted issuers is reached. +/// @param _max maximum number of trusted issuers. +error MaxTrustedIssuersReached(uint256 _max); - error CannotHaveMoreThan15ClaimTopics(); +/// @dev Thrown when called by other than a trusted issuer. +error NotATrustedIssuer(); - error CannotHaveMoreThan50TrustedIssuers(); +/// @dev Thrown when trusted claim topics is empty. +error TrustedClaimTopicsCannotBeEmpty(); - error NotATrustedIssuer(); +/// @dev Thrown when trusted issuer already exists. +error TrustedIssuerAlreadyExists(); - error TrustedClaimTopicsCannotBeEmpty(); +/// @dev Thrown when trusted issuer doesn"t exist. +error TrustedIssuerDoesNotExist(); - error TrustedIssuerAlreadyExists(); - error TrustedIssuerDoesntExist(); +contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, TIRStorage { /// Functions @@ -97,11 +107,11 @@ contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, * @dev See {ITrustedIssuersRegistry-addTrustedIssuer}. */ function addTrustedIssuer(IClaimIssuer _trustedIssuer, uint256[] calldata _claimTopics) external override onlyOwner { - require(address(_trustedIssuer) != address(0), InvalidArgumentErrors.ZeroAddress()); + require(address(_trustedIssuer) != address(0), ZeroAddress()); require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length == 0, TrustedIssuerAlreadyExists()); require(_claimTopics.length > 0, TrustedClaimTopicsCannotBeEmpty()); - require(_claimTopics.length <= 15, CannotHaveMoreThan15ClaimTopics()); - require(_trustedIssuers.length < 50, CannotHaveMoreThan50TrustedIssuers()); + require(_claimTopics.length <= 15, MaxClaimTopcisReached(15)); + require(_trustedIssuers.length < 50, MaxTrustedIssuersReached(50)); _trustedIssuers.push(_trustedIssuer); _trustedIssuerClaimTopics[address(_trustedIssuer)] = _claimTopics; for (uint256 i = 0; i < _claimTopics.length; i++) { @@ -114,7 +124,7 @@ contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, * @dev See {ITrustedIssuersRegistry-removeTrustedIssuer}. */ function removeTrustedIssuer(IClaimIssuer _trustedIssuer) external override onlyOwner { - require(address(_trustedIssuer) != address(0), InvalidArgumentErrors.ZeroAddress()); + require(address(_trustedIssuer) != address(0), ZeroAddress()); require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length != 0, NotATrustedIssuer()); uint256 length = _trustedIssuers.length; for (uint256 i = 0; i < length; i++) { @@ -147,9 +157,9 @@ contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, * @dev See {ITrustedIssuersRegistry-updateIssuerClaimTopics}. */ function updateIssuerClaimTopics(IClaimIssuer _trustedIssuer, uint256[] calldata _claimTopics) external override onlyOwner { - require(address(_trustedIssuer) != address(0), InvalidArgumentErrors.ZeroAddress()); + require(address(_trustedIssuer) != address(0), ZeroAddress()); require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length != 0, NotATrustedIssuer()); - require(_claimTopics.length <= 15, CannotHaveMoreThan15ClaimTopics()); + require(_claimTopics.length <= 15, MaxClaimTopcisReached(15)); require(_claimTopics.length > 0, ClaimTopicsCannotBeEmpty()); for (uint256 i = 0; i < _trustedIssuerClaimTopics[address(_trustedIssuer)].length; i++) { @@ -199,7 +209,7 @@ contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, * @dev See {ITrustedIssuersRegistry-getTrustedIssuerClaimTopics}. */ function getTrustedIssuerClaimTopics(IClaimIssuer _trustedIssuer) external view override returns (uint256[] memory) { - require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length != 0, TrustedIssuerDoesntExist()); + require(_trustedIssuerClaimTopics[address(_trustedIssuer)].length != 0, TrustedIssuerDoesNotExist()); return _trustedIssuerClaimTopics[address(_trustedIssuer)]; } diff --git a/contracts/roles/AgentRole.sol b/contracts/roles/AgentRole.sol index 48cd6e76..def7bfe0 100644 --- a/contracts/roles/AgentRole.sol +++ b/contracts/roles/AgentRole.sol @@ -66,8 +66,8 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts/access/Ownable.sol"; import "./Roles.sol"; -import "../libraries/errors/InvalidArgumentErrors.sol"; -import "../libraries/errors/RoleErrors.sol"; +import "../errors/InvalidArgumentErrors.sol"; +import "../errors/RoleErrors.sol"; contract AgentRole is Ownable { using Roles for Roles.Role; @@ -78,18 +78,18 @@ contract AgentRole is Ownable { event AgentRemoved(address indexed _agent); modifier onlyAgent() { - require(isAgent(msg.sender), RoleErrors.CallerDoesNotHaveAgentRole()); + require(isAgent(msg.sender), CallerDoesNotHaveAgentRole()); _; } function addAgent(address _agent) public onlyOwner { - require(_agent != address(0), InvalidArgumentErrors.ZeroAddress()); + require(_agent != address(0), ZeroAddress()); _agents.add(_agent); emit AgentAdded(_agent); } function removeAgent(address _agent) public onlyOwner { - require(_agent != address(0), InvalidArgumentErrors.ZeroAddress()); + require(_agent != address(0), ZeroAddress()); _agents.remove(_agent); emit AgentRemoved(_agent); } diff --git a/contracts/roles/AgentRoleUpgradeable.sol b/contracts/roles/AgentRoleUpgradeable.sol index f0484178..46c419bc 100644 --- a/contracts/roles/AgentRoleUpgradeable.sol +++ b/contracts/roles/AgentRoleUpgradeable.sol @@ -66,8 +66,8 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "./Roles.sol"; -import "../libraries/errors/InvalidArgumentErrors.sol"; -import "../libraries/errors/RoleErrors.sol"; +import "../errors/InvalidArgumentErrors.sol"; +import "../errors/RoleErrors.sol"; contract AgentRoleUpgradeable is OwnableUpgradeable { using Roles for Roles.Role; @@ -78,18 +78,18 @@ contract AgentRoleUpgradeable is OwnableUpgradeable { event AgentRemoved(address indexed _agent); modifier onlyAgent() { - require(isAgent(msg.sender), RoleErrors.CallerDoesNotHaveAgentRole()); + require(isAgent(msg.sender), CallerDoesNotHaveAgentRole()); _; } function addAgent(address _agent) public onlyOwner { - require(_agent != address(0), InvalidArgumentErrors.ZeroAddress()); + require(_agent != address(0), ZeroAddress()); _agents.add(_agent); emit AgentAdded(_agent); } function removeAgent(address _agent) public onlyOwner { - require(_agent != address(0), InvalidArgumentErrors.ZeroAddress()); + require(_agent != address(0), ZeroAddress()); _agents.remove(_agent); emit AgentRemoved(_agent); } diff --git a/contracts/roles/Roles.sol b/contracts/roles/Roles.sol index da63a02f..5bfd7fb6 100644 --- a/contracts/roles/Roles.sol +++ b/contracts/roles/Roles.sol @@ -63,8 +63,8 @@ pragma solidity 0.8.26; -import "../libraries/errors/InvalidArgumentErrors.sol"; -import "../libraries/errors/RoleErrors.sol"; +import "../errors/InvalidArgumentErrors.sol"; +import "../errors/RoleErrors.sol"; /** * @title Roles @@ -79,7 +79,7 @@ library Roles { * @dev Give an account access to this role. */ function add(Role storage role, address account) internal { - require(!has(role, account), RoleErrors.AccountAlreadyHasRole()); + require(!has(role, account), AccountAlreadyHasRole()); role.bearer[account] = true; } @@ -87,7 +87,7 @@ library Roles { * @dev Remove an account's access to this role. */ function remove(Role storage role, address account) internal { - require(has(role, account), RoleErrors.AccountDoesNotHaveRole()); + require(has(role, account), AccountDoesNotHaveRole()); role.bearer[account] = false; } @@ -96,7 +96,7 @@ library Roles { * @return bool */ function has(Role storage role, address account) internal view returns (bool) { - require(account != address(0), InvalidArgumentErrors.ZeroAddress()); + require(account != address(0), ZeroAddress()); return role.bearer[account]; } } diff --git a/contracts/roles/permissioning/agent/AgentManager.sol b/contracts/roles/permissioning/agent/AgentManager.sol index ac3b3d74..2ca84a8e 100644 --- a/contracts/roles/permissioning/agent/AgentManager.sol +++ b/contracts/roles/permissioning/agent/AgentManager.sol @@ -68,7 +68,7 @@ import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; import "../../../token/IToken.sol"; import "../../../registry/interface/IIdentityRegistry.sol"; import "./AgentRoles.sol"; -import "../../../libraries/errors/RoleErrors.sol"; +import "../../../errors/RoleErrors.sol"; contract AgentManager is AgentRoles { /// @dev the token managed by this AgentManager contract @@ -95,7 +95,7 @@ contract AgentManager is AgentRoles { require( isTransferManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleErrors.SenderIsNotTransferManager() + SenderIsNotTransferManager() ); token.forcedTransfer(_from, _to, _amount); } @@ -117,7 +117,7 @@ contract AgentManager is AgentRoles { require( isTransferManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleErrors.SenderIsNotTransferManager() + SenderIsNotTransferManager() ); token.batchForcedTransfer(_fromList, _toList, _amounts); } @@ -134,7 +134,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleErrors.SenderIsNotFreezer()); + , SenderIsNotFreezer()); token.pause(); } @@ -150,7 +150,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleErrors.SenderIsNotFreezer()); + , SenderIsNotFreezer()); token.unpause(); } @@ -170,7 +170,7 @@ contract AgentManager is AgentRoles { require( isSupplyModifier(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleErrors.SenderIsNotSupplyModifier() + SenderIsNotSupplyModifier() ); token.mint(_to, _amount); } @@ -191,7 +191,7 @@ contract AgentManager is AgentRoles { require( isSupplyModifier(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleErrors.SenderIsNotSupplyModifier() + SenderIsNotSupplyModifier() ); token.batchMint(_toList, _amounts); } @@ -213,7 +213,7 @@ contract AgentManager is AgentRoles { isSupplyModifier( address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleErrors.SenderIsNotSupplyModifier() + , SenderIsNotSupplyModifier() ); token.burn(_userAddress, _amount); } @@ -234,7 +234,7 @@ contract AgentManager is AgentRoles { require( isSupplyModifier(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleErrors.SenderIsNotSupplyModifier() + , SenderIsNotSupplyModifier() ); token.batchBurn(_userAddresses, _amounts); } @@ -255,7 +255,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleErrors.SenderIsNotFreezer()); + , SenderIsNotFreezer()); token.setAddressFrozen(_userAddress, _freeze); } @@ -275,7 +275,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleErrors.SenderIsNotFreezer()); + , SenderIsNotFreezer()); token.batchSetAddressFrozen(_userAddresses, _freeze); } @@ -295,7 +295,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleErrors.SenderIsNotFreezer()); + , SenderIsNotFreezer()); token.freezePartialTokens(_userAddress, _amount); } @@ -315,7 +315,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleErrors.SenderIsNotFreezer()); + , SenderIsNotFreezer()); token.batchFreezePartialTokens(_userAddresses, _amounts); } @@ -335,7 +335,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleErrors.SenderIsNotFreezer()); + , SenderIsNotFreezer()); token.unfreezePartialTokens(_userAddress, _amount); } @@ -355,7 +355,7 @@ contract AgentManager is AgentRoles { require( isFreezer(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleErrors.SenderIsNotFreezer()); + , SenderIsNotFreezer()); token.batchUnfreezePartialTokens(_userAddresses, _amounts); } @@ -376,7 +376,7 @@ contract AgentManager is AgentRoles { require( isRecoveryAgent(address(_managerOnchainID)) && _managerOnchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleErrors.SenderIsNotRecoveryAgent() + , SenderIsNotRecoveryAgent() ); token.recoveryAddress(_lostWallet, _newWallet, _onchainID); } @@ -398,7 +398,7 @@ contract AgentManager is AgentRoles { require( isWhiteListManager(address(_managerOnchainID)) && _managerOnchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleErrors.SenderIsNotWhiteListManager() + , SenderIsNotWhiteListManager() ); token.identityRegistry().registerIdentity(_userAddress, _onchainID, _country); } @@ -419,7 +419,7 @@ contract AgentManager is AgentRoles { require( isWhiteListManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleErrors.SenderIsNotWhiteListManager() + , SenderIsNotWhiteListManager() ); token.identityRegistry().updateIdentity(_userAddress, _identity); } @@ -440,7 +440,7 @@ contract AgentManager is AgentRoles { require( isWhiteListManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleErrors.SenderIsNotWhiteListManager() + , SenderIsNotWhiteListManager() ); token.identityRegistry().updateCountry(_userAddress, _country); } @@ -457,7 +457,7 @@ contract AgentManager is AgentRoles { require( isWhiteListManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2) - , RoleErrors.SenderIsNotWhiteListManager() + , SenderIsNotWhiteListManager() ); token.identityRegistry().deleteIdentity(_userAddress); } diff --git a/contracts/roles/permissioning/agent/AgentRoles.sol b/contracts/roles/permissioning/agent/AgentRoles.sol index 6acfc28b..afd16004 100644 --- a/contracts/roles/permissioning/agent/AgentRoles.sol +++ b/contracts/roles/permissioning/agent/AgentRoles.sol @@ -66,7 +66,7 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts/access/Ownable.sol"; import "../../Roles.sol"; -import "../../../libraries/errors/RoleErrors.sol"; +import "../../../errors/RoleErrors.sol"; contract AgentRoles is Ownable { using Roles for Roles.Role; @@ -89,7 +89,7 @@ contract AgentRoles is Ownable { /// modifiers modifier onlyAdmin() { - require(owner() == msg.sender || isAgentAdmin(_msgSender()), RoleErrors.SenderIsNotAdmin()); + require(owner() == msg.sender || isAgentAdmin(_msgSender()), SenderIsNotAdmin()); _; } diff --git a/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol b/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol index 1f9e5524..8b9b17c7 100644 --- a/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol +++ b/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol @@ -66,7 +66,7 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../../Roles.sol"; -import "../../../libraries/errors/RoleErrors.sol"; +import "../../../errors/RoleErrors.sol"; contract AgentRolesUpgradeable is OwnableUpgradeable @@ -91,7 +91,7 @@ contract AgentRolesUpgradeable is OwnableUpgradeable /// modifiers modifier onlyAdmin() { - require(owner() == msg.sender || isAgentAdmin(_msgSender()), RoleErrors.SenderIsNotAdmin()); + require(owner() == msg.sender || isAgentAdmin(_msgSender()), SenderIsNotAdmin()); _; } diff --git a/contracts/roles/permissioning/owner/OwnerManager.sol b/contracts/roles/permissioning/owner/OwnerManager.sol index 70c8cf8a..2b4af567 100644 --- a/contracts/roles/permissioning/owner/OwnerManager.sol +++ b/contracts/roles/permissioning/owner/OwnerManager.sol @@ -72,7 +72,7 @@ import "./OwnerRoles.sol"; import "../../AgentRole.sol"; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; -import "../../../libraries/errors/RoleErrors.sol"; +import "../../../errors/RoleErrors.sol"; contract OwnerManager is OwnerRoles { /// @dev the token that is managed by this OwnerManager Contract @@ -105,7 +105,7 @@ contract OwnerManager is OwnerRoles { function callSetIdentityRegistry(address _identityRegistry, IIdentity _onchainID) external { require( isRegistryAddressSetter(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleErrors.SenderIsNotRegistryAddressSetter() + SenderIsNotRegistryAddressSetter() ); token.setIdentityRegistry(_identityRegistry); } @@ -121,7 +121,7 @@ contract OwnerManager is OwnerRoles { function callSetCompliance(address _compliance, IIdentity _onchainID) external { require( isComplianceSetter(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleErrors.SenderIsNotComplianceSetter() + SenderIsNotComplianceSetter() ); token.setCompliance(_compliance); } @@ -136,7 +136,7 @@ contract OwnerManager is OwnerRoles { function callComplianceFunction(bytes calldata callData, IIdentity _onchainID) external { require( isComplianceManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleErrors.SenderIsNotComplianceManager() + SenderIsNotComplianceManager() ); address target = address(token.compliance()); @@ -181,7 +181,7 @@ contract OwnerManager is OwnerRoles { function callSetTokenName(string calldata _name, IIdentity _onchainID) external { require( isTokenInfoManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleErrors.SenderIsNotTokenInformationManager() + SenderIsNotTokenInformationManager() ); token.setName(_name); } @@ -197,7 +197,7 @@ contract OwnerManager is OwnerRoles { function callSetTokenSymbol(string calldata _symbol, IIdentity _onchainID) external { require( isTokenInfoManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleErrors.SenderIsNotTokenInformationManager() + SenderIsNotTokenInformationManager() ); token.setSymbol(_symbol); } @@ -213,7 +213,7 @@ contract OwnerManager is OwnerRoles { function callSetTokenOnchainID(address _tokenOnchainID, IIdentity _onchainID) external { require( isTokenInfoManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleErrors.SenderIsNotTokenInformationManager() + SenderIsNotTokenInformationManager() ); token.setOnchainID(_tokenOnchainID); } @@ -229,7 +229,7 @@ contract OwnerManager is OwnerRoles { function callSetClaimTopicsRegistry(address _claimTopicsRegistry, IIdentity _onchainID) external { require( isRegistryAddressSetter(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleErrors.SenderIsNotRegistryAddressSetter() + SenderIsNotRegistryAddressSetter() ); token.identityRegistry().setClaimTopicsRegistry(_claimTopicsRegistry); } @@ -245,7 +245,7 @@ contract OwnerManager is OwnerRoles { function callSetTrustedIssuersRegistry(address _trustedIssuersRegistry, IIdentity _onchainID) external { require( isRegistryAddressSetter(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleErrors.SenderIsNotRegistryAddressSetter() + SenderIsNotRegistryAddressSetter() ); token.identityRegistry().setTrustedIssuersRegistry(_trustedIssuersRegistry); } @@ -265,7 +265,7 @@ contract OwnerManager is OwnerRoles { ) external { require( isIssuersRegistryManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleErrors.SenderIsNotIssuersRegistryManager() + SenderIsNotIssuersRegistryManager() ); token.identityRegistry().issuersRegistry().addTrustedIssuer(_trustedIssuer, _claimTopics); } @@ -281,7 +281,7 @@ contract OwnerManager is OwnerRoles { function callRemoveTrustedIssuer(IClaimIssuer _trustedIssuer, IIdentity _onchainID) external { require( isIssuersRegistryManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleErrors.SenderIsNotIssuersRegistryManager() + SenderIsNotIssuersRegistryManager() ); token.identityRegistry().issuersRegistry().removeTrustedIssuer(_trustedIssuer); } @@ -301,7 +301,7 @@ contract OwnerManager is OwnerRoles { ) external { require( isIssuersRegistryManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleErrors.SenderIsNotIssuersRegistryManager() + SenderIsNotIssuersRegistryManager() ); token.identityRegistry().issuersRegistry().updateIssuerClaimTopics(_trustedIssuer, _claimTopics); } @@ -317,7 +317,7 @@ contract OwnerManager is OwnerRoles { function callAddClaimTopic(uint256 _claimTopic, IIdentity _onchainID) external { require( isClaimRegistryManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleErrors.SenderIsNotClaimRegistryManager() + SenderIsNotClaimRegistryManager() ); token.identityRegistry().topicsRegistry().addClaimTopic(_claimTopic); } @@ -333,7 +333,7 @@ contract OwnerManager is OwnerRoles { function callRemoveClaimTopic(uint256 _claimTopic, IIdentity _onchainID) external { require( isClaimRegistryManager(address(_onchainID)) && _onchainID.keyHasPurpose(keccak256(abi.encode(msg.sender)), 2), - RoleErrors.SenderIsNotClaimRegistryManager() + SenderIsNotClaimRegistryManager() ); token.identityRegistry().topicsRegistry().removeClaimTopic(_claimTopic); } diff --git a/contracts/roles/permissioning/owner/OwnerRoles.sol b/contracts/roles/permissioning/owner/OwnerRoles.sol index 64cabbcc..f53d31da 100644 --- a/contracts/roles/permissioning/owner/OwnerRoles.sol +++ b/contracts/roles/permissioning/owner/OwnerRoles.sol @@ -66,7 +66,7 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts/access/Ownable.sol"; import "../../Roles.sol"; -import "../../../libraries/errors/RoleErrors.sol"; +import "../../../errors/RoleErrors.sol"; contract OwnerRoles is Ownable { using Roles for Roles.Role; @@ -89,7 +89,7 @@ contract OwnerRoles is Ownable { /// modifiers modifier onlyAdmin() { - require(owner() == msg.sender || isOwnerAdmin(_msgSender()), RoleErrors.SenderIsNotAdmin()); + require(owner() == msg.sender || isOwnerAdmin(_msgSender()), SenderIsNotAdmin()); _; } diff --git a/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol b/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol index e4e1e65d..237b5455 100644 --- a/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol +++ b/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol @@ -66,7 +66,7 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../../Roles.sol"; -import "../../../libraries/errors/RoleErrors.sol"; +import "../../../errors/RoleErrors.sol"; contract OwnerRolesUpgradeable is OwnableUpgradeable @@ -91,7 +91,7 @@ contract OwnerRolesUpgradeable is OwnableUpgradeable /// modifiers modifier onlyAdmin() { - require(owner() == msg.sender || isOwnerAdmin(_msgSender()), RoleErrors.SenderIsNotAdmin()); + require(owner() == msg.sender || isOwnerAdmin(_msgSender()), SenderIsNotAdmin()); _; } diff --git a/contracts/token/Token.sol b/contracts/token/Token.sol index cfd27c0d..96707654 100755 --- a/contracts/token/Token.sol +++ b/contracts/token/Token.sol @@ -67,44 +67,60 @@ import "./IToken.sol"; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; import "./TokenStorage.sol"; import "../roles/AgentRoleUpgradeable.sol"; -import "../libraries/errors/InvalidArgumentErrors.sol"; -import "../libraries/errors/CommonErrors.sol"; +import "../errors/InvalidArgumentErrors.sol"; +import "../errors/CommonErrors.sol"; -contract Token is IToken, AgentRoleUpgradeable, TokenStorage { +/// errors + +/// @dev Thrown when address is not an agent. +/// @param _agent address of agent. +error AddressNotAgent(address _agent); - /// errors +/// @dev Thrown when agent is not authorized. +/// @param _agent address of agent. +/// @param _reason authorisation label. +error AgentNotAuthorized(address _agent, string _reason); - error AddressNotAgent(address agent); +/// @dev Thrown when already initialized. +error AlreadyInitialized(); - error AgentNotAuthorized(address agent, string reason); +/// @dev Thrown when amount is above maximum amount. +/// @param _amount amount value. +/// @param _maxAmount maximum amount value. +error AmountAboveFrozenTokens(uint256 _amount, uint256 _maxAmount); - error AlreadyInitialized(); +/// @dev Thrown when wallet is frozen. +error FrozenWallet(); - error AmountAboveFrozenTokens(uint256 amount, uint256 maxAmount); +/// @dev Thrown when compliance is not followed. +error ComplianceNotFollowed(); - error FrozenWallet(); +/// @dev Thrown when thers is no token to recover. +error NoTokenToRecover(); - error ComplianceNotFollowed(); +/// @dev Thrown when recovery is not possible. +error RecoveryNotPossible(); - error NoTokenToRecover(); +/// @dev Thrown when transfer is not possible. +error TransferNotPossible(); - error RecoveryNotPossible(); +/// @dev Thrown when identity is not verified. +error UnverifiedIdentity(); - error TransferNotPossible(); - error UnverifiedIdentity(); +contract Token is IToken, AgentRoleUpgradeable, TokenStorage { /// modifiers /// @dev Modifier to make a function callable only when the contract is not paused. modifier whenNotPaused() { - require(!_tokenPaused, CommonErrors.EnforcedPause()); + require(!_tokenPaused, EnforcedPause()); _; } /// @dev Modifier to make a function callable only when the contract is paused. modifier whenPaused() { - require(_tokenPaused, CommonErrors.ExpectedPause()); + require(_tokenPaused, ExpectedPause()); _; } @@ -138,12 +154,12 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { require( _identityRegistry != address(0) && _compliance != address(0) - , InvalidArgumentErrors.ZeroAddress()); + , ZeroAddress()); require( keccak256(abi.encode(_name)) != keccak256(abi.encode("")) && keccak256(abi.encode(_symbol)) != keccak256(abi.encode("")) - , InvalidArgumentErrors.EmptyString()); - require(0 <= _decimals && _decimals <= 18, InvalidArgumentErrors.DecimalsBetween0And18()); + , EmptyString()); + require(0 <= _decimals && _decimals <= 18, DecimalsOutOfRange(_decimals)); __Ownable_init(); _tokenName = _name; _tokenSymbol = _symbol; @@ -183,7 +199,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-setName}. */ function setName(string calldata _name) external override onlyOwner { - require(keccak256(abi.encode(_name)) != keccak256(abi.encode("")), InvalidArgumentErrors.EmptyString()); + require(keccak256(abi.encode(_name)) != keccak256(abi.encode("")), EmptyString()); _tokenName = _name; emit UpdatedTokenInformation(_tokenName, _tokenSymbol, _tokenDecimals, _TOKEN_VERSION, _tokenOnchainID); } @@ -192,7 +208,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-setSymbol}. */ function setSymbol(string calldata _symbol) external override onlyOwner { - require(keccak256(abi.encode(_symbol)) != keccak256(abi.encode("")), InvalidArgumentErrors.EmptyString()); + require(keccak256(abi.encode(_symbol)) != keccak256(abi.encode("")), EmptyString()); _tokenSymbol = _symbol; emit UpdatedTokenInformation(_tokenName, _tokenSymbol, _tokenDecimals, _TOKEN_VERSION, _tokenOnchainID); } @@ -274,7 +290,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { require(!_frozen[_to] && !_frozen[_from], FrozenWallet()); uint256 balance = balanceOf(_from) - (_frozenTokens[_from]); - require(_amount <= balance, CommonErrors.ERC20InsufficientBalance(_from, balance, _amount)); + require(_amount <= balance, ERC20InsufficientBalance(_from, balance, _amount)); if (_tokenIdentityRegistry.isVerified(_to) && _tokenCompliance.canTransfer(_from, _to, _amount)) { _approve(_from, msg.sender, _allowances[_from][msg.sender] - (_amount)); _transfer(_from, _to, _amount); @@ -471,7 +487,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { function transfer(address _to, uint256 _amount) public override whenNotPaused returns (bool) { require(!_frozen[_to] && !_frozen[msg.sender], FrozenWallet()); uint256 balance = balanceOf(msg.sender) - _frozenTokens[msg.sender]; - require(_amount <= balance, CommonErrors.ERC20InsufficientBalance(msg.sender, balance, _amount)); + require(_amount <= balance, ERC20InsufficientBalance(msg.sender, balance, _amount)); if (_tokenIdentityRegistry.isVerified(_to) && _tokenCompliance.canTransfer(msg.sender, _to, _amount)) { _transfer(msg.sender, _to, _amount); _tokenCompliance.transferred(msg.sender, _to, _amount); @@ -492,7 +508,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { if(getAgentRestrictions(msg.sender).disableForceTransfer) { revert AgentNotAuthorized(msg.sender, "forceTransfer disabled"); } - require(balanceOf(_from) >= _amount, CommonErrors.ERC20InsufficientBalance(_from, balanceOf(_from), _amount)); + require(balanceOf(_from) >= _amount, ERC20InsufficientBalance(_from, balanceOf(_from), _amount)); uint256 freeBalance = balanceOf(_from) - (_frozenTokens[_from]); if (_amount > freeBalance) { uint256 tokensToUnfreeze = _amount - (freeBalance); @@ -524,7 +540,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { function burn(address _userAddress, uint256 _amount) public override onlyAgent { require(!getAgentRestrictions(msg.sender).disableBurn, AgentNotAuthorized(msg.sender, "burn disabled")); require(balanceOf(_userAddress) >= _amount, - CommonErrors.ERC20InsufficientBalance(_userAddress, balanceOf(_userAddress), _amount)); + ERC20InsufficientBalance(_userAddress, balanceOf(_userAddress), _amount)); uint256 freeBalance = balanceOf(_userAddress) - _frozenTokens[_userAddress]; if (_amount > freeBalance) { uint256 tokensToUnfreeze = _amount - (freeBalance); @@ -554,7 +570,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { AgentNotAuthorized(msg.sender, "partial freeze disabled")); uint256 balance = balanceOf(_userAddress); require(balance >= _frozenTokens[_userAddress] + _amount, - CommonErrors.ERC20InsufficientBalance(_userAddress, balance, _amount)); + ERC20InsufficientBalance(_userAddress, balance, _amount)); _frozenTokens[_userAddress] = _frozenTokens[_userAddress] + (_amount); emit TokensFrozen(_userAddress, _amount); } @@ -612,8 +628,8 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { address _to, uint256 _amount ) internal virtual { - require(_from != address(0), CommonErrors.ERC20InvalidSpender(_from)); - require(_to != address(0), CommonErrors.ERC20InvalidReceiver(_to)); + require(_from != address(0), ERC20InvalidSpender(_from)); + require(_to != address(0), ERC20InvalidReceiver(_to)); _beforeTokenTransfer(_from, _to, _amount); @@ -626,7 +642,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {ERC20-_mint}. */ function _mint(address _userAddress, uint256 _amount) internal virtual { - require(_userAddress != address(0), CommonErrors.ERC20InvalidReceiver(_userAddress)); + require(_userAddress != address(0), ERC20InvalidReceiver(_userAddress)); _beforeTokenTransfer(address(0), _userAddress, _amount); @@ -639,7 +655,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {ERC20-_burn}. */ function _burn(address _userAddress, uint256 _amount) internal virtual { - require(_userAddress != address(0), CommonErrors.ERC20InvalidSpender(_userAddress)); + require(_userAddress != address(0), ERC20InvalidSpender(_userAddress)); _beforeTokenTransfer(_userAddress, address(0), _amount); @@ -656,8 +672,8 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { address _spender, uint256 _amount ) internal virtual { - require(_owner != address(0), CommonErrors.ERC20InvalidSender(_owner)); - require(_spender != address(0), CommonErrors.ERC20InvalidSpender(_spender)); + require(_owner != address(0), ERC20InvalidSender(_owner)); + require(_spender != address(0), ERC20InvalidSpender(_spender)); _allowances[_owner][_spender] = _amount; emit Approval(_owner, _spender, _amount); diff --git a/test/authorities/trex-implementation-authority.test.ts b/test/authorities/trex-implementation-authority.test.ts index 2d388428..64462cbf 100644 --- a/test/authorities/trex-implementation-authority.test.ts +++ b/test/authorities/trex-implementation-authority.test.ts @@ -265,7 +265,7 @@ describe('TrexImplementationAuthority', () => { await expect(otherTrexImplementationAuthority.addTREXVersion(versionStruct, contractsStruct)).to.be.revertedWithCustomError( otherTrexImplementationAuthority, - 'OnlyReferenceContractCanAddVersion', + 'OnlyReferenceContractCanCall', ); }); }); @@ -425,7 +425,7 @@ describe('TrexImplementationAuthority', () => { await expect( otherTrexImplementationAuthority.changeImplementationAuthority(token.target, ethers.ZeroAddress), - ).to.be.revertedWithCustomError(otherTrexImplementationAuthority, 'OnlyReferenceContractCanDeployNewIA'); + ).to.be.revertedWithCustomError(otherTrexImplementationAuthority, 'OnlyReferenceContractCanCall'); }); }); @@ -583,7 +583,7 @@ describe('TrexImplementationAuthority', () => { await expect( trexImplementationAuthority.changeImplementationAuthority(token.target, otherTrexImplementationAuthority.target), - ).to.be.revertedWithCustomError(trexImplementationAuthority, 'InvalidIA'); + ).to.be.revertedWithCustomError(trexImplementationAuthority, 'InvalidImplementationAuthority'); }); }); }); diff --git a/test/compliance.test.ts b/test/compliance.test.ts index f8f547d7..91b50259 100644 --- a/test/compliance.test.ts +++ b/test/compliance.test.ts @@ -240,7 +240,7 @@ describe('ModularCompliance', () => { const module = await ethers.deployContract('CountryAllowModule'); - await expect(compliance.addModule(module.target)).to.be.revertedWithCustomError(compliance, 'CannotAddMoreThan25Modules'); + await expect(compliance.addModule(module.target)).to.be.revertedWithCustomError(compliance, 'MaxModulesReached'); }); }); }); @@ -356,7 +356,7 @@ describe('ModularCompliance', () => { await expect(compliance.connect(charlieWallet).transferred(aliceWallet.address, bobWallet.address, 0)).to.be.revertedWithCustomError( compliance, - 'NoValue', + 'ZeroValue', ); }); }); @@ -408,7 +408,7 @@ describe('ModularCompliance', () => { accounts: { bobWallet, charlieWallet }, } = await loadFixture(deploySuiteWithModuleComplianceBoundToWallet); - await expect(compliance.connect(charlieWallet).created(bobWallet.address, 0)).to.be.revertedWithCustomError(compliance, 'NoValue'); + await expect(compliance.connect(charlieWallet).created(bobWallet.address, 0)).to.be.revertedWithCustomError(compliance, 'ZeroValue'); }); }); @@ -459,7 +459,7 @@ describe('ModularCompliance', () => { accounts: { aliceWallet, charlieWallet }, } = await loadFixture(deploySuiteWithModuleComplianceBoundToWallet); - await expect(compliance.connect(charlieWallet).destroyed(aliceWallet.address, 0)).to.be.revertedWithCustomError(compliance, 'NoValue'); + await expect(compliance.connect(charlieWallet).destroyed(aliceWallet.address, 0)).to.be.revertedWithCustomError(compliance, 'ZeroValue'); }); }); diff --git a/test/compliances/module-conditional-transfer.test.ts b/test/compliances/module-conditional-transfer.test.ts index cd42c424..3e7634eb 100644 --- a/test/compliances/module-conditional-transfer.test.ts +++ b/test/compliances/module-conditional-transfer.test.ts @@ -203,7 +203,7 @@ describe('ConditionalTransferModule', () => { ), conditionalTransferModule.target, ), - ).to.be.revertedWithCustomError(conditionalTransferModule, 'NotApproved'); + ).to.be.revertedWithCustomError(conditionalTransferModule, 'TransferNotApproved'); }); }); diff --git a/test/compliances/module-country-restrict.test.ts b/test/compliances/module-country-restrict.test.ts index 8b02d1f4..655de3d2 100644 --- a/test/compliances/module-country-restrict.test.ts +++ b/test/compliances/module-country-restrict.test.ts @@ -312,7 +312,7 @@ describe('CountryRestrictModule', () => { ]), countryRestrictModule.target, ), - ).to.be.revertedWithCustomError(countryRestrictModule, 'Max195CountriesInBatch'); + ).to.be.revertedWithCustomError(countryRestrictModule, 'MaxCountriesInBatchReached'); }); }); @@ -414,7 +414,7 @@ describe('CountryRestrictModule', () => { ), countryRestrictModule.target, ), - ).to.be.revertedWithCustomError(countryRestrictModule, 'Max195CountriesInBatch'); + ).to.be.revertedWithCustomError(countryRestrictModule, 'MaxCountriesInBatchReached'); }); }); diff --git a/test/dvd.test.ts b/test/dvd.test.ts index 2169d9e5..88935bbf 100644 --- a/test/dvd.test.ts +++ b/test/dvd.test.ts @@ -158,7 +158,7 @@ describe('DVDTransferManager', () => { await expect( transferManager.connect(deployer).modifyFee(erc20A.target, erc20B.target, 2, 0, 2, ethers.ZeroAddress, davidWallet.address), - ).to.be.revertedWithCustomError(transferManager, 'FeeWalletCannotBeZeroAddress'); + ).to.be.revertedWithCustomError(transferManager, 'ZeroAddress'); }); }); @@ -171,7 +171,7 @@ describe('DVDTransferManager', () => { await expect( transferManager.connect(deployer).modifyFee(erc20A.target, erc20B.target, 0, 1, 2, ethers.ZeroAddress, ethers.ZeroAddress), - ).to.be.revertedWithCustomError(transferManager, 'FeeWalletCannotBeZeroAddress'); + ).to.be.revertedWithCustomError(transferManager, 'ZeroAddress'); }); }); }); diff --git a/test/registries/claim-topics-registry.test.ts b/test/registries/claim-topics-registry.test.ts index 9e411a60..7dc305c0 100644 --- a/test/registries/claim-topics-registry.test.ts +++ b/test/registries/claim-topics-registry.test.ts @@ -39,7 +39,7 @@ describe('ClaimTopicsRegistry', () => { await expect(claimTopicsRegistry.connect(deployer).addClaimTopic(14)).to.be.revertedWithCustomError( claimTopicsRegistry, - 'CannotRequireMoreThan15Topics', + 'MaxTopicsReached', ); }); }); diff --git a/test/registries/identity-registry-storage.test.ts b/test/registries/identity-registry-storage.test.ts index 76b9ea03..178a1bf9 100644 --- a/test/registries/identity-registry-storage.test.ts +++ b/test/registries/identity-registry-storage.test.ts @@ -288,7 +288,7 @@ describe('IdentityRegistryStorage', () => { await expect(identityRegistryStorage.connect(deployer).bindIdentityRegistry(charlieIdentity.target)).to.be.revertedWithCustomError( identityRegistryStorage, - 'CannotBindMoreThan300IRTo1IRS', + 'MaxIRByIRSReached', ); }); }); diff --git a/test/registries/trusted-issuers-registry.test.ts b/test/registries/trusted-issuers-registry.test.ts index ab32950f..bf880fd6 100644 --- a/test/registries/trusted-issuers-registry.test.ts +++ b/test/registries/trusted-issuers-registry.test.ts @@ -73,7 +73,7 @@ describe('TrustedIssuersRegistry', () => { await expect(trustedIssuersRegistry.connect(deployer).addTrustedIssuer(deployer.address, claimTopics)).to.be.revertedWithCustomError( trustedIssuersRegistry, - 'CannotHaveMoreThan15ClaimTopics', + 'MaxClaimTopcisReached', ); }); }); @@ -96,7 +96,7 @@ describe('TrustedIssuersRegistry', () => { await expect(trustedIssuersRegistry.connect(deployer).addTrustedIssuer(deployer.address, claimTopics)).to.be.revertedWithCustomError( trustedIssuersRegistry, - 'CannotHaveMoreThan50TrustedIssuers', + 'MaxTrustedIssuersReached', ); }); }); @@ -227,7 +227,7 @@ describe('TrustedIssuersRegistry', () => { await expect( trustedIssuersRegistry.connect(deployer).updateIssuerClaimTopics(claimIssuerContract.target, claimTopics), - ).to.be.revertedWithCustomError(trustedIssuersRegistry, 'CannotHaveMoreThan15ClaimTopics'); + ).to.be.revertedWithCustomError(trustedIssuersRegistry, 'MaxClaimTopcisReached'); }); }); @@ -275,7 +275,7 @@ describe('TrustedIssuersRegistry', () => { await expect(trustedIssuersRegistry.connect(deployer).getTrustedIssuerClaimTopics(deployer.address)).to.be.revertedWithCustomError( trustedIssuersRegistry, - 'TrustedIssuerDoesntExist', + 'TrustedIssuerDoesNotExist', ); }); }); From ba2c8538a1b727a95ef937d9097ec9f64b5f4443 Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Fri, 5 Jul 2024 09:05:31 +0200 Subject: [PATCH 27/55] =?UTF-8?q?=E2=99=BB()=20TREX-132=20Missing=20some?= =?UTF-8?q?=20reverts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/token/Token.sol | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/contracts/token/Token.sol b/contracts/token/Token.sol index 96707654..ac9171d1 100755 --- a/contracts/token/Token.sol +++ b/contracts/token/Token.sol @@ -226,9 +226,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-pause}. */ function pause() external override onlyAgent whenNotPaused { - if(getAgentRestrictions(msg.sender).disablePause) { - revert AgentNotAuthorized(msg.sender, "pause disabled"); - } + require(!getAgentRestrictions(msg.sender).disablePause, AgentNotAuthorized(msg.sender, "pause disabled")); _tokenPaused = true; emit Paused(msg.sender); } @@ -237,9 +235,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IToken-unpause}. */ function unpause() external override onlyAgent whenPaused { - if(getAgentRestrictions(msg.sender).disablePause) { - revert AgentNotAuthorized(msg.sender, "pause disabled"); - } + require(!getAgentRestrictions(msg.sender).disablePause, AgentNotAuthorized(msg.sender, "pause disabled")); _tokenPaused = false; emit Unpaused(msg.sender); } @@ -366,9 +362,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { address _newWallet, address _investorOnchainID ) external override onlyAgent returns (bool) { - if(getAgentRestrictions(msg.sender).disableRecovery) { - revert AgentNotAuthorized(msg.sender, "recovery disabled"); - } + require(!getAgentRestrictions(msg.sender).disableRecovery, AgentNotAuthorized(msg.sender, "recovery disabled")); require(balanceOf(_lostWallet) != 0, NoTokenToRecover()); IIdentity _onchainID = IIdentity(_investorOnchainID); bytes32 _key = keccak256(abi.encode(_newWallet)); @@ -505,9 +499,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { address _to, uint256 _amount ) public override onlyAgent returns (bool) { - if(getAgentRestrictions(msg.sender).disableForceTransfer) { - revert AgentNotAuthorized(msg.sender, "forceTransfer disabled"); - } + require(!getAgentRestrictions(msg.sender).disableForceTransfer, AgentNotAuthorized(msg.sender, "forceTransfer disabled")); require(balanceOf(_from) >= _amount, ERC20InsufficientBalance(_from, balanceOf(_from), _amount)); uint256 freeBalance = balanceOf(_from) - (_frozenTokens[_from]); if (_amount > freeBalance) { From b0d18ce351641c21d0b6399e98d6471b8585de56 Mon Sep 17 00:00:00 2001 From: "ali.arbak" Date: Fri, 5 Jul 2024 10:56:18 +0300 Subject: [PATCH 28/55] =?UTF-8?q?=E2=9C=A8()=20Change=20the=20token=20tran?= =?UTF-8?q?sfer=20strategy=20in=20the=20DvA=20contract?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/DVA/DVATransferManager.sol | 3 ++- test/dva.test.ts | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/contracts/DVA/DVATransferManager.sol b/contracts/DVA/DVATransferManager.sol index d499cc0a..7d8c8abe 100644 --- a/contracts/DVA/DVATransferManager.sol +++ b/contracts/DVA/DVATransferManager.sol @@ -383,7 +383,8 @@ contract DVATransferManager is IDVATransferManager, Initializable, OwnableUpgrad transfer.status = TransferStatus.COMPLETED; IToken token = IToken(transfer.tokenAddress); token.unfreezePartialTokens(transfer.sender, transfer.amount); - token.transferFrom(transfer.sender, transfer.recipient, transfer.amount); + token.transferFrom(transfer.sender, address(this), transfer.amount); + token.transfer(transfer.recipient, transfer.amount); emit TransferCompleted( transferID, transfer.tokenAddress, diff --git a/test/dva.test.ts b/test/dva.test.ts index 95aed026..bce81c1a 100644 --- a/test/dva.test.ts +++ b/test/dva.test.ts @@ -24,6 +24,8 @@ describe('DVATransferManager', () => { async function deployFullSuiteWithVerifiedTransferManager() { const context = await loadFixture(deployFullSuiteWithTransferManager); await context.suite.token.connect(context.accounts.deployer).addAgent(context.suite.transferManager.target); + const identity = await context.suite.identityRegistry.identity(context.accounts.aliceWallet.address); + await context.suite.identityRegistry.connect(context.accounts.tokenAgent).registerIdentity(context.suite.transferManager.target, identity, 0); return context; } @@ -972,7 +974,7 @@ describe('DVATransferManager', () => { await context.suite.transferManager.connect(context.accounts.deployer).upgradeTo(newImplementation.target); // then - const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.transferManager.target); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.transferManager.target as string); expect(implementationAddress).to.eq(newImplementation.target); }); }); From 917e421dc0c9860df0798007992f216524fa984e Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Fri, 5 Jul 2024 16:45:17 +0200 Subject: [PATCH 29/55] =?UTF-8?q?=E2=99=BB()=20TREX-133=20Events=20at=20fi?= =?UTF-8?q?le=20level?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/DVA/IDVATransferManager.sol | 205 ++++++++---------- contracts/DVD/DVDTransferManager.sol | 89 ++++---- .../compliance/modular/IModularCompliance.sol | 57 ++--- .../modules/ConditionalTransferModule.sol | 38 ++-- .../modular/modules/CountryAllowModule.sol | 29 ++- .../modular/modules/CountryRestrictModule.sol | 31 ++- .../modules/ExchangeMonthlyLimitsModule.sol | 41 ++-- .../compliance/modular/modules/IModule.sol | 24 +- .../modular/modules/MaxBalanceModule.sol | 25 ++- .../modular/modules/SupplyLimitModule.sol | 15 +- .../modules/TimeExchangeLimitsModule.sol | 41 ++-- .../modules/TimeTransfersLimitsModule.sol | 17 +- .../modular/modules/TransferFeesModule.sol | 18 +- .../modules/TransferRestrictModule.sol | 27 ++- contracts/events/CommonEvents.sol | 69 ++++++ contracts/factory/ITREXFactory.sol | 45 ++-- contracts/factory/ITREXGateway.sol | 66 +++--- contracts/proxy/authority/IIAFactory.sol | 12 +- .../ITREXImplementationAuthority.sol | 62 ++++-- contracts/proxy/interface/IProxy.sol | 5 +- .../interface/IClaimTopicsRegistry.sol | 24 +- .../registry/interface/IIdentityRegistry.sol | 77 +++---- .../interface/IIdentityRegistryStorage.sol | 68 +++--- .../interface/ITrustedIssuersRegistry.sol | 37 ++-- contracts/roles/AgentRole.sol | 15 +- contracts/roles/AgentRoleUpgradeable.sol | 14 +- .../roles/permissioning/agent/AgentRoles.sol | 18 +- .../agent/AgentRolesUpgradeable.sol | 20 +- .../permissioning/owner/OwnerManager.sol | 17 +- .../roles/permissioning/owner/OwnerRoles.sol | 18 +- .../owner/OwnerRolesUpgradeable.sol | 20 +- contracts/token/IToken.sol | 172 ++++++--------- 32 files changed, 728 insertions(+), 688 deletions(-) create mode 100644 contracts/events/CommonEvents.sol diff --git a/contracts/DVA/IDVATransferManager.sol b/contracts/DVA/IDVATransferManager.sol index 5285ba38..9d746bdd 100644 --- a/contracts/DVA/IDVATransferManager.sol +++ b/contracts/DVA/IDVATransferManager.sol @@ -71,6 +71,94 @@ pragma solidity 0.8.26; import "../roles/AgentRole.sol"; import "../token/IToken.sol"; +/// Events + +/// @dev This event is emitted whenever an approval criteria of a token is modified. +/// @param _tokenAddress is the token address. +/// @param _includeRecipientApprover determines whether the recipient is included in the approver list. +/// @param _includeAgentApprover determines whether the agent is included in the approver list. +/// @param _sequentialApproval determines whether approvals must be sequential. +/// @param _additionalApprovers are the addresses of additional approvers to be added to the approver list. +/// @param _hash is the approval criteria hash +event ApprovalCriteriaSet( + address _tokenAddress, + bool _includeRecipientApprover, + bool _includeAgentApprover, + bool _sequentialApproval, + address[] _additionalApprovers, + bytes32 _hash); + +/// @dev This event is emitted whenever a transfer is initiated. +/// @param _transferID is the unique ID of the transfer. +/// @param _tokenAddress is the token address. +/// @param _sender is the address of the sender. +/// @param _recipient is the address of the recipient. +/// @param _amount is the amount of the transfer. +/// @param _approvalCriteriaHash is the approval criteria hash. +event TransferInitiated( + bytes32 _transferID, + address _tokenAddress, + address _sender, + address _recipient, + uint256 _amount, + bytes32 _approvalCriteriaHash); + +/// @dev This event is emitted whenever a transfer is approved by an approver. +/// @param _transferID is the unique ID of the transfer. +/// @param _approver is the approver address. +event TransferApproved(bytes32 _transferID, address _approver); + +/// @dev This event is emitted whenever a transfer is rejected by an approver. +/// @param _transferID is the unique ID of the transfer. +/// @param _rejectedBy is the approver address. +event TransferRejected(bytes32 _transferID, address _rejectedBy); + +/// @dev This event is emitted whenever a transfer is cancelled by the sender. +/// @param _transferID is the unique ID of the transfer. +event TransferCancelled(bytes32 _transferID); + +/// @dev This event is emitted whenever all approvers approve a transfer. +/// @param _transferID is the unique ID of the transfer. +/// @param _tokenAddress is the token address. +/// @param _sender is the address of the sender. +/// @param _recipient is the address of the recipient. +/// @param _amount is the amount of the transfer. +event TransferCompleted( + bytes32 _transferID, + address _tokenAddress, + address _sender, + address _recipient, + uint256 _amount); + +/// @dev This event is emitted whenever a transfer approval criteria are reset. +/// @param _transferID is the unique ID of the transfer. +/// @param _approvalCriteriaHash is the approval criteria hash. +event TransferApprovalStateReset(bytes32 _transferID, bytes32 _approvalCriteriaHash); + + +// Errors + +error OnlyTokenOwnerCanCall(address _tokenAddress); + +error OnlyTransferSenderCanCall(bytes32 _transferID); + +error TokenIsNotRegistered(address _tokenAddress); + +error RecipientIsNotVerified(address _tokenAddress, address _recipient); + +error DVAManagerIsNotAnAgentOfTheToken(address _tokenAddress); + +error InvalidTransferID(bytes32 _transferID); + +error TransferIsNotInPendingStatus(bytes32 _transferID); + +error ApprovalsMustBeSequential(bytes32 _transferID); + +error ApproverNotFound(bytes32 _transferID, address _approver); + +error SignaturesCanNotBeEmpty(bytes32 _transferID); + + interface IDVATransferManager { enum TransferStatus { PENDING, @@ -109,124 +197,7 @@ interface IDVATransferManager { bytes32 s; } - /** - * this event is emitted whenever an approval criteria of a token is modified. - * the event is emitted by 'setApprovalCriteria' function. - * `tokenAddress` is the token address. - * `includeRecipientApprover` determines whether the recipient is included in the approver list - * `includeAgentApprover` determines whether the agent is included in the approver list - * `sequentialApproval` determines whether approvals must be sequential - * `additionalApprovers` are the addresses of additional approvers to be added to the approver list - * `hash` is the approval criteria hash - */ - event ApprovalCriteriaSet( - address tokenAddress, - bool includeRecipientApprover, - bool includeAgentApprover, - bool sequentialApproval, - address[] additionalApprovers, - bytes32 hash - ); - - /** - * this event is emitted whenever a transfer is initiated - * the event is emitted by 'initiateTransfer' function. - * `transferID` is the unique ID of the transfer - * `tokenAddress` is the token address - * `sender` is the address of the sender - * `recipient` is the address of the recipient - * `amount` is the amount of the transfer - * `approvers` is the list of approvers - * `approvalCriteriaHash` is the approval criteria hash - */ - event TransferInitiated( - bytes32 transferID, - address tokenAddress, - address sender, - address recipient, - uint256 amount, - bytes32 approvalCriteriaHash - ); - - /** - * this event is emitted whenever a transfer is approved by an approver - * the event is emitted by 'approveTransfer' function. - * `transferID` is the unique ID of the transfer - * `approver` is the approver address - */ - event TransferApproved( - bytes32 transferID, - address approver - ); - - /** - * this event is emitted whenever a transfer is rejected by an approver - * the event is emitted by 'rejectTransfer' function. - * `transferID` is the unique ID of the transfer - * `rejectedBy` is the approver address - */ - event TransferRejected( - bytes32 transferID, - address rejectedBy - ); - - /** - * this event is emitted whenever a transfer is cancelled by the sender - * the event is emitted by 'cancelTransfer' function. - * `transferID` is the unique ID of the transfer - */ - event TransferCancelled( - bytes32 transferID - ); - - /** - * this event is emitted whenever all approvers approve a transfer - * the event is emitted by 'approveTransfer' function. - * `transferID` is the unique ID of the transfer - * `tokenAddress` is the token address - * `sender` is the address of the sender - * `recipient` is the address of the recipient - * `amount` is the amount of the transfer - */ - event TransferCompleted( - bytes32 transferID, - address tokenAddress, - address sender, - address recipient, - uint256 amount - ); - - /** - * this event is emitted whenever a transfer approval criteria are reset - * the event is emitted by 'approveTransfer' and 'rejectTransfer' functions. - * `transferID` is the unique ID of the transfer - * `approvers` is the list of approvers - * `approvalCriteriaHash` is the approval criteria hash - */ - event TransferApprovalStateReset( - bytes32 transferID, - bytes32 approvalCriteriaHash - ); - - error OnlyTokenOwnerCanCall(address _tokenAddress); - - error OnlyTransferSenderCanCall(bytes32 _transferID); - - error TokenIsNotRegistered(address _tokenAddress); - - error RecipientIsNotVerified(address _tokenAddress, address _recipient); - - error DVAManagerIsNotAnAgentOfTheToken(address _tokenAddress); - - error InvalidTransferID(bytes32 _transferID); - - error TransferIsNotInPendingStatus(bytes32 _transferID); - - error ApprovalsMustBeSequential(bytes32 _transferID); - - error ApproverNotFound(bytes32 _transferID, address _approver); - error SignaturesCanNotBeEmpty(bytes32 _transferID); /** * @dev modify the approval criteria of a token diff --git a/contracts/DVD/DVDTransferManager.sol b/contracts/DVD/DVDTransferManager.sol index 5becb607..58255c42 100644 --- a/contracts/DVD/DVDTransferManager.sol +++ b/contracts/DVD/DVDTransferManager.sol @@ -73,6 +73,51 @@ import "../token/IToken.sol"; import "../errors/CommonErrors.sol"; import "../errors/InvalidArgumentErrors.sol"; +/// events + +/** +* @dev Emitted when a DVD transfer is initiated by `maker` to swap `token1Amount` tokens `token1` (TREX or not) +* for `token2Amount` tokens `token2` with `taker` +* this event is emitted by the `initiateDVDTransfer` function +*/ +event DVDTransferInitiated( + bytes32 indexed transferID, + address maker, + address indexed token1, + uint256 token1Amount, + address taker, + address indexed token2, + uint256 token2Amount); + +/** +* @dev Emitted when a DVD transfer is validated by `taker` and +* executed either by `taker` either by the agent of the TREX token +* if the TREX token is subject to conditional transfers +* this event is emitted by the `takeDVDTransfer` function +*/ +event DVDTransferExecuted(bytes32 indexed transferID); + +/** +* @dev Emitted when a DVD transfer is cancelled +* this event is emitted by the `cancelDVDTransfer` function +*/ +event DVDTransferCancelled(bytes32 indexed transferID); + +/** +* @dev Emitted when a DVD transfer is cancelled +* this event is emitted by the `cancelDVDTransfer` function +*/ +event FeeModified( + bytes32 indexed parity, + address token1, + address token2, + uint fee1, + uint fee2, + uint feeBase, + address fee1Wallet, + address fee2Wallet); + + /// Errors // @dev Thrown when the fee settings are invalid. @@ -127,50 +172,6 @@ contract DVDTransferManager is Ownable { // nonce of the transaction allowing the creation of unique transferID uint256 public txNonce; - /// events - - /** - * @dev Emitted when a DVD transfer is initiated by `maker` to swap `token1Amount` tokens `token1` (TREX or not) - * for `token2Amount` tokens `token2` with `taker` - * this event is emitted by the `initiateDVDTransfer` function - */ - event DVDTransferInitiated( - bytes32 indexed transferID, - address maker, - address indexed token1, - uint256 token1Amount, - address taker, - address indexed token2, - uint256 token2Amount); - - /** - * @dev Emitted when a DVD transfer is validated by `taker` and - * executed either by `taker` either by the agent of the TREX token - * if the TREX token is subject to conditional transfers - * this event is emitted by the `takeDVDTransfer` function - */ - event DVDTransferExecuted(bytes32 indexed transferID); - - /** - * @dev Emitted when a DVD transfer is cancelled - * this event is emitted by the `cancelDVDTransfer` function - */ - event DVDTransferCancelled(bytes32 indexed transferID); - - /** - * @dev Emitted when a DVD transfer is cancelled - * this event is emitted by the `cancelDVDTransfer` function - */ - event FeeModified( - bytes32 indexed parity, - address token1, - address token2, - uint fee1, - uint fee2, - uint feeBase, - address fee1Wallet, - address fee2Wallet); - /// functions // initiates the nonce at 0 diff --git a/contracts/compliance/modular/IModularCompliance.sol b/contracts/compliance/modular/IModularCompliance.sol index 91041382..c43298c4 100644 --- a/contracts/compliance/modular/IModularCompliance.sol +++ b/contracts/compliance/modular/IModularCompliance.sol @@ -62,45 +62,36 @@ pragma solidity 0.8.26; -interface IModularCompliance { +/// events - /// events +/// @dev Event emitted for each executed interaction with a module contract. +/// For gas efficiency, only the interaction calldata selector (first 4 bytes) is included in the event. +/// For interactions without calldata or whose calldata is shorter than 4 bytes, the selector will be `0`. +/// @param _target Address of the module. +/// @param _selector See above comments. +event ModuleInteraction(address indexed _target, bytes4 _selector); - /** - * @dev Event emitted for each executed interaction with a module contract. - * For gas efficiency, only the interaction calldata selector (first 4 - * bytes) is included in the event. For interactions without calldata or - * whose calldata is shorter than 4 bytes, the selector will be `0`. - */ - event ModuleInteraction(address indexed target, bytes4 selector); - /** - * this event is emitted when a token has been bound to the compliance contract - * the event is emitted by the bindToken function - * `_token` is the address of the token to bind - */ - event TokenBound(address _token); +/// @dev This event is emitted when a token has been bound to the compliance contract. +/// @param _token is the address of the token to bind. +event TokenBound(address _token); - /** - * this event is emitted when a token has been unbound from the compliance contract - * the event is emitted by the unbindToken function - * `_token` is the address of the token to unbind - */ - event TokenUnbound(address _token); +/// @dev This event is emitted when a token has been unbound from the compliance contract. +/// @param _token is the address of the token to unbind. +event TokenUnbound(address _token); - /** - * this event is emitted when a module has been added to the list of modules bound to the compliance contract - * the event is emitted by the addModule function - * `_module` is the address of the compliance module - */ - event ModuleAdded(address indexed _module); - /** - * this event is emitted when a module has been removed from the list of modules bound to the compliance contract - * the event is emitted by the removeModule function - * `_module` is the address of the compliance module - */ - event ModuleRemoved(address indexed _module); +/// @dev This event is emitted when a module has been added to the list of modules bound to the compliance contract. +/// @param _module The address of the compliance module. +event ModuleAdded(address indexed _module); + + +/// @dev This event is emitted when a module has been removed from the list of modules bound to the compliance contract. +/// @param _module is the address of the compliance module +event ModuleRemoved(address indexed _module); + + +interface IModularCompliance { /// functions diff --git a/contracts/compliance/modular/modules/ConditionalTransferModule.sol b/contracts/compliance/modular/modules/ConditionalTransferModule.sol index 95437ee1..6cd9caa7 100644 --- a/contracts/compliance/modular/modules/ConditionalTransferModule.sol +++ b/contracts/compliance/modular/modules/ConditionalTransferModule.sol @@ -73,6 +73,24 @@ import "../../../token/IToken.sol"; import "../../../roles/AgentRole.sol"; import "./AbstractModuleUpgradeable.sol"; +/// Events + +/// @dev This event is emitted whenever a transfer is approved. +/// @param _from is the address of transfer sender. +/// @param _to is the address of transfer recipient. +/// @param _amount is the token amount to be sent (take care of decimals). +/// @param _token is the token address of the token concerned by the approval. +event TransferApproved(address _from, address _to, uint _amount, address _token); + + +/// @dev This event is emitted whenever a transfer approval is removed. +/// @param _from is the address of transfer sender. +/// @param _to is the address of transfer recipient. +/// @param _amount is the token amount to be sent (take care of decimals). +/// @param _token is the token address of the token concerned by the approval. +event ApprovalRemoved(address _from, address _to, uint _amount, address _token); + + /// Errors /// @dev Thrown when a tranfer is not approved. @@ -89,26 +107,6 @@ contract ConditionalTransferModule is AbstractModuleUpgradeable { /// Mapping between transfer details and their approval status (amount of transfers approved) per compliance mapping(address => mapping(bytes32 => uint)) private _transfersApproved; - /** - * this event is emitted whenever a transfer is approved. - * the event is emitted by 'approveTransfer' function. - * `_from` is the address of transfer sender. - * `_to` is the address of transfer recipient - * `_amount` is the token amount to be sent (take care of decimals) - * `_token` is the token address of the token concerned by the approval - */ - event TransferApproved(address _from, address _to, uint _amount, address _token); - - /** - * this event is emitted whenever a transfer approval is removed. - * the event is emitted by 'unApproveTransfer' function. - * `_from` is the address of transfer sender. - * `_to` is the address of transfer recipient - * `_amount` is the token amount to be sent (take care of decimals) - * `_token` is the token address of the token concerned by the approval - */ - event ApprovalRemoved(address _from, address _to, uint _amount, address _token); - /** * @dev initializes the contract and sets the initial state. * @notice This function should only be called once during the contract deployment. diff --git a/contracts/compliance/modular/modules/CountryAllowModule.sol b/contracts/compliance/modular/modules/CountryAllowModule.sol index 5de0afc5..3008fab3 100644 --- a/contracts/compliance/modular/modules/CountryAllowModule.sol +++ b/contracts/compliance/modular/modules/CountryAllowModule.sol @@ -72,6 +72,20 @@ import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; import "./AbstractModuleUpgradeable.sol"; +/// Events + +/// @dev This event is emitted whenever a Country has been allowed. +/// @param _compliance compliance address contract. +/// @param _country is the numeric ISO 3166-1 of the restricted country. +event CountryAllowed(address _compliance, uint16 _country); + + +/// @dev this event is emitted whenever a Country has been disallowed. +/// @param _compliance compliance address contract. +/// @param _country is the numeric ISO 3166-1 of the disallowed country. +event CountryUnallowed(address _compliance, uint16 _country); + + /// Errors /// @dev Thrown when a country is already allowed. @@ -89,21 +103,6 @@ contract CountryAllowModule is AbstractModuleUpgradeable { /// Mapping between country and their allowance status per compliance contract mapping(address => mapping(uint16 => bool)) private _allowedCountries; - /// events - - /** - * this event is emitted whenever a Country has been allowed. - * the event is emitted by 'addAllowedCountry' and 'batchAllowCountries' functions. - * `_country` is the numeric ISO 3166-1 of the restricted country. - */ - event CountryAllowed(address _compliance, uint16 _country); - /** - * this event is emitted whenever a Country has been disallowed. - * the event is emitted by 'removeAllowedCountry' and 'batchDisallowCountries' functions. - * `_country` is the numeric ISO 3166-1 of the disallowed country. - */ - event CountryUnallowed(address _compliance, uint16 _country); - /// functions /** diff --git a/contracts/compliance/modular/modules/CountryRestrictModule.sol b/contracts/compliance/modular/modules/CountryRestrictModule.sol index 11f39d8b..d274b0e3 100644 --- a/contracts/compliance/modular/modules/CountryRestrictModule.sol +++ b/contracts/compliance/modular/modules/CountryRestrictModule.sol @@ -72,6 +72,21 @@ import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; import "./AbstractModuleUpgradeable.sol"; + +/// Events + +/// @dev This event is emitted whenever a Country has been restricted. +/// @param _compliance compliance address contract. +/// @param _country is the numeric ISO 3166-1 of the restricted country. +event AddedRestrictedCountry(address indexed _compliance, uint16 _country); + + +/// @dev This event is emitted whenever a Country has been unrestricted. +/// @param _compliance compliance address contract. +/// @param _country is the numeric ISO 3166-1 of the unrestricted country. +event RemovedRestrictedCountry(address indexed _compliance, uint16 _country); + + /// Errors /// @dev Thrown when a country is already restricted. @@ -94,22 +109,6 @@ contract CountryRestrictModule is AbstractModuleUpgradeable { /// Mapping between country and their restriction status per compliance contract mapping(address => mapping(uint16 => bool)) private _restrictedCountries; - /** - * this event is emitted whenever a Country has been restricted. - * the event is emitted by 'addCountryRestriction' and 'batchRestrictCountries' functions. - * `_country` is the numeric ISO 3166-1 of the restricted country. - */ - event AddedRestrictedCountry(address indexed _compliance, uint16 _country); - - /** - * this event is emitted whenever a Country has been unrestricted. - * the event is emitted by 'removeCountryRestriction' and 'batchUnrestrictCountries' functions. - * `_country` is the numeric ISO 3166-1 of the unrestricted country. - */ - event RemovedRestrictedCountry(address indexed _compliance, uint16 _country); - - /// Functions - /** * @dev initializes the contract and sets the initial state. * @notice This function should only be called once during the contract deployment. diff --git a/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol b/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol index 0eb9cc11..a93b8e69 100644 --- a/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol +++ b/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol @@ -73,6 +73,24 @@ import "../../../token/IToken.sol"; import "../../../roles/AgentRole.sol"; import "./AbstractModuleUpgradeable.sol"; +/// Events + +/// @dev This event is emitted whenever the Exchange Limit has been updated. +/// @param compliance is the address of the caller Compliance contract. +/// @param _exchangeID is the amount ONCHAINID address of the exchange. +/// @param _newExchangeMonthlyLimit is the amount Limit of tokens to be transferred monthly to an exchange wallet. +event ExchangeMonthlyLimitUpdated(address indexed compliance, address _exchangeID, uint _newExchangeMonthlyLimit); + + +/// @dev This event is emitted whenever an ONCHAINID is tagged as being an exchange ID. +/// @param _newExchangeID is the ONCHAINID address of the exchange to add. +event ExchangeIDAdded(address _newExchangeID); + + +/// @dev This event is emitted whenever an ONCHAINID is untagged as belonging to an exchange. +/// @param _exchangeID is the ONCHAINID being untagged as an exchange ID. +event ExchangeIDRemoved(address _exchangeID); + contract ExchangeMonthlyLimitsModule is AbstractModuleUpgradeable { /// Struct of transfer Counters @@ -90,29 +108,6 @@ contract ExchangeMonthlyLimitsModule is AbstractModuleUpgradeable { /// Mapping for wallets tagged as exchange wallets mapping(address => bool) private _exchangeIDs; - /** - * this event is emitted whenever the Exchange Limit has been updated. - * the event is emitted by 'setExchangeMonthlyLimit' - * `compliance` is the address of the caller Compliance contract. - * `_exchangeID` is the amount ONCHAINID address of the exchange. - * `_newExchangeMonthlyLimit` is the amount Limit of tokens to be transferred monthly to an exchange wallet. - */ - event ExchangeMonthlyLimitUpdated(address indexed compliance, address _exchangeID, uint _newExchangeMonthlyLimit); - - /** - * this event is emitted whenever an ONCHAINID is tagged as being an exchange ID. - * the event is emitted by 'addExchangeID'. - * `_newExchangeID` is the ONCHAINID address of the exchange to add. - */ - event ExchangeIDAdded(address _newExchangeID); - - /** - * this event is emitted whenever an ONCHAINID is untagged as belonging to an exchange. - * the event is emitted by 'removeExchangeID'. - * `_exchangeID` is the ONCHAINID being untagged as an exchange ID. - */ - event ExchangeIDRemoved(address _exchangeID); - /** * @dev initializes the contract and sets the initial state. * @notice This function should only be called once during the contract deployment. diff --git a/contracts/compliance/modular/modules/IModule.sol b/contracts/compliance/modular/modules/IModule.sol index ee99de7f..cbf11425 100644 --- a/contracts/compliance/modular/modules/IModule.sol +++ b/contracts/compliance/modular/modules/IModule.sol @@ -62,22 +62,18 @@ pragma solidity 0.8.26; -interface IModule { - /// events +// events - /** - * this event is emitted when the compliance contract is bound to the module. - * the event is emitted by the bindCompliance function - * `_compliance` is the address of the compliance contract being bound - */ - event ComplianceBound(address indexed _compliance); +/// @dev This event is emitted when the compliance contract is bound to the module. +/// @param _compliance is the address of the compliance contract being bound +event ComplianceBound(address indexed _compliance); - /** - * this event is emitted when the compliance contract is unbound from the module. - * the event is emitted by the unbindCompliance function - * `_compliance` is the address of the compliance contract being unbound - */ - event ComplianceUnbound(address indexed _compliance); +/// @dev This event is emitted when the compliance contract is unbound from the module. +/// @param _compliance is the address of the compliance contract being unbound +event ComplianceUnbound(address indexed _compliance); + + +interface IModule { /// functions diff --git a/contracts/compliance/modular/modules/MaxBalanceModule.sol b/contracts/compliance/modular/modules/MaxBalanceModule.sol index fdb589e4..c8bb4bcd 100644 --- a/contracts/compliance/modular/modules/MaxBalanceModule.sol +++ b/contracts/compliance/modular/modules/MaxBalanceModule.sol @@ -73,6 +73,20 @@ import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; import "./AbstractModuleUpgradeable.sol"; +/// events + +/// @dev This event is emitted when the max balance has been set for a compliance bound. +/// @param _compliance is the address of modular compliance concerned. +/// @param _maxBalance is the max amount of tokens that a user can hold. +event MaxBalanceSet(address indexed _compliance, uint256 indexed _maxBalance); + +/// @dev This event is emitted when the balance has been set for a compliance bound. +/// @param _compliance is the address of modular compliance concerned. +/// @param _id the ONCHAINID address of the token holder. +/// @param _balance the current balance of the token holder. +event IDBalancePreSet(address indexed _compliance, address indexed _id, uint256 _balance); + + /// errors /// @dev Thrown when @@ -114,17 +128,6 @@ contract MaxBalanceModule is AbstractModuleUpgradeable { // solhint-disable-next-line var-name-mixedcase mapping(address => mapping(address => uint256)) private _IDBalance; - /// events - - /** - * this event is emitted when the max balance has been set for a compliance bound. - * `_compliance` is the address of modular compliance concerned - * `_maxBalance` is the max amount of tokens that a user can hold . - */ - event MaxBalanceSet(address indexed _compliance, uint256 indexed _maxBalance); - - event IDBalancePreSet(address indexed _compliance, address indexed _id, uint256 _balance); - /// functions /** diff --git a/contracts/compliance/modular/modules/SupplyLimitModule.sol b/contracts/compliance/modular/modules/SupplyLimitModule.sol index c795820e..1a157ab3 100644 --- a/contracts/compliance/modular/modules/SupplyLimitModule.sol +++ b/contracts/compliance/modular/modules/SupplyLimitModule.sol @@ -72,17 +72,18 @@ import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; import "./AbstractModuleUpgradeable.sol"; +/// Events + +/// @dev This event is emitted when the supply limit has been set. +/// @param _compliance is the compliance address. +/// @param _limit is the max amount of tokens in circulation. +event SupplyLimitSet(address _compliance, uint256 _limit); + + contract SupplyLimitModule is AbstractModuleUpgradeable { /// supply limits array mapping(address => uint256) private _supplyLimits; - /** - * this event is emitted when the supply limit has been set. - * `_compliance` is the compliance address. - * `_limit` is the max amount of tokens in circulation. - */ - event SupplyLimitSet(address _compliance, uint256 _limit); - /** * @dev initializes the contract and sets the initial state. * @notice This function should only be called once during the contract deployment. diff --git a/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol b/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol index 9ab4e076..712654b6 100644 --- a/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol +++ b/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol @@ -73,6 +73,23 @@ import "../../../token/IToken.sol"; import "../../../roles/AgentRole.sol"; import "./AbstractModuleUpgradeable.sol"; +/// Events + +/// @dev This event is emitted whenever an exchange limit is updated for the given compliance address. +/// @param _compliance is the compliance contract address. +/// @param _exchangeID is the ONCHAINID of the exchange. +/// @param _limitValue is the new limit value for the given limit time. +/// @param _limitTime is the period of time of the limit. +event ExchangeLimitUpdated(address indexed _compliance, address _exchangeID, uint _limitValue, uint32 _limitTime); + +/// &dev This event is emitted whenever an ONCHAINID is tagged as an exchange ID. +/// @param _newExchangeID is the ONCHAINID address of the exchange to add. +event ExchangeIDAdded(address _newExchangeID); + +/// @dev This event is emitted whenever an ONCHAINID is untagged as belonging to an exchange. +/// @param _exchangeID is the ONCHAINID being untagged as an exchange ID. +event ExchangeIDRemoved(address _exchangeID); + contract TimeExchangeLimitsModule is AbstractModuleUpgradeable { /// Struct of transfer Counters @@ -104,30 +121,6 @@ contract TimeExchangeLimitsModule is AbstractModuleUpgradeable { /// Mapping for wallets tagged as exchange wallets mapping(address => bool) private _exchangeIDs; - /** - * this event is emitted whenever an exchange limit is updated for the given compliance address - * the event is emitted by 'setExchangeLimit'. - * compliance`is the compliance contract address - * _exchangeID is the ONCHAINID of the exchange - * _limitValue is the new limit value for the given limit time - * _limitTime is the period of time of the limit - */ - event ExchangeLimitUpdated(address indexed compliance, address _exchangeID, uint _limitValue, uint32 _limitTime); - - /** - * this event is emitted whenever an ONCHAINID is tagged as an exchange ID. - * the event is emitted by 'addExchangeID'. - * `_newExchangeID` is the ONCHAINID address of the exchange to add. - */ - event ExchangeIDAdded(address _newExchangeID); - - /** - * this event is emitted whenever an ONCHAINID is untagged as belonging to an exchange. - * the event is emitted by 'removeExchangeID'. - * `_exchangeID` is the ONCHAINID being untagged as an exchange ID. - */ - event ExchangeIDRemoved(address _exchangeID); - /** * @dev initializes the contract and sets the initial state. * @notice This function should only be called once during the contract deployment. diff --git a/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol b/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol index 64f2845d..99a3c6e9 100644 --- a/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol +++ b/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol @@ -74,6 +74,14 @@ import "../../../roles/AgentRole.sol"; import "./AbstractModuleUpgradeable.sol"; import "../../../errors/InvalidArgumentErrors.sol"; +/// Events + +/// @dev This event is emitted whenever a transfer limit is updated for the given compliance address and limit time. +/// @param _compliance is the compliance contract address. +/// @param _limitTime is the period of time of the limit. +/// @param _limitValue is the new limit value for the given limit time. +event TimeTransferLimitUpdated(address indexed _compliance, uint32 _limitTime, uint256 _limitValue); + contract TimeTransfersLimitsModule is AbstractModuleUpgradeable { /// Struct of transfer Counters @@ -101,15 +109,6 @@ contract TimeTransfersLimitsModule is AbstractModuleUpgradeable { /// Mapping for users Counters mapping(address => mapping(address => mapping(uint32 => TransferCounter))) public usersCounters; - /** - * this event is emitted whenever a transfer limit is updated for the given compliance address and limit time - * the event is emitted by 'setTimeTransferLimit'. - * compliance`is the compliance contract address - * _limitValue is the new limit value for the given limit time - * _limitTime is the period of time of the limit - */ - event TimeTransferLimitUpdated(address indexed compliance, uint32 limitTime, uint256 limitValue); - /** * @dev initializes the contract and sets the initial state. * @notice This function should only be called once during the contract deployment. diff --git a/contracts/compliance/modular/modules/TransferFeesModule.sol b/contracts/compliance/modular/modules/TransferFeesModule.sol index 7b2a8566..672ce857 100644 --- a/contracts/compliance/modular/modules/TransferFeesModule.sol +++ b/contracts/compliance/modular/modules/TransferFeesModule.sol @@ -73,6 +73,15 @@ import "../../../token/IToken.sol"; import "../../../roles/AgentRole.sol"; import "./AbstractModuleUpgradeable.sol"; +/// Events + +/// @dev This event is emitted whenever a fee definition is updated for the given compliance address. +/// @param _compliance is the compliance contract address. +/// @param _rate is the rate of the fee in BPS (0.01% = 1, 1% = 100, 100% = 10000). +/// @param _collector is the collector wallet address. +event FeeUpdated(address indexed _compliance, uint256 _rate, address _collector); + + /// Errors /// @dev Thrown when fee rate is out of range. @@ -99,15 +108,6 @@ contract TransferFeesModule is AbstractModuleUpgradeable { /// Mapping for compliance fees mapping(address => Fee) private _fees; - /** - * this event is emitted whenever a fee definition is updated for the given compliance address - * the event is emitted by 'setFee'. - * compliance is the compliance contract address - * _rate is the rate of the fee (0.01% = 1, 1% = 100, 100% = 10000) - * _collector is the collector wallet address - */ - event FeeUpdated(address indexed compliance, uint256 _rate, address _collector); - /** * @dev initializes the contract and sets the initial state. * @notice This function should only be called once during the contract deployment. diff --git a/contracts/compliance/modular/modules/TransferRestrictModule.sol b/contracts/compliance/modular/modules/TransferRestrictModule.sol index 0f7c2862..8584826a 100644 --- a/contracts/compliance/modular/modules/TransferRestrictModule.sol +++ b/contracts/compliance/modular/modules/TransferRestrictModule.sol @@ -70,24 +70,23 @@ pragma solidity ^0.8.26; import "./AbstractModuleUpgradeable.sol"; +/// Events + +/// @dev This event is emitted when a user is allowed for transfer. +/// @param _compliance is the compliance address. +/// @param _userAddress is the allowed user address. +event UserAllowed(address _compliance, address _userAddress); + +/// @dev This event is emitted when a user is disallowed for transfer. +/// @param _compliance is the compliance address. +/// @param _userAddress is the disallowed user address +event UserDisallowed(address _compliance, address _userAddress); + + contract TransferRestrictModule is AbstractModuleUpgradeable { /// allowed user addresses mapping mapping(address => mapping(address => bool)) private _allowedUserAddresses; - /** - * this event is emitted when a user is allowed for transfer - * `_compliance` is the compliance address. - * `_userAddress` is the allowed user address - */ - event UserAllowed(address _compliance, address _userAddress); - - /** - * this event is emitted when a user is disallowed for transfer - * `_compliance` is the compliance address. - * `_userAddress` is the disallowed user address - */ - event UserDisallowed(address _compliance, address _userAddress); - /** * @dev initializes the contract and sets the initial state. * @notice This function should only be called once during the contract deployment. diff --git a/contracts/events/CommonEvents.sol b/contracts/events/CommonEvents.sol new file mode 100644 index 00000000..12b3154d --- /dev/null +++ b/contracts/events/CommonEvents.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-3.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// + +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2023, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +pragma solidity 0.8.26; + + +/// event emitted when the implementation authority of the factory contract is set +event ImplementationAuthoritySet(address _implementationAuthority); + diff --git a/contracts/factory/ITREXFactory.sol b/contracts/factory/ITREXFactory.sol index deed9662..2551ed67 100644 --- a/contracts/factory/ITREXFactory.sol +++ b/contracts/factory/ITREXFactory.sol @@ -61,6 +61,36 @@ */ pragma solidity 0.8.26; +import "../events/CommonEvents.sol"; + +/// Events + +/// @dev Event emitted whenever a single contract is deployed by the factory. +/// @param _addr Address of the created contract. +event Deployed(address indexed _addr); + +/// @dev Event emitted when the Identity Factory is set. +/// @param _idFactory The address of the identity factory contract. +event IdFactorySet(address _idFactory); + +/// @dev Event emitted by the factory when a full suite of T-REX contracts is deployed. +/// @param _token Address of token contract. +/// @param _ir Address of identity registry contract. +/// @param _irs Address of identity registry storage contract. +/// @param _tir Address of trusted identity registry contract. +/// @param _ctr Address of claim topics registry contract. +/// @param _mc Address of modular compliance contract. +/// @param _salt The salt string that was used to deploy the token. +event TREXSuiteDeployed( + address indexed _token, + address _ir, + address _irs, + address _tir, + address _ctr, + address _mc, + string indexed _salt); + + interface ITREXFactory { /// Types @@ -101,21 +131,6 @@ interface ITREXFactory { uint256[][] issuerClaims; } - /// events - - /// event emitted whenever a single contract is deployed by the factory - event Deployed(address indexed _addr); - - /// event emitted when the Identity Factory is set - event IdFactorySet(address _idFactory); - - /// event emitted when the implementation authority of the factory contract is set - event ImplementationAuthoritySet(address _implementationAuthority); - - /// event emitted by the factory when a full suite of T-REX contracts is deployed - event TREXSuiteDeployed(address indexed _token, address _ir, address _irs, address _tir, address _ctr, address - _mc, string indexed _salt); - /// functions /** diff --git a/contracts/factory/ITREXGateway.sol b/contracts/factory/ITREXGateway.sol index 90be51ee..3c11002c 100644 --- a/contracts/factory/ITREXGateway.sol +++ b/contracts/factory/ITREXGateway.sol @@ -63,6 +63,46 @@ pragma solidity 0.8.26; import "./ITREXFactory.sol"; +/// Events + +/// @dev Event emitted when the _factory variable is set/modified. +/// @param _factory The address of the new factory contract. +event FactorySet(address indexed _factory); + +/// @dev Event emitted when the public deployment status is set/modified. +/// @param _publicDeploymentStatus Determines if public deployments are enabled (`true`) or disabled (`false`). +event PublicDeploymentStatusSet(bool indexed _publicDeploymentStatus); + +/// @dev Event emitted when the deployment fees details are set/modified. +/// @param _fee The amount of deployment fee. +/// @param _feeToken Address of the token used for the deployment fee. +/// @param _feeCollector Address that will collect the deployment fees. +event DeploymentFeeSet(uint256 indexed _fee, address indexed _feeToken, address indexed _feeCollector); + +/// @dev Event emitted when the deployment fees are enabled/disabled. +/// @param _isEnabled Determines if deployment fees are enabled (`true`) or disabled (`false`). +event DeploymentFeeEnabled(bool indexed _isEnabled); + +/// @dev Event emitted when an address is flagged as a deployer. +/// @param _deployer Address added to the list of approved deployers. +event DeployerAdded(address indexed _deployer); + +/// @dev Event emitted when a deployer address loses deployment privileges. +/// @param _deployer Address removed from the list of approved deployers. +event DeployerRemoved(address indexed _deployer); + +/// @dev Event emitted when a discount on deployment fees is granted for an address. +/// @param _deployer Address of the deployer to which the discount will be applied. +/// @param _discount The discount rate in BPS. +event FeeDiscountApplied(address indexed _deployer, uint16 _discount); + +/// @dev Event emitted whenever a TREX token has been deployed by the TREX factory through the use of the Gateway. +/// @param _requester Address who called the deployement. +/// @param _intendedOwner Address of the intended owner. +/// @param _feeApplied Fee amount in BPS. +event GatewaySuiteDeploymentProcessed(address indexed _requester, address _intendedOwner, uint256 _feeApplied); + + interface ITREXGateway { /// Types @@ -76,32 +116,6 @@ interface ITREXGateway { address feeCollector; } - /// events - - /// event emitted when the _factory variable is set/modified - event FactorySet(address indexed factory); - - /// event emitted when the public deployment status is set/modified - event PublicDeploymentStatusSet(bool indexed publicDeploymentStatus); - - /// event emitted when the deployment fees details are set/modified - event DeploymentFeeSet(uint256 indexed fee, address indexed feeToken, address indexed feeCollector); - - /// event emitted when the deployment fees are enabled/disabled - event DeploymentFeeEnabled(bool indexed isEnabled); - - /// event emitted when an address is flagged as a deployer - event DeployerAdded(address indexed deployer); - - /// event emitted when a deployer address loses deployment privileges - event DeployerRemoved(address indexed deployer); - - /// event emitted when a discount on deployment fees is granted for an address - event FeeDiscountApplied(address indexed deployer, uint16 discount); - - /// event emitted whenever a TREX token has been deployed by the TREX factory through the use of the Gateway - event GatewaySuiteDeploymentProcessed(address indexed requester, address intendedOwner, uint256 feeApplied); - /// Functions /** diff --git a/contracts/proxy/authority/IIAFactory.sol b/contracts/proxy/authority/IIAFactory.sol index c30cf8ba..4562fcaf 100644 --- a/contracts/proxy/authority/IIAFactory.sol +++ b/contracts/proxy/authority/IIAFactory.sol @@ -61,12 +61,16 @@ */ pragma solidity 0.8.26; -interface IIAFactory { - /// events - /// event emitted when a new TREXImplementationAuthority is deployed - event ImplementationAuthorityDeployed(address indexed _ia); +/// Events + +/// @dev Event emitted when a new TREXImplementationAuthority is deployed. +/// @param _ia Address of implementation authority contract. +event ImplementationAuthorityDeployed(address indexed _ia); + + +interface IIAFactory { /// functions diff --git a/contracts/proxy/authority/ITREXImplementationAuthority.sol b/contracts/proxy/authority/ITREXImplementationAuthority.sol index 4ea63098..41268244 100644 --- a/contracts/proxy/authority/ITREXImplementationAuthority.sol +++ b/contracts/proxy/authority/ITREXImplementationAuthority.sol @@ -62,6 +62,45 @@ pragma solidity 0.8.26; +/// events + +/// @dev Event emitted when a new TREX version is added to the contract memory. +/// @param _version Version details. +/// @param _trex Address of contract for this version. +event TREXVersionAdded( + ITREXImplementationAuthority.Version indexed _version, + ITREXImplementationAuthority.TREXContracts indexed _trex); + +/// @dev Event emitted when a new TREX version is fetched from reference contract by auxiliary contract. +/// @param _version Version details. +/// @param _trex Address of contract for this version. +event TREXVersionFetched( + ITREXImplementationAuthority.Version indexed _version, + ITREXImplementationAuthority.TREXContracts indexed _trex); + +/// @dev Event emitted when the current version is updated. +/// @param _version Version details. +event VersionUpdated(ITREXImplementationAuthority.Version indexed _version); + +/// @dev Event emitted by the constructor when the IA is deployed. +/// @param _referenceStatus Main implementation authority or auxiliary contract. +/// @param _trexFactory Address of trexFactory contract. +event ImplementationAuthoritySet(bool _referenceStatus, address _trexFactory); + +/// @dev Event emitted when the TREX factory address is set. +/// @param _trexFactory Address of TRexFactory contract. +event TREXFactorySet(address indexed _trexFactory); + +/// @dev Event emitted when the IA factory address is set. +/// @param _iaFactory Address of implementation authority contract. +event IAFactorySet(address indexed _iaFactory); + +/// @dev Event emitted when a token issuer decides to change current IA for a new one. +/// @param _token Address of the token proxy contract. +/// @param _newImplementationAuthority Address of the new implementation authorirty contract. +event ImplementationAuthorityChanged(address indexed _token, address indexed _newImplementationAuthority); + + interface ITREXImplementationAuthority { /// types @@ -90,29 +129,6 @@ interface ITREXImplementationAuthority { uint8 patch; } - /// events - - /// event emitted when a new TREX version is added to the contract memory - event TREXVersionAdded(Version indexed version, TREXContracts indexed trex); - - /// event emitted when a new TREX version is fetched from reference contract by auxiliary contract - event TREXVersionFetched(Version indexed version, TREXContracts indexed trex); - - /// event emitted when the current version is updated - event VersionUpdated(Version indexed version); - - /// event emitted by the constructor when the IA is deployed - event ImplementationAuthoritySet(bool referenceStatus, address trexFactory); - - /// event emitted when the TREX factory address is set - event TREXFactorySet(address indexed trexFactory); - - /// event emitted when the IA factory address is set - event IAFactorySet(address indexed iaFactory); - - /// event emitted when a token issuer decides to change current IA for a new one - event ImplementationAuthorityChanged(address indexed _token, address indexed _newImplementationAuthority); - /// functions /** diff --git a/contracts/proxy/interface/IProxy.sol b/contracts/proxy/interface/IProxy.sol index 792cdb36..b430ac15 100644 --- a/contracts/proxy/interface/IProxy.sol +++ b/contracts/proxy/interface/IProxy.sol @@ -62,11 +62,10 @@ pragma solidity 0.8.26; -interface IProxy { +import "../../events/CommonEvents.sol"; - /// events - event ImplementationAuthoritySet(address indexed _implementationAuthority); +interface IProxy { /// functions diff --git a/contracts/registry/interface/IClaimTopicsRegistry.sol b/contracts/registry/interface/IClaimTopicsRegistry.sol index 20ab309e..d117e451 100644 --- a/contracts/registry/interface/IClaimTopicsRegistry.sol +++ b/contracts/registry/interface/IClaimTopicsRegistry.sol @@ -62,20 +62,18 @@ pragma solidity 0.8.26; -interface IClaimTopicsRegistry { - /** - * this event is emitted when a claim topic has been added to the ClaimTopicsRegistry - * the event is emitted by the 'addClaimTopic' function - * `claimTopic` is the required claim added to the Claim Topics Registry - */ - event ClaimTopicAdded(uint256 indexed claimTopic); +/// Events - /** - * this event is emitted when a claim topic has been removed from the ClaimTopicsRegistry - * the event is emitted by the 'removeClaimTopic' function - * `claimTopic` is the required claim removed from the Claim Topics Registry - */ - event ClaimTopicRemoved(uint256 indexed claimTopic); +/// @dev This event is emitted when a claim topic has been added to the ClaimTopicsRegistry. +/// @param _claimTopic is the required claim added to the Claim Topics Registry. +event ClaimTopicAdded(uint256 indexed _claimTopic); + +/// @dev This event is emitted when a claim topic has been removed from the ClaimTopicsRegistry. +/// @param _claimTopic is the required claim removed from the Claim Topics Registry. +event ClaimTopicRemoved(uint256 indexed _claimTopic); + + +interface IClaimTopicsRegistry { /** * @dev Add a trusted claim topic (For example: KYC=1, AML=2). diff --git a/contracts/registry/interface/IIdentityRegistry.sol b/contracts/registry/interface/IIdentityRegistry.sol index c7e25e2d..60b29d7b 100644 --- a/contracts/registry/interface/IIdentityRegistry.sol +++ b/contracts/registry/interface/IIdentityRegistry.sol @@ -69,59 +69,42 @@ import "./IIdentityRegistryStorage.sol"; import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; -interface IIdentityRegistry { - /** - * this event is emitted when the ClaimTopicsRegistry has been set for the IdentityRegistry - * the event is emitted by the IdentityRegistry constructor - * `claimTopicsRegistry` is the address of the Claim Topics Registry contract - */ - event ClaimTopicsRegistrySet(address indexed claimTopicsRegistry); +/// Events - /** - * this event is emitted when the IdentityRegistryStorage has been set for the IdentityRegistry - * the event is emitted by the IdentityRegistry constructor - * `identityStorage` is the address of the Identity Registry Storage contract - */ - event IdentityStorageSet(address indexed identityStorage); +/// @dev This event is emitted when the ClaimTopicsRegistry has been set for the IdentityRegistry. +/// @param _claimTopicsRegistry is the address of the Claim Topics Registry contract. +event ClaimTopicsRegistrySet(address indexed _claimTopicsRegistry); - /** - * this event is emitted when the TrustedIssuersRegistry has been set for the IdentityRegistry - * the event is emitted by the IdentityRegistry constructor - * `trustedIssuersRegistry` is the address of the Trusted Issuers Registry contract - */ - event TrustedIssuersRegistrySet(address indexed trustedIssuersRegistry); +/// @dev This event is emitted when the IdentityRegistryStorage has been set for the IdentityRegistry. +/// @param _identityStorage is the address of the Identity Registry Storage contract. +event IdentityStorageSet(address indexed _identityStorage); - /** - * this event is emitted when an Identity is registered into the Identity Registry. - * the event is emitted by the 'registerIdentity' function - * `investorAddress` is the address of the investor's wallet - * `identity` is the address of the Identity smart contract (onchainID) - */ - event IdentityRegistered(address indexed investorAddress, IIdentity indexed identity); +/// @dev This event is emitted when the TrustedIssuersRegistry has been set for the IdentityRegistry. +/// @param _trustedIssuersRegistry is the address of the Trusted Issuers Registry contract. +event TrustedIssuersRegistrySet(address indexed _trustedIssuersRegistry); - /** - * this event is emitted when an Identity is removed from the Identity Registry. - * the event is emitted by the 'deleteIdentity' function - * `investorAddress` is the address of the investor's wallet - * `identity` is the address of the Identity smart contract (onchainID) - */ - event IdentityRemoved(address indexed investorAddress, IIdentity indexed identity); +/// @dev This event is emitted when an Identity is registered into the Identity Registry. +/// @param _investorAddress is the address of the investor's wallet. +/// @param _identity is the address of the Identity smart contract (onchainID). +event IdentityRegistered(address indexed _investorAddress, IIdentity indexed _identity); - /** - * this event is emitted when an Identity has been updated - * the event is emitted by the 'updateIdentity' function - * `oldIdentity` is the old Identity contract's address to update - * `newIdentity` is the new Identity contract's - */ - event IdentityUpdated(IIdentity indexed oldIdentity, IIdentity indexed newIdentity); +/// @dev This event is emitted when an Identity is removed from the Identity Registry. +/// @param _investorAddress is the address of the investor's wallet. +/// @param _identity is the address of the Identity smart contract (onchainID). +event IdentityRemoved(address indexed _investorAddress, IIdentity indexed _identity); - /** - * this event is emitted when an Identity's country has been updated - * the event is emitted by the 'updateCountry' function - * `investorAddress` is the address on which the country has been updated - * `country` is the numeric code (ISO 3166-1) of the new country - */ - event CountryUpdated(address indexed investorAddress, uint16 indexed country); +/// @dev This event is emitted when an Identity has been updated. +/// @param _oldIdentity is the old Identity contract's address to update. +/// @param _newIdentity is the new Identity contract's. +event IdentityUpdated(IIdentity indexed _oldIdentity, IIdentity indexed _newIdentity); + +/// @dev This event is emitted when an Identity's country has been updated. +/// @param _investorAddress is the address on which the country has been updated +/// @param _country is the numeric code (ISO 3166-1) of the new country +event CountryUpdated(address indexed _investorAddress, uint16 indexed _country); + + +interface IIdentityRegistry { /** * @dev Register an identity contract corresponding to a user address. diff --git a/contracts/registry/interface/IIdentityRegistryStorage.sol b/contracts/registry/interface/IIdentityRegistryStorage.sol index ae607408..e394a040 100644 --- a/contracts/registry/interface/IIdentityRegistryStorage.sol +++ b/contracts/registry/interface/IIdentityRegistryStorage.sol @@ -64,55 +64,39 @@ pragma solidity 0.8.26; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; -interface IIdentityRegistryStorage { - /// events +/// events - /** - * this event is emitted when an Identity is registered into the storage contract. - * the event is emitted by the 'registerIdentity' function - * `investorAddress` is the address of the investor's wallet - * `identity` is the address of the Identity smart contract (onchainID) - */ - event IdentityStored(address indexed investorAddress, IIdentity indexed identity); +/// @dev This event is emitted when an Identity is registered into the storage contract. +/// @param _investorAddress` is the address of the investor's wallet. +/// @param _identity` is the address of the Identity smart contract (onchainID). +event IdentityStored(address indexed _investorAddress, IIdentity indexed _identity); - /** - * this event is emitted when an Identity is removed from the storage contract. - * the event is emitted by the 'deleteIdentity' function - * `investorAddress` is the address of the investor's wallet - * `identity` is the address of the Identity smart contract (onchainID) - */ - event IdentityUnstored(address indexed investorAddress, IIdentity indexed identity); +/// @dev This event is emitted when an Identity is removed from the storage contract. +/// @param _investorAddress is the address of the investor's wallet. +/// @param _identity is the address of the Identity smart contract (onchainID). +event IdentityUnstored(address indexed _investorAddress, IIdentity indexed _identity); - /** - * this event is emitted when an Identity has been updated - * the event is emitted by the 'updateIdentity' function - * `oldIdentity` is the old Identity contract's address to update - * `newIdentity` is the new Identity contract's - */ - event IdentityModified(IIdentity indexed oldIdentity, IIdentity indexed newIdentity); +/// @dev This event is emitted when an Identity has been updated. +/// @param _oldIdentity is the old Identity contract's address to update. +/// @param _newIdentity is the new Identity contract's. +event IdentityModified(IIdentity indexed _oldIdentity, IIdentity indexed _newIdentity); - /** - * this event is emitted when an Identity's country has been updated - * the event is emitted by the 'updateCountry' function - * `investorAddress` is the address on which the country has been updated - * `country` is the numeric code (ISO 3166-1) of the new country - */ - event CountryModified(address indexed investorAddress, uint16 indexed country); +/// @dev This event is emitted when an Identity's country has been updated. +/// @param _investorAddress is the address on which the country has been updated. +/// @param _country is the numeric code (ISO 3166-1) of the new country. +event CountryModified(address indexed _investorAddress, uint16 indexed _country); - /** - * this event is emitted when an Identity Registry is bound to the storage contract - * the event is emitted by the 'addIdentityRegistry' function - * `identityRegistry` is the address of the identity registry added - */ - event IdentityRegistryBound(address indexed identityRegistry); +/// @dev This event is emitted when an Identity Registry is bound to the storage contract. +/// @param _identityRegistry is the address of the identity registry added. +event IdentityRegistryBound(address indexed _identityRegistry); - /** - * this event is emitted when an Identity Registry is unbound from the storage contract - * the event is emitted by the 'removeIdentityRegistry' function - * `identityRegistry` is the address of the identity registry removed - */ - event IdentityRegistryUnbound(address indexed identityRegistry); +/// @dev This event is emitted when an Identity Registry is unbound from the storage contract. +/// @param _identityRegistry is the address of the identity registry removed. +event IdentityRegistryUnbound(address indexed _identityRegistry); + + +interface IIdentityRegistryStorage { /// functions diff --git a/contracts/registry/interface/ITrustedIssuersRegistry.sol b/contracts/registry/interface/ITrustedIssuersRegistry.sol index 6ba19170..91fdabaa 100644 --- a/contracts/registry/interface/ITrustedIssuersRegistry.sol +++ b/contracts/registry/interface/ITrustedIssuersRegistry.sol @@ -65,29 +65,24 @@ pragma solidity 0.8.26; import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; -interface ITrustedIssuersRegistry { - /** - * this event is emitted when a trusted issuer is added in the registry. - * the event is emitted by the addTrustedIssuer function - * `trustedIssuer` is the address of the trusted issuer's ClaimIssuer contract - * `claimTopics` is the set of claims that the trusted issuer is allowed to emit - */ - event TrustedIssuerAdded(IClaimIssuer indexed trustedIssuer, uint256[] claimTopics); +/// Events - /** - * this event is emitted when a trusted issuer is removed from the registry. - * the event is emitted by the removeTrustedIssuer function - * `trustedIssuer` is the address of the trusted issuer's ClaimIssuer contract - */ - event TrustedIssuerRemoved(IClaimIssuer indexed trustedIssuer); +/// @dev This event is emitted when a trusted issuer is added in the registry. +/// @param _trustedIssuer is the address of the trusted issuer's ClaimIssuer contract. +/// @param _claimTopics is the set of claims that the trusted issuer is allowed to emit. +event TrustedIssuerAdded(IClaimIssuer indexed _trustedIssuer, uint256[] _claimTopics); - /** - * this event is emitted when the set of claim topics is changed for a given trusted issuer. - * the event is emitted by the updateIssuerClaimTopics function - * `trustedIssuer` is the address of the trusted issuer's ClaimIssuer contract - * `claimTopics` is the set of claims that the trusted issuer is allowed to emit - */ - event ClaimTopicsUpdated(IClaimIssuer indexed trustedIssuer, uint256[] claimTopics); +/// @dev This event is emitted when a trusted issuer is removed from the registry. +/// @param _trustedIssuer is the address of the trusted issuer's ClaimIssuer contract. +event TrustedIssuerRemoved(IClaimIssuer indexed _trustedIssuer); + +/// &dev This event is emitted when the set of claim topics is changed for a given trusted issuer. +/// @param _trustedIssuer is the address of the trusted issuer's ClaimIssuer contract +/// @param _claimTopics is the set of claims that the trusted issuer is allowed to emit. +event ClaimTopicsUpdated(IClaimIssuer indexed _trustedIssuer, uint256[] _claimTopics); + + +interface ITrustedIssuersRegistry { /** * @dev registers a ClaimIssuer contract as trusted claim issuer. diff --git a/contracts/roles/AgentRole.sol b/contracts/roles/AgentRole.sol index def7bfe0..7d76355a 100644 --- a/contracts/roles/AgentRole.sol +++ b/contracts/roles/AgentRole.sol @@ -69,14 +69,23 @@ import "./Roles.sol"; import "../errors/InvalidArgumentErrors.sol"; import "../errors/RoleErrors.sol"; + +/// Events + +/// @dev This event is emmited when an agent is added. +/// @param _agent Address of agent contract +event AgentAdded(address indexed _agent); + +/// @dev This event is emmited when an agent is removed. +/// @param _agent Address of agent contract +event AgentRemoved(address indexed _agent); + + contract AgentRole is Ownable { using Roles for Roles.Role; Roles.Role private _agents; - event AgentAdded(address indexed _agent); - event AgentRemoved(address indexed _agent); - modifier onlyAgent() { require(isAgent(msg.sender), CallerDoesNotHaveAgentRole()); _; diff --git a/contracts/roles/AgentRoleUpgradeable.sol b/contracts/roles/AgentRoleUpgradeable.sol index 46c419bc..f36588a6 100644 --- a/contracts/roles/AgentRoleUpgradeable.sol +++ b/contracts/roles/AgentRoleUpgradeable.sol @@ -69,14 +69,22 @@ import "./Roles.sol"; import "../errors/InvalidArgumentErrors.sol"; import "../errors/RoleErrors.sol"; +/// Events + +/// @dev This event is emmited when an agent is added. +/// @param _agent Address of agent contract +event AgentAdded(address indexed _agent); + +/// @dev This event is emmited when an agent is removed. +/// @param _agent Address of agent contract +event AgentRemoved(address indexed _agent); + + contract AgentRoleUpgradeable is OwnableUpgradeable { using Roles for Roles.Role; Roles.Role private _agents; - event AgentAdded(address indexed _agent); - event AgentRemoved(address indexed _agent); - modifier onlyAgent() { require(isAgent(msg.sender), CallerDoesNotHaveAgentRole()); _; diff --git a/contracts/roles/permissioning/agent/AgentRoles.sol b/contracts/roles/permissioning/agent/AgentRoles.sol index afd16004..c5709ae9 100644 --- a/contracts/roles/permissioning/agent/AgentRoles.sol +++ b/contracts/roles/permissioning/agent/AgentRoles.sol @@ -68,6 +68,19 @@ import "@openzeppelin/contracts/access/Ownable.sol"; import "../../Roles.sol"; import "../../../errors/RoleErrors.sol"; +/// events + +/// @dev This event is emmited when a role is added. +/// @param _agent Address of agent contract +/// @param _role Role label. +event RoleAdded(address indexed _agent, string _role); + +/// @dev This event is emmited when a role is removed. +/// @param _agent Address of agent contract +/// @param _role Role label. +event RoleRemoved(address indexed _agent, string _role); + + contract AgentRoles is Ownable { using Roles for Roles.Role; @@ -81,11 +94,6 @@ contract AgentRoles is Ownable { Roles.Role private _whiteListManagers; Roles.Role private _agentAdmin; - /// events - - event RoleAdded(address indexed _agent, string _role); - event RoleRemoved(address indexed _agent, string _role); - /// modifiers modifier onlyAdmin() { diff --git a/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol b/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol index 8b9b17c7..38e43210 100644 --- a/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol +++ b/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol @@ -68,9 +68,20 @@ import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../../Roles.sol"; import "../../../errors/RoleErrors.sol"; -contract AgentRolesUpgradeable is OwnableUpgradeable +/// events - { +/// @dev This event is emmited when a role is added. +/// @param _agent Address of agent contract +/// @param _role Role label. +event RoleAdded(address indexed _agent, string _role); + +/// @dev This event is emmited when a role is removed. +/// @param _agent Address of agent contract +/// @param _role Role label. +event RoleRemoved(address indexed _agent, string _role); + + +contract AgentRolesUpgradeable is OwnableUpgradeable { using Roles for Roles.Role; /// variables @@ -83,11 +94,6 @@ contract AgentRolesUpgradeable is OwnableUpgradeable Roles.Role private _whiteListManagers; Roles.Role private _agentAdmin; - /// events - - event RoleAdded(address indexed _agent, string _role); - event RoleRemoved(address indexed _agent, string _role); - /// modifiers modifier onlyAdmin() { diff --git a/contracts/roles/permissioning/owner/OwnerManager.sol b/contracts/roles/permissioning/owner/OwnerManager.sol index 2b4af567..96e0227e 100644 --- a/contracts/roles/permissioning/owner/OwnerManager.sol +++ b/contracts/roles/permissioning/owner/OwnerManager.sol @@ -74,17 +74,20 @@ import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; import "../../../errors/RoleErrors.sol"; +/// Events + +/// @dev Event emitted for each executed interaction with the compliance contract. +/// For gas efficiency, only the interaction calldata selector (first 4 bytes) is included in the event. +/// For interactions without calldata or whose calldata is shorter than 4 bytes, the selector will be `0`. +/// @param _target Address of compliance contract. +/// @param _selector See above comment. +event ComplianceInteraction(address indexed _target, bytes4 _selector); + + contract OwnerManager is OwnerRoles { /// @dev the token that is managed by this OwnerManager Contract IToken public token; - /// @dev Event emitted for each executed interaction with the compliance contract. - /// - /// For gas efficiency, only the interaction calldata selector (first 4 - /// bytes) is included in the event. For interactions without calldata or - /// whose calldata is shorter than 4 bytes, the selector will be `0`. - event ComplianceInteraction(address indexed target, bytes4 selector); - /** * @dev the constructor initiates the OwnerManager contract * and sets msg.sender as owner of the contract diff --git a/contracts/roles/permissioning/owner/OwnerRoles.sol b/contracts/roles/permissioning/owner/OwnerRoles.sol index f53d31da..291dfd6f 100644 --- a/contracts/roles/permissioning/owner/OwnerRoles.sol +++ b/contracts/roles/permissioning/owner/OwnerRoles.sol @@ -68,6 +68,19 @@ import "@openzeppelin/contracts/access/Ownable.sol"; import "../../Roles.sol"; import "../../../errors/RoleErrors.sol"; +/// Events + +/// @dev This event is emmited when a role is added. +/// @param _owner Address of contract +/// @param _role Role label. +event RoleAdded(address indexed _owner, string _role); + +/// @dev This event is emmited when a role is removed. +/// @param _owner Address of contract +/// @param _role Role label. +event RoleRemoved(address indexed _owner, string _role); + + contract OwnerRoles is Ownable { using Roles for Roles.Role; @@ -81,11 +94,6 @@ contract OwnerRoles is Ownable { Roles.Role private _issuersRegistryManager; Roles.Role private _tokenInfoManager; - /// events - - event RoleAdded(address indexed _owner, string _role); - event RoleRemoved(address indexed _owner, string _role); - /// modifiers modifier onlyAdmin() { diff --git a/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol b/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol index 237b5455..8a02d22d 100644 --- a/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol +++ b/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol @@ -68,9 +68,20 @@ import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../../Roles.sol"; import "../../../errors/RoleErrors.sol"; -contract OwnerRolesUpgradeable is OwnableUpgradeable +/// Events - { +/// @dev This event is emmited when a role is added. +/// @param _owner Address of contract +/// @param _role Role label. +event RoleAdded(address indexed _owner, string _role); + +/// @dev This event is emmited when a role is removed. +/// @param _owner Address of contract +/// @param _role Role label. +event RoleRemoved(address indexed _owner, string _role); + + +contract OwnerRolesUpgradeable is OwnableUpgradeable { using Roles for Roles.Role; /// variables @@ -83,11 +94,6 @@ contract OwnerRolesUpgradeable is OwnableUpgradeable Roles.Role private _issuersRegistryManager; Roles.Role private _tokenInfoManager; - /// events - - event RoleAdded(address indexed _owner, string _role); - event RoleRemoved(address indexed _owner, string _role); - /// modifiers modifier onlyAdmin() { diff --git a/contracts/token/IToken.sol b/contracts/token/IToken.sol index dd48f891..7266ccb8 100644 --- a/contracts/token/IToken.sol +++ b/contracts/token/IToken.sol @@ -68,109 +68,79 @@ import "../compliance/modular/IModularCompliance.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./TokenStructs.sol"; -/// @dev interface -interface IToken is IERC20 { - - /// events - - /** - * this event is emitted when the token information is updated. - * the event is emitted by the token init function and by the setTokenInformation function - * `_newName` is the name of the token - * `_newSymbol` is the symbol of the token - * `_newDecimals` is the decimals of the token - * `_newVersion` is the version of the token, current version is 3.0 - * `_newOnchainID` is the address of the onchainID of the token - */ - event UpdatedTokenInformation(string indexed _newName, string indexed _newSymbol, uint8 _newDecimals, string - _newVersion, address indexed _newOnchainID); - - /** - * this event is emitted when the IdentityRegistry has been set for the token - * the event is emitted by the token constructor and by the setIdentityRegistry function - * `_identityRegistry` is the address of the Identity Registry of the token - */ - event IdentityRegistryAdded(address indexed _identityRegistry); - - /** - * this event is emitted when the Compliance has been set for the token - * the event is emitted by the token constructor and by the setCompliance function - * `_compliance` is the address of the Compliance contract of the token - */ - event ComplianceAdded(address indexed _compliance); - - /** - * this event is emitted when an investor successfully recovers his tokens - * the event is emitted by the recoveryAddress function - * `_lostWallet` is the address of the wallet that the investor lost access to - * `_newWallet` is the address of the wallet that the investor provided for the recovery - * `_investorOnchainID` is the address of the onchainID of the investor who asked for a recovery - */ - event RecoverySuccess(address indexed _lostWallet, address indexed _newWallet, address indexed _investorOnchainID); - - /** - * this event is emitted when the wallet of an investor is frozen or unfrozen - * the event is emitted by setAddressFrozen and batchSetAddressFrozen functions - * `_userAddress` is the wallet of the investor that is concerned by the freezing status - * `_isFrozen` is the freezing status of the wallet - * if `_isFrozen` equals `true` the wallet is frozen after emission of the event - * if `_isFrozen` equals `false` the wallet is unfrozen after emission of the event - * `_owner` is the address of the agent who called the function to freeze the wallet - */ - event AddressFrozen(address indexed _userAddress, bool indexed _isFrozen, address indexed _owner); +/// events + +/// @dev This event is emitted when the token information is updated. +/// @param _newName is the name of the token. +/// @param _newSymbol is the symbol of the token. +/// @param _newDecimals is the decimals of the token. +/// @param _newVersion is the version of the token. +/// @param _newOnchainID is the address of the onchainID of the token. +event UpdatedTokenInformation(string indexed _newName, string indexed _newSymbol, uint8 _newDecimals, + string _newVersion, address indexed _newOnchainID); + +/// @dev This event is emitted when the IdentityRegistry has been set for the token. +/// @param _identityRegistry is the address of the Identity Registry of the token. +event IdentityRegistryAdded(address indexed _identityRegistry); + +/// @dev This event is emitted when the Compliance has been set for the token. +/// @param _compliance is the address of the Compliance contract of the token. +event ComplianceAdded(address indexed _compliance); + +/// @dev This event is emitted when an investor successfully recovers his tokens. +/// @param _lostWallet is the address of the wallet that the investor lost access to. +/// @param _newWallet is the address of the wallet that the investor provided for the recovery. +/// @param _investorOnchainID is the address of the onchainID of the investor who asked for a recovery. +event RecoverySuccess(address indexed _lostWallet, address indexed _newWallet, address indexed _investorOnchainID); + +/// @dev This event is emitted when the wallet of an investor is frozen or unfrozen. +/// @param _userAddress is the wallet of the investor that is concerned by the freezing status. +/// @param _isFrozen is the freezing status of the wallet. +/// @param _isFrozen equals `true` the wallet is frozen after emission of the event. +/// @param _isFrozen equals `false` the wallet is unfrozen after emission of the event. +/// @param _owner is the address of the agent who called the function to freeze the wallet. +event AddressFrozen(address indexed _userAddress, bool indexed _isFrozen, address indexed _owner); + +/// @dev This event is emitted when a certain amount of tokens is frozen on a wallet. +/// @param _userAddress is the wallet of the investor that is concerned by the freezing status. +/// @param _amount is the amount of tokens that are frozen. +event TokensFrozen(address indexed _userAddress, uint256 _amount); + +/// @dev This event is emitted when a certain amount of tokens is unfrozen on a wallet. +/// @param _userAddress is the wallet of the investor that is concerned by the freezing status. +/// @param _amount is the amount of tokens that are unfrozen. +event TokensUnfrozen(address indexed _userAddress, uint256 _amount); + +/// @dev This event is emitted when the token is paused. +/// @param _userAddress is the address of the wallet that called the pause function +event Paused(address _userAddress); + +/// @dev This event is emitted when the token is unpaused. +/// @param _userAddress is the address of the wallet that called the unpause function. +event Unpaused(address _userAddress); + +/// @dev This event is emitted when restrictions on an agent's roles are updated. +/// @param _agent is the address of the agent whose roles are being restricted. +/// @param _disableMint indicates whether the agent is restricted from minting tokens. +/// @param _disableBurn indicates whether the agent is restricted from burning tokens. +/// @param _disableAddressFreeze indicates whether the agent is restricted from freezing addresses. +/// @param _disableForceTransfer indicates whether the agent is restricted from forcing transfers. +/// @param _disablePartialFreeze indicates whether the agent is restricted from partially freezing tokens. +/// @param _disablePause indicates whether the agent is restricted from pausing the token contract. +/// @param _disableRecovery indicates whether the agent is restricted from performing recovery operations. +event AgentRestrictionsSet( + address indexed _agent, + bool _disableMint, + bool _disableBurn, + bool _disableAddressFreeze, + bool _disableForceTransfer, + bool _disablePartialFreeze, + bool _disablePause, + bool _disableRecovery); - /** - * this event is emitted when a certain amount of tokens is frozen on a wallet - * the event is emitted by freezePartialTokens and batchFreezePartialTokens functions - * `_userAddress` is the wallet of the investor that is concerned by the freezing status - * `_amount` is the amount of tokens that are frozen - */ - event TokensFrozen(address indexed _userAddress, uint256 _amount); - - /** - * this event is emitted when a certain amount of tokens is unfrozen on a wallet - * the event is emitted by unfreezePartialTokens and batchUnfreezePartialTokens functions - * `_userAddress` is the wallet of the investor that is concerned by the freezing status - * `_amount` is the amount of tokens that are unfrozen - */ - event TokensUnfrozen(address indexed _userAddress, uint256 _amount); - - /** - * this event is emitted when the token is paused - * the event is emitted by the pause function - * `_userAddress` is the address of the wallet that called the pause function - */ - event Paused(address _userAddress); - /** - * this event is emitted when the token is unpaused - * the event is emitted by the unpause function - * `_userAddress` is the address of the wallet that called the unpause function - */ - event Unpaused(address _userAddress); - - - /** - * This event is emitted when restrictions on an agent's roles are updated. - * The event is emitted by the `setAgentRestrictions` function. - * `agent` is the address of the agent whose roles are being restricted. - * `disableMint` indicates whether the agent is restricted from minting tokens. - * `disableBurn` indicates whether the agent is restricted from burning tokens. - * `disableAddressFreeze` indicates whether the agent is restricted from freezing addresses. - * `disableForceTransfer` indicates whether the agent is restricted from forcing transfers. - * `disablePartialFreeze` indicates whether the agent is restricted from partially freezing tokens. - * `disablePause` indicates whether the agent is restricted from pausing the token contract. - * `disableRecovery` indicates whether the agent is restricted from performing recovery operations. - */ - event AgentRestrictionsSet( - address indexed agent, - bool disableMint, - bool disableBurn, - bool disableAddressFreeze, - bool disableForceTransfer, - bool disablePartialFreeze, - bool disablePause, - bool disableRecovery ); +/// @dev interface +interface IToken is IERC20 { /// functions From 0395ed8a6537cad33f7d098fe9ad199a0fb89cf5 Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Fri, 16 Aug 2024 14:30:25 +0200 Subject: [PATCH 30/55] TREX-129 default allowance from develop (#215) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨() TREX-129 Default allowance * ✅(test) TREX-129 Add tests * ✅(test) TREX-129 Add more tests * 🐛() TREX-129 update after review * 🐛() TREX-129 update after review 2 * 🔧(Token) improve global allowance logic * 📝(CHANGELOG) update changelog --------- Co-authored-by: joachimlebrun --- .solhint.json | 5 +- CHANGELOG.md | 11 + contracts/errors/CommonErrors.sol | 6 + contracts/token/IToken.sol | 31 ++ contracts/token/Token.sol | 43 ++- contracts/token/TokenStorage.sol | 6 +- hardhat.config.ts | 1 + package-lock.json | 567 ++++++++++-------------------- package.json | 3 + test/token/token-transfer.test.ts | 118 +++++++ 10 files changed, 414 insertions(+), 377 deletions(-) diff --git a/.solhint.json b/.solhint.json index 826a2bcb..9e7603d4 100644 --- a/.solhint.json +++ b/.solhint.json @@ -21,14 +21,15 @@ "code-complexity": ["error", 7], "function-max-lines": ["error", 50], "max-line-length": ["error", 130], - "max-states-count": ["error", 15], + "max-states-count": ["warn", 15], "no-empty-blocks": "error", "no-unused-vars": "error", "payable-fallback": "error", "constructor-syntax": "error", "not-rely-on-time": "off", "reason-string": "off", - "no-global-import": "off" + "no-global-import": "off", + "gas-custom-errors": "off" }, "plugins": ["prettier"] } diff --git a/CHANGELOG.md b/CHANGELOG.md index 78384da2..7502e735 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,17 @@ # Change Log All notable changes to this project will be documented in this file. +## [4.2.0] + +### Added + +- **Default Allowance Mechanism**: + - Introduced a new feature allowing the contract owner to set certain addresses as trusted external smart contracts, enabling them to use `transferFrom` without requiring an explicit allowance from users. By default, users are opted in, allowing these contracts to have an "infinite allowance". Users can opt-out if they prefer to control allowances manually. + - Added custom errors and events to provide better feedback and traceability: + - Custom errors: `DefaultAllowanceAlreadyEnabled`, `DefaultAllowanceAlreadyDisabled`, `DefaultAllowanceAlreadySet`. + - Events: `DefaultAllowance`, `DefaultAllowanceDisabled`, `DefaultAllowanceEnabled`. + - Enhanced the `allowance` function to return `type(uint256).max` for addresses with default allowance enabled, unless the user has opted out. + ## [4.1.5] ### Update diff --git a/contracts/errors/CommonErrors.sol b/contracts/errors/CommonErrors.sol index fc9b9249..b2045473 100644 --- a/contracts/errors/CommonErrors.sol +++ b/contracts/errors/CommonErrors.sol @@ -121,3 +121,9 @@ error EnforcedPause(); * @dev The operation failed because the contract is not paused. */ error ExpectedPause(); + +/** +* @dev The operation failed because the input array is too big. +* @param _maxSize maximum size for the array. +*/ +error ArraySizeLimited(uint256 _maxSize); diff --git a/contracts/token/IToken.sol b/contracts/token/IToken.sol index 7266ccb8..9709da05 100644 --- a/contracts/token/IToken.sol +++ b/contracts/token/IToken.sol @@ -138,6 +138,18 @@ event AgentRestrictionsSet( bool _disablePause, bool _disableRecovery); +/// @dev This event is emitted when the owner gives or cancels a default allowance. +/// @param _to Address of target. +/// @param _allowance Allowance or disallowance. +event DefaultAllowance(address _to, bool _allowance); + +/// @dev This event is emitted when a user remove the default allowance. +/// @param _user Address of user. +event DefaultAllowanceDisabled(address _user); + +/// @dev This event is emitted when a user adds the default allowance back after disabling. +/// @param _user Address of user. +event DefaultAllowanceEnabled(address _user); /// @dev interface interface IToken is IERC20 { @@ -325,6 +337,24 @@ interface IToken is IERC20 { address _investorOnchainID ) external returns (bool); + /** + * @dev The owner of this address can allow or disallow spending without allowance. + * Any `TransferFrom` from these targets won't need allowance (allow = true) or will need allowance (allow = false). + * @param _allow Allow or disallow spending without allowance. + * @param _targets Addresses without allowance needed. + */ + function setAllowanceForAll(bool _allow, address[] calldata _targets) external; + + /** + * @dev The caller can remove default allowance globally. + */ + function disableDefaultAllowance() external; + + /** + * @dev The caller can get default allowance back globally. + */ + function enableDefaultAllowance() external; + /** * @dev function allowing to issue transfers in batch * Require that the msg.sender and `to` addresses are not frozen. @@ -518,4 +548,5 @@ interface IToken is IERC20 { * Each flag set to `true` disables the corresponding capability for the agent. */ function getAgentRestrictions(address agent) external view returns (TokenRoles memory); + } diff --git a/contracts/token/Token.sol b/contracts/token/Token.sol index ac9171d1..aa4114b2 100755 --- a/contracts/token/Token.sol +++ b/contracts/token/Token.sol @@ -107,6 +107,15 @@ error TransferNotPossible(); /// @dev Thrown when identity is not verified. error UnverifiedIdentity(); +/// @dev Thrown when default allowance is already enabled for _user. +error DefaultAllowanceAlreadyEnabled(address _user); + +/// @dev Thrown when default allowance is already disabled for _user. +error DefaultAllowanceAlreadyDisabled(address _user); + +/// @dev Thrown when default allowance is already set for _target. +error DefaultAllowanceAlreadySet(address _target); + contract Token is IToken, AgentRoleUpgradeable, TokenStorage { @@ -288,7 +297,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { uint256 balance = balanceOf(_from) - (_frozenTokens[_from]); require(_amount <= balance, ERC20InsufficientBalance(_from, balance, _amount)); if (_tokenIdentityRegistry.isVerified(_to) && _tokenCompliance.canTransfer(_from, _to, _amount)) { - _approve(_from, msg.sender, _allowances[_from][msg.sender] - (_amount)); + if (!_defaultAllowances[msg.sender] || _defaultAllowanceOptOuts[_from]) { + _approve(_from, msg.sender, _allowances[_from][msg.sender] - (_amount)); + } _transfer(_from, _to, _amount); _tokenCompliance.transferred(_from, _to, _amount); return true; @@ -385,6 +396,31 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { revert RecoveryNotPossible(); } + /// @dev See {IToken-setAllowanceForAll}. + function setAllowanceForAll(bool _allow, address[] calldata _targets) external override onlyOwner { + uint256 targetsCount = _targets.length; + require(targetsCount <= 100, ArraySizeLimited(100)); + for (uint256 i = 0; i < targetsCount; i++) { + require(_defaultAllowances[_targets[i]] != _allow, DefaultAllowanceAlreadySet(_targets[i])); + _defaultAllowances[_targets[i]] = _allow; + emit DefaultAllowance(_targets[i], _allow); + } + } + + /// @dev See {IToken-disableDefaultAllowance}. + function disableDefaultAllowance() external override { + require(!_defaultAllowanceOptOuts[msg.sender], DefaultAllowanceAlreadyDisabled(msg.sender)); + _defaultAllowanceOptOuts[msg.sender] = true; + emit DefaultAllowanceDisabled(msg.sender); + } + + /// @dev See {IToken-enableDefaultAllowance}. + function enableDefaultAllowance() external override { + require(_defaultAllowanceOptOuts[msg.sender], DefaultAllowanceAlreadyEnabled(msg.sender)); + _defaultAllowanceOptOuts[msg.sender] = false; + emit DefaultAllowanceEnabled(msg.sender); + } + /** * @dev See {IERC20-totalSupply}. */ @@ -396,6 +432,10 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { * @dev See {IERC20-allowance}. */ function allowance(address _owner, address _spender) external view virtual override returns (uint256) { + if (_defaultAllowances[_spender] && !_defaultAllowanceOptOuts[_owner]) { + return type(uint256).max; + } + return _allowances[_owner][_spender]; } @@ -676,4 +716,5 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { */ // solhint-disable-next-line no-empty-blocks function _beforeTokenTransfer(address _from, address _to, uint256 _amount) internal virtual {} + } diff --git a/contracts/token/TokenStorage.sol b/contracts/token/TokenStorage.sol index 6f4a820b..1ce25063 100644 --- a/contracts/token/TokenStorage.sol +++ b/contracts/token/TokenStorage.sol @@ -93,9 +93,13 @@ contract TokenStorage { mapping(address => TokenRoles) internal _agentsRestrictions; + mapping(address spender => bool allowance) internal _defaultAllowances; + + mapping(address user => bool optOut) internal _defaultAllowanceOptOuts; + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. */ - uint256[48] private __gap; + uint256[46] private __gap; } diff --git a/hardhat.config.ts b/hardhat.config.ts index e86b1ea8..421a3c58 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -5,6 +5,7 @@ import '@openzeppelin/hardhat-upgrades'; import 'solidity-coverage'; import '@nomiclabs/hardhat-solhint'; import '@primitivefi/hardhat-dodoc'; +import 'hardhat-tracer'; const config: HardhatUserConfig = { solidity: { diff --git a/package-lock.json b/package-lock.json index 632fca09..246cfc8a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,9 @@ "name": "@tokenysolutions/t-rex", "version": "4.2.0-beta1", "license": "SEE LICENSE IN LICENSE.md", + "dependencies": { + "hardhat-tracer": "^3.0.3" + }, "devDependencies": { "@commitlint/cli": "^19.3.0", "@nomicfoundation/hardhat-toolbox": "^5.0.0", @@ -428,7 +431,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, + "devOptional": true, "peer": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" @@ -637,7 +640,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", - "dev": true, "funding": [ { "type": "individual", @@ -664,7 +666,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", - "dev": true, "funding": [ { "type": "individual", @@ -689,7 +690,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", - "dev": true, "funding": [ { "type": "individual", @@ -712,7 +712,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", - "dev": true, "funding": [ { "type": "individual", @@ -735,7 +734,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", - "dev": true, "funding": [ { "type": "individual", @@ -754,7 +752,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", - "dev": true, "funding": [ { "type": "individual", @@ -774,7 +771,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", - "dev": true, "funding": [ { "type": "individual", @@ -795,7 +791,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", - "dev": true, "funding": [ { "type": "individual", @@ -814,7 +809,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", - "dev": true, "funding": [ { "type": "individual", @@ -833,7 +827,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", - "dev": true, "funding": [ { "type": "individual", @@ -861,7 +854,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", - "dev": true, "funding": [ { "type": "individual", @@ -888,7 +880,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", - "dev": true, "funding": [ { "type": "individual", @@ -918,7 +909,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", - "dev": true, "funding": [ { "type": "individual", @@ -948,14 +938,12 @@ "node_modules/@ethersproject/json-wallets/node_modules/aes-js": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", - "dev": true + "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==" }, "node_modules/@ethersproject/keccak256": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", - "dev": true, "funding": [ { "type": "individual", @@ -975,7 +963,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", - "dev": true, "funding": [ { "type": "individual", @@ -991,7 +978,6 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", - "dev": true, "funding": [ { "type": "individual", @@ -1010,7 +996,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", - "dev": true, "funding": [ { "type": "individual", @@ -1030,7 +1015,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", - "dev": true, "funding": [ { "type": "individual", @@ -1049,7 +1033,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", - "dev": true, "funding": [ { "type": "individual", @@ -1087,7 +1070,6 @@ "version": "7.4.6", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "dev": true, "engines": { "node": ">=8.3.0" }, @@ -1108,7 +1090,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", - "dev": true, "funding": [ { "type": "individual", @@ -1128,7 +1109,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", - "dev": true, "funding": [ { "type": "individual", @@ -1148,7 +1128,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", - "dev": true, "funding": [ { "type": "individual", @@ -1169,7 +1148,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", - "dev": true, "funding": [ { "type": "individual", @@ -1193,7 +1171,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", - "dev": true, "funding": [ { "type": "individual", @@ -1217,7 +1194,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", - "dev": true, "funding": [ { "type": "individual", @@ -1238,7 +1214,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", - "dev": true, "funding": [ { "type": "individual", @@ -1265,7 +1240,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", - "dev": true, "funding": [ { "type": "individual", @@ -1286,7 +1260,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", - "dev": true, "funding": [ { "type": "individual", @@ -1319,7 +1292,6 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", - "dev": true, "funding": [ { "type": "individual", @@ -1342,7 +1314,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", - "dev": true, "funding": [ { "type": "individual", @@ -1365,7 +1336,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "dev": true, "engines": { "node": ">=14" } @@ -1513,7 +1483,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, + "devOptional": true, "peer": true, "engines": { "node": ">=6.0.0" @@ -1523,14 +1493,14 @@ "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true, + "devOptional": true, "peer": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, + "devOptional": true, "peer": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", @@ -1541,7 +1511,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz", "integrity": "sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==", - "dev": true, "dependencies": { "ethereumjs-abi": "^0.6.8", "ethereumjs-util": "^6.2.1", @@ -1557,7 +1526,6 @@ "version": "4.11.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -1565,14 +1533,12 @@ "node_modules/@metamask/eth-sig-util/node_modules/bn.js": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, "node_modules/@metamask/eth-sig-util/node_modules/ethereum-cryptography": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -1595,7 +1561,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, "dependencies": { "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", @@ -1636,7 +1601,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", - "dev": true, "funding": [ { "type": "individual", @@ -1648,7 +1612,6 @@ "version": "1.7.1", "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", - "dev": true, "funding": [ { "type": "individual", @@ -1695,7 +1658,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.4.1.tgz", "integrity": "sha512-NgrMo2rI9r28uidumvd+K2/AJLdxtXsUlJr3hj/pM6S1FCd/HiWaLeLa/cjCVPcE2u1rYAa3W6UFxLCB7S5Dhw==", - "dev": true, "license": "MIT", "dependencies": { "@nomicfoundation/edr-darwin-arm64": "0.4.1", @@ -1714,7 +1676,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.4.1.tgz", "integrity": "sha512-XuiUUnWAVNw7JYv7nRqDWfpBm21HOxCRBQ8lQnRnmiets9Ss2X5Ul9mvBheIPh/D0wBzwJ8TRtsSrorpwE79cA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 18" @@ -1724,7 +1685,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.4.1.tgz", "integrity": "sha512-N1MfJqEX5ixaXlyyrHnaYxzwIT27Nc/jUgLI7ts4/9kRvPTvyZRYmXS1ciKhmUFr/WvFckTCix2RJbZoGGtX7g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 18" @@ -1734,7 +1694,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.4.1.tgz", "integrity": "sha512-bSPOfmcFjJwDgWOV5kgZHeqg2OWu1cINrHSGjig0aVHehjcoX4Sgayrj6fyAxcOV5NQKA6WcyTFll6NrCxzWRA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 18" @@ -1744,7 +1703,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.4.1.tgz", "integrity": "sha512-F/+DgOdeBFQDrk+SX4aFffJFBgJfd75ZtE2mjcWNAh/qWiS7NfUxdQX/5OvNo/H6EY4a+3bZH6Bgzqg4mEWvMw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 18" @@ -1754,7 +1712,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.4.1.tgz", "integrity": "sha512-POHhTWczIXCPhzKtY0Vt/l+VCqqCx5gNR5ErwSrNnLz/arfQobZFAU+nc61BX3Jch82TW8b3AbfGI73Kh7gO0w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 18" @@ -1764,7 +1721,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.4.1.tgz", "integrity": "sha512-uu8oNp4Ozg3H1x1We0FF+rwXfFiAvsOm5GQ+OBx9YYOXnfDPWqguQfGIkhrti9GD0iYhfQ/WOG5wvp0IzzgGSg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 18" @@ -1774,7 +1730,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.4.1.tgz", "integrity": "sha512-PaZHFw455z89ZiKYNTnKu+/TiVZVRI+mRJsbRTe2N0VlYfUBS1o2gdXBM12oP1t198HR7xQwEPPAslTFxGBqHA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 18" @@ -1784,7 +1739,6 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz", "integrity": "sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==", - "dev": true, "dependencies": { "@nomicfoundation/ethereumjs-util": "9.0.4" } @@ -1793,7 +1747,6 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz", "integrity": "sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==", - "dev": true, "bin": { "rlp": "bin/rlp.cjs" }, @@ -1805,7 +1758,6 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz", "integrity": "sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==", - "dev": true, "dependencies": { "@nomicfoundation/ethereumjs-common": "4.0.4", "@nomicfoundation/ethereumjs-rlp": "5.0.4", @@ -1828,7 +1780,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -1851,7 +1802,6 @@ "version": "9.0.4", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz", "integrity": "sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==", - "dev": true, "dependencies": { "@nomicfoundation/ethereumjs-rlp": "5.0.4", "ethereum-cryptography": "0.1.3" @@ -1872,7 +1822,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -2251,7 +2200,6 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz", "integrity": "sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg==", - "dev": true, "engines": { "node": ">= 12" }, @@ -2275,7 +2223,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -2291,7 +2238,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -2307,7 +2253,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -2323,7 +2268,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -2339,7 +2283,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -2355,7 +2298,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -2371,7 +2313,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -2387,7 +2328,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -2403,7 +2343,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "win32" @@ -2419,7 +2358,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -3058,7 +2996,6 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==", - "dev": true, "funding": { "url": "https://paulmillr.com/funding/" } @@ -3067,7 +3004,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", - "dev": true, "funding": [ { "type": "individual", @@ -3084,7 +3020,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", - "dev": true, "funding": [ { "type": "individual", @@ -3100,7 +3035,6 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==", - "dev": true, "dependencies": { "@sentry/hub": "5.30.0", "@sentry/minimal": "5.30.0", @@ -3116,7 +3050,6 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==", - "dev": true, "dependencies": { "@sentry/types": "5.30.0", "@sentry/utils": "5.30.0", @@ -3130,7 +3063,6 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==", - "dev": true, "dependencies": { "@sentry/hub": "5.30.0", "@sentry/types": "5.30.0", @@ -3144,7 +3076,6 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz", "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==", - "dev": true, "dependencies": { "@sentry/core": "5.30.0", "@sentry/hub": "5.30.0", @@ -3164,7 +3095,6 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==", - "dev": true, "dependencies": { "@sentry/hub": "5.30.0", "@sentry/minimal": "5.30.0", @@ -3180,7 +3110,6 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==", - "dev": true, "engines": { "node": ">=6" } @@ -3189,7 +3118,6 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", - "dev": true, "dependencies": { "@sentry/types": "5.30.0", "tslib": "^1.9.3" @@ -3253,28 +3181,28 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true, + "devOptional": true, "peer": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, + "devOptional": true, "peer": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, + "devOptional": true, "peer": true }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true, + "devOptional": true, "peer": true }, "node_modules/@typechain/ethers-v6": { @@ -3329,7 +3257,6 @@ "version": "5.1.5", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -3404,8 +3331,7 @@ "node_modules/@types/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", - "dev": true + "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==" }, "node_modules/@types/minimatch": { "version": "5.1.2", @@ -3425,7 +3351,6 @@ "version": "20.12.12", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", - "dev": true, "dependencies": { "undici-types": "~5.26.4" } @@ -3434,7 +3359,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -3456,7 +3380,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -3672,7 +3595,7 @@ "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, + "devOptional": true, "bin": { "acorn": "bin/acorn" }, @@ -3693,7 +3616,7 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", - "dev": true, + "devOptional": true, "peer": true, "engines": { "node": ">=0.4.0" @@ -3703,7 +3626,6 @@ "version": "0.4.16", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", - "dev": true, "engines": { "node": ">=0.3.0" } @@ -3719,7 +3641,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, "dependencies": { "debug": "4" }, @@ -3731,7 +3652,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -3784,7 +3704,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, "dependencies": { "string-width": "^4.1.0" } @@ -3793,7 +3712,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -3802,7 +3720,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3816,7 +3733,6 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, "engines": { "node": ">=6" } @@ -3825,7 +3741,6 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, "dependencies": { "type-fest": "^0.21.3" }, @@ -3840,7 +3755,6 @@ "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, "engines": { "node": ">=10" }, @@ -3852,7 +3766,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -3888,7 +3801,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -3901,14 +3813,13 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, + "devOptional": true, "peer": true }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/array-back": { "version": "3.1.0", @@ -4089,7 +4000,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, "peer": true, "engines": { "node": "*" @@ -4171,14 +4081,12 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base-x": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", - "dev": true, "dependencies": { "safe-buffer": "^5.0.1" } @@ -4206,14 +4114,12 @@ "node_modules/bech32": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "dev": true + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, "engines": { "node": ">=8" }, @@ -4224,20 +4130,17 @@ "node_modules/blakejs": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", - "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", - "dev": true + "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==" }, "node_modules/bn.js": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "dev": true + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" }, "node_modules/boxen": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", - "dev": true, "dependencies": { "ansi-align": "^3.0.0", "camelcase": "^6.2.0", @@ -4259,7 +4162,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -4274,7 +4176,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4290,7 +4191,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -4301,14 +4201,12 @@ "node_modules/boxen/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/boxen/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -4317,7 +4215,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -4331,7 +4228,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -4343,7 +4239,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -4352,7 +4247,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, "dependencies": { "fill-range": "^7.1.1" }, @@ -4363,20 +4257,17 @@ "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", - "dev": true + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" }, "node_modules/browserify-aes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, "dependencies": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", @@ -4390,7 +4281,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "dev": true, "dependencies": { "base-x": "^3.0.2" } @@ -4399,7 +4289,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dev": true, "dependencies": { "bs58": "^4.0.0", "create-hash": "^1.1.0", @@ -4420,20 +4309,17 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", - "dev": true + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -4509,7 +4395,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, "engines": { "node": ">=10" }, @@ -4540,7 +4425,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", - "dev": true, "peer": true, "dependencies": { "assertion-error": "^1.1.0", @@ -4593,7 +4477,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, "peer": true, "dependencies": { "get-func-name": "^2.0.2" @@ -4606,7 +4489,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -4630,7 +4512,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -4641,14 +4522,12 @@ "node_modules/ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" }, "node_modules/cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -4658,7 +4537,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, "engines": { "node": ">=6" } @@ -4667,7 +4545,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true, "engines": { "node": ">=6" }, @@ -4813,7 +4690,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -4821,8 +4697,7 @@ "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/colorette": { "version": "2.0.20", @@ -4855,7 +4730,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", - "dev": true, "license": "MIT" }, "node_modules/command-line-args": { @@ -4999,8 +4873,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/concat-stream": { "version": "1.6.2", @@ -5103,7 +4976,6 @@ "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -5161,7 +5033,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, "dependencies": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -5174,7 +5045,6 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, "dependencies": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", @@ -5188,7 +5058,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, + "devOptional": true, "peer": true }, "node_modules/cross-spawn": { @@ -5288,7 +5158,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -5305,7 +5174,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, "engines": { "node": ">=10" }, @@ -5344,7 +5212,6 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", - "dev": true, "peer": true, "dependencies": { "type-detect": "^4.0.0" @@ -5424,7 +5291,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -5433,7 +5299,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, "engines": { "node": ">=0.3.1" } @@ -5497,7 +5362,6 @@ "version": "6.5.4", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dev": true, "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -5511,14 +5375,12 @@ "node_modules/elliptic/node_modules/bn.js": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/enhanced-resolve": { "version": "5.16.1", @@ -5537,7 +5399,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", - "dev": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -5550,7 +5411,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, "engines": { "node": ">=6" } @@ -5701,7 +5561,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, "engines": { "node": ">=6" } @@ -5710,7 +5569,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "engines": { "node": ">=10" }, @@ -6501,7 +6359,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", - "dev": true, "dependencies": { "@noble/hashes": "1.2.0", "@noble/secp256k1": "1.7.1", @@ -6513,7 +6370,6 @@ "version": "0.6.8", "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", - "dev": true, "dependencies": { "bn.js": "^4.11.8", "ethereumjs-util": "^6.0.0" @@ -6523,7 +6379,6 @@ "version": "4.11.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -6531,14 +6386,12 @@ "node_modules/ethereumjs-abi/node_modules/bn.js": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, "node_modules/ethereumjs-abi/node_modules/ethereum-cryptography": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -6561,7 +6414,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, "dependencies": { "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", @@ -6693,7 +6545,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "dev": true, "dependencies": { "is-hex-prefixed": "1.0.0", "strip-hex-prefix": "1.0.0" @@ -6713,7 +6564,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, "dependencies": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" @@ -6825,7 +6675,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -6867,7 +6716,6 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, "bin": { "flat": "cli.js" } @@ -6896,7 +6744,6 @@ "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true, "funding": [ { "type": "individual", @@ -6963,8 +6810,7 @@ "node_modules/fp-ts": { "version": "1.19.3", "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", - "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==", - "dev": true + "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==" }, "node_modules/fs-extra": { "version": "11.2.0", @@ -6989,14 +6835,12 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -7046,7 +6890,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -7067,7 +6910,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, "peer": true, "engines": { "node": "*" @@ -7434,8 +7276,7 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/graphemer": { "version": "1.4.0", @@ -7479,7 +7320,6 @@ "version": "2.22.6", "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.6.tgz", "integrity": "sha512-abFEnd9QACwEtSvZZGSmzvw7N3zhQN1cDKz5SLHAupfG24qTHofCjqvD5kT5Wwsq5XOL0ON1Mq5rr4v0XX5ciw==", - "dev": true, "license": "MIT", "dependencies": { "@ethersproject/abi": "^5.1.2", @@ -7557,11 +7397,135 @@ "hardhat": "^2.0.2" } }, + "node_modules/hardhat-tracer": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/hardhat-tracer/-/hardhat-tracer-3.0.3.tgz", + "integrity": "sha512-Uto+JQGayzZRnwdUyM1Un0zmFth+j3jkijHxls75BCTEBHXvAilUO20UloT+b2DYWVCcKn5GRuRpxjSQEV4QYg==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "debug": "^4.3.4", + "ethers": "^5.6.1", + "semver": "^7.6.2" + }, + "peerDependencies": { + "chai": "4.x", + "hardhat": ">=2.22.5 <3.x" + } + }, + "node_modules/hardhat-tracer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/hardhat-tracer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/hardhat-tracer/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/hardhat-tracer/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/hardhat-tracer/node_modules/ethers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", + "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.1", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.2", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.1", + "@ethersproject/wordlists": "5.7.0" + } + }, + "node_modules/hardhat-tracer/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/hardhat/node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -7573,7 +7537,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7583,7 +7546,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -7597,7 +7559,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "engines": { "node": ">=0.8.0" } @@ -7606,7 +7567,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "dev": true, "dependencies": { "locate-path": "^2.0.0" }, @@ -7618,7 +7578,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -7633,7 +7592,6 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -7653,7 +7611,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "engines": { "node": ">=4" } @@ -7662,7 +7619,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -7671,7 +7627,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "dev": true, "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -7684,7 +7639,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -7696,7 +7650,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, "dependencies": { "p-try": "^1.0.0" }, @@ -7708,7 +7661,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "dev": true, "dependencies": { "p-limit": "^1.1.0" }, @@ -7720,7 +7672,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, "engines": { "node": ">=4" } @@ -7729,7 +7680,6 @@ "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, "dependencies": { "path-parse": "^1.0.6" }, @@ -7741,7 +7691,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -7750,7 +7699,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -7762,7 +7710,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, "engines": { "node": ">= 4.0.0" } @@ -7771,7 +7718,6 @@ "version": "7.5.9", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "dev": true, "engines": { "node": ">=8.3.0" }, @@ -7801,7 +7747,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -7861,7 +7806,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, "dependencies": { "inherits": "^2.0.4", "readable-stream": "^3.6.0", @@ -7875,7 +7819,6 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" @@ -7897,7 +7840,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, "bin": { "he": "bin/he" } @@ -7913,7 +7855,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dev": true, "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -7945,7 +7886,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -7989,7 +7929,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -8026,7 +7965,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -8077,8 +8015,7 @@ "node_modules/immutable": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz", - "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==", - "dev": true + "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==" }, "node_modules/import-fresh": { "version": "3.3.0", @@ -8128,7 +8065,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, "engines": { "node": ">=8" } @@ -8138,7 +8074,6 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -8147,8 +8082,7 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ini": { "version": "4.1.1", @@ -8187,7 +8121,6 @@ "version": "1.10.4", "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz", "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==", - "dev": true, "dependencies": { "fp-ts": "^1.0.0" } @@ -8230,7 +8163,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -8312,7 +8244,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -8333,7 +8264,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -8345,7 +8275,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", "integrity": "sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==", - "dev": true, "engines": { "node": ">=6.5.0", "npm": ">=3" @@ -8367,7 +8296,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -8409,7 +8337,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, "engines": { "node": ">=8" } @@ -8518,7 +8445,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, "engines": { "node": ">=10" }, @@ -8596,8 +8522,7 @@ "node_modules/js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "dev": true + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" }, "node_modules/js-tokens": { "version": "4.0.0", @@ -8609,7 +8534,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -8711,7 +8635,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", - "dev": true, "hasInstallScript": true, "dependencies": { "node-addon-api": "^2.0.0", @@ -8926,8 +8849,7 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "node_modules/lodash.camelcase": { "version": "4.3.0", @@ -9007,7 +8929,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -9023,7 +8944,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -9038,7 +8958,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -9054,7 +8973,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -9065,14 +8983,12 @@ "node_modules/log-symbols/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/log-symbols/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -9213,7 +9129,6 @@ "version": "2.3.7", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "dev": true, "peer": true, "dependencies": { "get-func-name": "^2.0.1" @@ -9234,8 +9149,7 @@ "node_modules/lru_map": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", - "dev": true + "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==" }, "node_modules/lru-cache": { "version": "10.2.2", @@ -9250,7 +9164,7 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, + "devOptional": true, "peer": true }, "node_modules/markdown-table": { @@ -9263,7 +9177,6 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1", @@ -9274,7 +9187,6 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", - "dev": true, "engines": { "node": ">= 0.10.0" } @@ -9374,14 +9286,12 @@ "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" }, "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", - "dev": true + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" }, "node_modules/minimatch": { "version": "9.0.4", @@ -9433,7 +9343,6 @@ "version": "0.38.5", "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", "integrity": "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==", - "dev": true, "dependencies": { "obliterator": "^2.0.0" } @@ -9442,7 +9351,6 @@ "version": "10.4.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", - "dev": true, "dependencies": { "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", @@ -9477,7 +9385,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, "engines": { "node": ">=6" } @@ -9486,7 +9393,6 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, "funding": [ { "type": "individual", @@ -9513,7 +9419,6 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -9524,7 +9429,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -9541,7 +9445,6 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -9560,7 +9463,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -9572,7 +9474,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -9581,7 +9482,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -9596,7 +9496,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -9607,14 +9506,12 @@ "node_modules/mocha/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/mocha/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -9629,7 +9526,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -9644,7 +9540,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "engines": { "node": ">=8" } @@ -9653,7 +9548,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -9667,7 +9561,6 @@ "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -9685,7 +9578,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, "engines": { "node": ">=10" }, @@ -9696,8 +9588,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -9745,8 +9636,7 @@ "node_modules/node-addon-api": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", - "dev": true + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" }, "node_modules/node-emoji": { "version": "1.11.0", @@ -9782,7 +9672,6 @@ "version": "4.8.1", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", - "dev": true, "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", @@ -9815,7 +9704,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -9992,14 +9880,12 @@ "node_modules/obliterator": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", - "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==", - "dev": true + "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==" }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "dependencies": { "wrappy": "1" } @@ -10047,7 +9933,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -10096,7 +9981,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, "dependencies": { "aggregate-error": "^3.0.0" }, @@ -10111,7 +9995,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "dev": true, "engines": { "node": ">=4" } @@ -10183,7 +10066,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -10200,8 +10082,7 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-scurry": { "version": "1.11.1", @@ -10232,7 +10113,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, "peer": true, "engines": { "node": "*" @@ -10242,7 +10122,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dev": true, "dependencies": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", @@ -10264,7 +10143,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -10498,7 +10376,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -10507,7 +10384,6 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -10552,7 +10428,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -10566,7 +10441,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -10725,7 +10599,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -10929,7 +10802,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -10939,7 +10811,6 @@ "version": "2.2.7", "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz", "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==", - "dev": true, "dependencies": { "bn.js": "^5.2.0" }, @@ -10998,7 +10869,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -11043,8 +10913,7 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sc-istanbul": { "version": "0.4.6", @@ -11198,14 +11067,12 @@ "node_modules/scrypt-js": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", - "dev": true + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" }, "node_modules/secp256k1": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", - "dev": true, "hasInstallScript": true, "dependencies": { "elliptic": "^6.5.4", @@ -11220,7 +11087,6 @@ "version": "7.6.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -11232,7 +11098,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, "dependencies": { "randombytes": "^2.1.0" } @@ -11272,20 +11137,17 @@ "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "node_modules/sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -11458,7 +11320,6 @@ "version": "0.8.26", "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.26.tgz", "integrity": "sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==", - "dev": true, "license": "MIT", "dependencies": { "command-exists": "^1.2.8", @@ -11480,7 +11341,6 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, "license": "MIT", "engines": { "node": ">= 12" @@ -11490,7 +11350,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver" @@ -11950,7 +11809,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -11960,7 +11818,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -11997,7 +11854,6 @@ "version": "0.1.10", "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", - "dev": true, "dependencies": { "type-fest": "^0.7.1" }, @@ -12009,7 +11865,6 @@ "version": "0.7.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", - "dev": true, "engines": { "node": ">=8" } @@ -12018,7 +11873,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -12027,7 +11881,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -12168,7 +12021,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -12214,7 +12066,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", "integrity": "sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==", - "dev": true, "dependencies": { "is-hex-prefixed": "1.0.0" }, @@ -12227,7 +12078,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -12239,7 +12089,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -12521,7 +12370,6 @@ "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, "license": "MIT", "dependencies": { "os-tmpdir": "~1.0.2" @@ -12534,7 +12382,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -12546,7 +12393,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, "engines": { "node": ">=0.6" } @@ -12665,7 +12511,7 @@ "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, + "devOptional": true, "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", @@ -12709,7 +12555,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, + "devOptional": true, "peer": true, "engines": { "node": ">=0.3.1" @@ -12730,26 +12576,22 @@ "node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/tsort": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", - "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==", - "dev": true + "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==" }, "node_modules/tweetnacl": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "dev": true + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" }, "node_modules/tweetnacl-util": { "version": "0.15.1", "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", - "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", - "dev": true + "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==" }, "node_modules/type-check": { "version": "0.4.0", @@ -12767,7 +12609,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, "peer": true, "engines": { "node": ">=4" @@ -12777,7 +12618,6 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, "engines": { "node": ">=10" }, @@ -13003,7 +12843,7 @@ "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "dev": true, + "devOptional": true, "peer": true, "bin": { "tsc": "bin/tsc", @@ -13056,7 +12896,6 @@ "version": "5.28.4", "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", - "dev": true, "dependencies": { "@fastify/busboy": "^2.0.0" }, @@ -13067,8 +12906,7 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/unfetch": { "version": "4.2.0", @@ -13101,7 +12939,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -13125,14 +12962,12 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, "bin": { "uuid": "dist/bin/uuid" } @@ -13141,7 +12976,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, + "devOptional": true, "peer": true }, "node_modules/web3-utils": { @@ -13302,7 +13137,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, "dependencies": { "string-width": "^4.0.0" }, @@ -13314,7 +13148,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -13323,7 +13156,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -13376,14 +13208,12 @@ "node_modules/workerpool": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==" }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -13474,7 +13304,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -13489,7 +13318,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -13500,14 +13328,12 @@ "node_modules/wrap-ansi/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -13516,7 +13342,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -13529,8 +13354,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { "version": "8.5.0", @@ -13558,7 +13382,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "engines": { "node": ">=10" } @@ -13597,7 +13420,6 @@ "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, "engines": { "node": ">=10" } @@ -13606,7 +13428,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -13653,7 +13474,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, + "devOptional": true, "peer": true, "engines": { "node": ">=6" diff --git a/package.json b/package.json index 0dd8cafd..3d0258aa 100644 --- a/package.json +++ b/package.json @@ -85,5 +85,8 @@ "*.js": [ "eslint" ] + }, + "dependencies": { + "hardhat-tracer": "^3.0.3" } } diff --git a/test/token/token-transfer.test.ts b/test/token/token-transfer.test.ts index dcaa013f..f63afeea 100644 --- a/test/token/token-transfer.test.ts +++ b/test/token/token-transfer.test.ts @@ -678,4 +678,122 @@ describe('Token - Transfers', () => { }); }); }); + + describe('.setAllowanceForAll()', () => { + it('should only allow the owner to set default allowances', async () => { + const { + suite: { token }, + accounts: { deployer, aliceWallet, bobWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await expect(token.connect(aliceWallet).setAllowanceForAll(true, [bobWallet.address])).to.be.revertedWith('Ownable: caller is not the owner'); + + await expect(token.connect(deployer).setAllowanceForAll(true, [bobWallet.address])) + .to.emit(token, 'DefaultAllowance') + .withArgs(bobWallet.address, true); + }); + + it('should revert if default allowance is already set for a target', async () => { + const { + suite: { token }, + accounts: { deployer, bobWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await token.connect(deployer).setAllowanceForAll(true, [bobWallet.address]); + + await expect(token.connect(deployer).setAllowanceForAll(true, [bobWallet.address])) + .to.be.revertedWithCustomError(token, 'DefaultAllowanceAlreadySet') + .withArgs(bobWallet.address); + }); + + it('should allow transfer without explicit allowance for addresses with default allowance', async () => { + const { + suite: { token }, + accounts: { deployer, aliceWallet, bobWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await expect(token.connect(aliceWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)).to.be.reverted; + + await token.connect(deployer).setAllowanceForAll(true, [bobWallet.address]); + + await expect(token.connect(bobWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)) + .to.emit(token, 'Transfer') + .withArgs(aliceWallet.address, bobWallet.address, 100); + }); + + it('should allow users to opt out of default allowance', async () => { + const { + suite: { token }, + accounts: { deployer, aliceWallet, bobWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await token.connect(deployer).setAllowanceForAll(true, [bobWallet.address]); + + await expect(token.connect(bobWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)) + .to.emit(token, 'Transfer') + .withArgs(aliceWallet.address, bobWallet.address, 100); + + await expect(token.connect(aliceWallet).disableDefaultAllowance()).to.emit(token, 'DefaultAllowanceDisabled').withArgs(aliceWallet.address); + + await expect(token.connect(bobWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)).to.be.reverted; + + await expect(token.connect(aliceWallet).enableDefaultAllowance()).to.emit(token, 'DefaultAllowanceEnabled').withArgs(aliceWallet.address); + + await expect(token.connect(bobWallet).transferFrom(aliceWallet.address, bobWallet.address, 100)) + .to.emit(token, 'Transfer') + .withArgs(aliceWallet.address, bobWallet.address, 100); + }); + + it('should revert if a user tries to disable an already disabled default allowance', async () => { + const { + suite: { token }, + accounts: { aliceWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await token.connect(aliceWallet).disableDefaultAllowance(); + + await expect(token.connect(aliceWallet).disableDefaultAllowance()) + .to.be.revertedWithCustomError(token, 'DefaultAllowanceAlreadyDisabled') + .withArgs(aliceWallet.address); + }); + + it('should revert if a user tries to enable an already enabled default allowance', async () => { + const { + suite: { token }, + accounts: { aliceWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await token.connect(aliceWallet).disableDefaultAllowance(); + await token.connect(aliceWallet).enableDefaultAllowance(); + + await expect(token.connect(aliceWallet).enableDefaultAllowance()) + .to.be.revertedWithCustomError(token, 'DefaultAllowanceAlreadyEnabled') + .withArgs(aliceWallet.address); + }); + + it('should return max uint256 as allowance for addresses with default allowance when user has not opted out', async () => { + const { + suite: { token }, + accounts: { deployer, aliceWallet, bobWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await token.connect(deployer).setAllowanceForAll(true, [bobWallet.address]); + + const allowance = await token.allowance(aliceWallet.address, bobWallet.address); + expect(allowance).to.equal(ethers.MaxUint256); + }); + + it('should return actual allowance when user has opted out of default allowance', async () => { + const { + suite: { token }, + accounts: { deployer, aliceWallet, bobWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await token.connect(deployer).setAllowanceForAll(true, [bobWallet.address]); + await token.connect(aliceWallet).disableDefaultAllowance(); + + const allowance = await token.allowance(aliceWallet.address, bobWallet.address); + expect(allowance).to.equal(0); + }); + }); }); From e2cb9c74c782a663dfc45bbe67d93a675d7db2f7 Mon Sep 17 00:00:00 2001 From: Joachim Date: Tue, 20 Aug 2024 00:36:21 +0800 Subject: [PATCH 31/55] TREX-161 : Add erc 165 (#219) - import ERC-165 - Implement ERC-165 on T-REX - Full Test coverage of ERC-165 - CHANGELOG --- .solcover.js | 1 + CHANGELOG.md | 18 +- contracts/DVA/DVATransferManager.sol | 14 +- .../compliance/modular/ModularCompliance.sol | 14 +- .../modular/modules/AbstractModule.sol | 12 +- .../modules/AbstractModuleUpgradeable.sol | 14 +- contracts/factory/TREXGateway.sol | 14 +- contracts/proxy/authority/IAFactory.sol | 11 +- .../authority/TREXImplementationAuthority.sol | 14 +- .../implementation/ClaimTopicsRegistry.sol | 14 +- .../implementation/IdentityRegistry.sol | 14 +- .../IdentityRegistryStorage.sol | 14 +- .../implementation/TrustedIssuersRegistry.sol | 14 +- contracts/roles/AgentRole.sol | 4 +- contracts/roles/IERC173.sol | 19 ++ contracts/token/Token.sol | 15 +- contracts/utils/InterfaceIdCalculator.sol | 188 ++++++++++++++++++ hardhat.config.ts | 4 +- package-lock.json | 81 ++++---- package.json | 2 +- .../trex-implementation-authority.test.ts | 99 +++++++++ test/compliance.test.ts | 43 ++++ .../module-conditional-transfer.test.ts | 43 ++++ test/compliances/module-country-allow.test.ts | 43 ++++ .../module-country-restrict.test.ts | 43 ++++ .../module-exchange-monthly-limits.test.ts | 35 ++++ test/compliances/module-max-balance.test.ts | 35 ++++ test/compliances/module-supply-limit.test.ts | 35 ++++ .../module-time-exchange-limits.test.ts | 35 ++++ .../module-time-transfer-limits.test.ts | 35 ++++ test/compliances/module-transfer-fees.test.ts | 35 ++++ .../module-transfer-restrict.test.ts | 35 ++++ test/dva.test.ts | 35 ++++ test/gateway.test.ts | 43 ++++ test/registries/claim-topics-registry.test.ts | 44 ++++ .../identity-registry-storage.test.ts | 43 ++++ test/registries/identity-registry.test.ts | 43 ++++ .../trusted-issuers-registry.test.ts | 43 ++++ test/token/token-information.test.ts | 54 +++++ 39 files changed, 1239 insertions(+), 63 deletions(-) create mode 100644 contracts/roles/IERC173.sol create mode 100644 contracts/utils/InterfaceIdCalculator.sol diff --git a/.solcover.js b/.solcover.js index 30b33cac..63069152 100644 --- a/.solcover.js +++ b/.solcover.js @@ -4,5 +4,6 @@ module.exports = { "_testContracts", "roles/permissioning/owner/", "roles/permissioning/agent/", + "utils", ], }; diff --git a/CHANGELOG.md b/CHANGELOG.md index 7502e735..0ac8aa59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,13 +12,29 @@ All notable changes to this project will be documented in this file. - Events: `DefaultAllowance`, `DefaultAllowanceDisabled`, `DefaultAllowanceEnabled`. - Enhanced the `allowance` function to return `type(uint256).max` for addresses with default allowance enabled, unless the user has opted out. +- **ERC-165 Interface Implementation**: + - Implemented ERC-165 support across all major contracts in the suite, allowing them to explicitly declare the interfaces they support. This enhancement improves interoperability and makes it easier for external contracts and tools to interact with T-REX contracts. + - ERC-165 support was added to the following contracts: + - `Token` + - `IdentityRegistry` + - `IdentityRegistryStorage` + - `TrustedIssuersRegistry` + - `ClaimTopicsRegistry` + - `TREXGateway` + - `DVATransferManager` + - `ModularCompliance` + - Compliance Modules (e.g., `CountryAllowModule`, `TransferRestrictModule`) + - `TREXImplementationAuthority` + - `IAFactory` + - Each contract now implements the `supportsInterface` function to identify the supported interfaces, ensuring compliance with ERC-165 standards. + ## [4.1.5] ### Update - DvA Transfer Manager contract proxified - The DvA manager contract freezes the tokens to be transferred instead of being a vault (so it must be a token agent) - Only the token owner (rather than agents) can call setApprovalCriteria, as it is part of the main token settings. -- + ## [4.1.4] ### Added diff --git a/contracts/DVA/DVATransferManager.sol b/contracts/DVA/DVATransferManager.sol index e547a092..b3381ed4 100644 --- a/contracts/DVA/DVATransferManager.sol +++ b/contracts/DVA/DVATransferManager.sol @@ -74,8 +74,10 @@ import "./IDVATransferManager.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import "../roles/IERC173.sol"; -contract DVATransferManager is IDVATransferManager, Initializable, OwnableUpgradeable, UUPSUpgradeable { +contract DVATransferManager is IDVATransferManager, Initializable, OwnableUpgradeable, UUPSUpgradeable, IERC165 { // Mapping for token approval criteria mapping(address => ApprovalCriteria) private _approvalCriteria; @@ -301,6 +303,16 @@ contract DVATransferManager is IDVATransferManager, Initializable, OwnableUpgrad return "DVATransferManager"; } + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { + return + interfaceId == type(IDVATransferManager).interfaceId || + interfaceId == type(IERC173).interfaceId || + interfaceId == type(IERC165).interfaceId; + } + /** * @dev See {IDVATransferManager-calculateTransferID} */ diff --git a/contracts/compliance/modular/ModularCompliance.sol b/contracts/compliance/modular/ModularCompliance.sol index cffc915a..f319a2ff 100644 --- a/contracts/compliance/modular/ModularCompliance.sol +++ b/contracts/compliance/modular/ModularCompliance.sol @@ -69,6 +69,8 @@ import "./MCStorage.sol"; import "./modules/IModule.sol"; import "../../errors/ComplianceErrors.sol"; import "../../errors/InvalidArgumentErrors.sol"; +import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import "../../roles/IERC173.sol"; /// errors @@ -89,7 +91,7 @@ error OnlyOwnerOrTokenCanCall(); error TokenNotBound(); -contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage { +contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage, IERC165 { /// modifiers @@ -272,6 +274,16 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage return true; } + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { + return + interfaceId == type(IModularCompliance).interfaceId || + interfaceId == type(IERC173).interfaceId || + interfaceId == type(IERC165).interfaceId; + } + /// @dev Extracts the Solidity ABI selector for the specified interaction. /// @param callData Interaction data. /// @return result The 4 byte function selector of the call encoded in diff --git a/contracts/compliance/modular/modules/AbstractModule.sol b/contracts/compliance/modular/modules/AbstractModule.sol index c7552e83..6b66f354 100644 --- a/contracts/compliance/modular/modules/AbstractModule.sol +++ b/contracts/compliance/modular/modules/AbstractModule.sol @@ -65,8 +65,9 @@ pragma solidity 0.8.26; import "./IModule.sol"; import "../../../errors/InvalidArgumentErrors.sol"; import "../../../errors/ComplianceErrors.sol"; +import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; -abstract contract AbstractModule is IModule { +abstract contract AbstractModule is IModule, IERC165 { /// compliance contract binding status mapping(address => bool) private _complianceBound; @@ -115,4 +116,13 @@ abstract contract AbstractModule is IModule { return _complianceBound[_compliance]; } + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { + return + interfaceId == type(IModule).interfaceId || + interfaceId == type(IERC165).interfaceId; + } + } diff --git a/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol index 31898009..4a421961 100644 --- a/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol +++ b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol @@ -68,9 +68,11 @@ import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "./IModule.sol"; import "../../../errors/InvalidArgumentErrors.sol"; import "../../../errors/ComplianceErrors.sol"; +import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import "../../../roles/IERC173.sol"; -abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUpgradeable, UUPSUpgradeable { +abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUpgradeable, UUPSUpgradeable, IERC165 { struct AbstractModuleStorage { /// compliance contract binding status mapping(address => bool) complianceBound; @@ -129,6 +131,16 @@ abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUp return s.complianceBound[_compliance]; } + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { + return + interfaceId == type(IModule).interfaceId || + interfaceId == type(IERC173).interfaceId || + interfaceId == type(IERC165).interfaceId; + } + // solhint-disable-next-line func-name-mixedcase function __AbstractModule_init() internal onlyInitializing { __Ownable_init(); diff --git a/contracts/factory/TREXGateway.sol b/contracts/factory/TREXGateway.sol index 6128cea6..58069a31 100644 --- a/contracts/factory/TREXGateway.sol +++ b/contracts/factory/TREXGateway.sol @@ -67,6 +67,8 @@ import "@openzeppelin/contracts/utils/Strings.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../errors/InvalidArgumentErrors.sol"; import "../errors/RoleErrors.sol"; +import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import "../roles/IERC173.sol"; /// Errors @@ -101,7 +103,7 @@ error DiscountOutOfRange(); error BatchMaxLengthExceeded(uint16 lengthLimit); -contract TREXGateway is ITREXGateway, AgentRole { +contract TREXGateway is ITREXGateway, AgentRole, IERC165 { /// address of the TREX Factory that is managed by the Gateway address private _factory; @@ -345,4 +347,14 @@ contract TREXGateway is ITREXGateway, AgentRole { function calculateFee(address deployer) public override view returns(uint256) { return _deploymentFee.fee - ((_feeDiscount[deployer] * _deploymentFee.fee) / 10000); } + + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { + return + interfaceId == type(ITREXGateway).interfaceId || + interfaceId == type(IERC173).interfaceId || + interfaceId == type(IERC165).interfaceId; + } } diff --git a/contracts/proxy/authority/IAFactory.sol b/contracts/proxy/authority/IAFactory.sol index f33a2466..5123506a 100644 --- a/contracts/proxy/authority/IAFactory.sol +++ b/contracts/proxy/authority/IAFactory.sol @@ -64,7 +64,7 @@ pragma solidity 0.8.26; import "./TREXImplementationAuthority.sol"; -contract IAFactory is IIAFactory { +contract IAFactory is IIAFactory, IERC165 { /// variables @@ -106,4 +106,13 @@ contract IAFactory is IIAFactory { function deployedByFactory(address _ia) external view override returns (bool) { return _deployedByFactory[_ia]; } + + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { + return + interfaceId == type(IIAFactory).interfaceId || + interfaceId == type(IERC165).interfaceId; + } } diff --git a/contracts/proxy/authority/TREXImplementationAuthority.sol b/contracts/proxy/authority/TREXImplementationAuthority.sol index c3df54cc..761affe3 100644 --- a/contracts/proxy/authority/TREXImplementationAuthority.sol +++ b/contracts/proxy/authority/TREXImplementationAuthority.sol @@ -70,6 +70,8 @@ import "../../factory/ITREXFactory.sol"; import "./IIAFactory.sol"; import "../../errors/CommonErrors.sol"; import "../../errors/InvalidArgumentErrors.sol"; +import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import "../../roles/IERC173.sol"; /// Errors @@ -101,7 +103,7 @@ error VersionAlreadyInUse(); error VersionOfNewIAMustBeTheSameAsCurrentIA(); -contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { +contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable, IERC165 { /// variables @@ -347,6 +349,16 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable { return ITREXFactory(_trexFactory).getImplementationAuthority(); } + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { + return + interfaceId == type(ITREXImplementationAuthority).interfaceId || + interfaceId == type(IERC173).interfaceId || + interfaceId == type(IERC165).interfaceId; + } + /** * @dev casting function Version => bytes to allow compare values easier */ diff --git a/contracts/registry/implementation/ClaimTopicsRegistry.sol b/contracts/registry/implementation/ClaimTopicsRegistry.sol index 2e92295d..638d5c4d 100644 --- a/contracts/registry/implementation/ClaimTopicsRegistry.sol +++ b/contracts/registry/implementation/ClaimTopicsRegistry.sol @@ -65,6 +65,8 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../storage/CTRStorage.sol"; import "../interface/IClaimTopicsRegistry.sol"; +import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import "../../roles/IERC173.sol"; /// Errors @@ -76,7 +78,7 @@ error MaxTopicsReached(uint256 _max); error ClaimTopicAlreadyExists(); -contract ClaimTopicsRegistry is IClaimTopicsRegistry, OwnableUpgradeable, CTRStorage { +contract ClaimTopicsRegistry is IClaimTopicsRegistry, OwnableUpgradeable, CTRStorage, IERC165 { function init() external initializer { __Ownable_init(); @@ -116,4 +118,14 @@ contract ClaimTopicsRegistry is IClaimTopicsRegistry, OwnableUpgradeable, CTRSto function getClaimTopics() external view override returns (uint256[] memory) { return _claimTopics; } + + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { + return + interfaceId == type(IClaimTopicsRegistry).interfaceId || + interfaceId == type(IERC173).interfaceId || + interfaceId == type(IERC165).interfaceId; + } } diff --git a/contracts/registry/implementation/IdentityRegistry.sol b/contracts/registry/implementation/IdentityRegistry.sol index 363e0825..97adbfa6 100644 --- a/contracts/registry/implementation/IdentityRegistry.sol +++ b/contracts/registry/implementation/IdentityRegistry.sol @@ -72,9 +72,11 @@ import "../../roles/AgentRoleUpgradeable.sol"; import "../interface/IIdentityRegistryStorage.sol"; import "../storage/IRStorage.sol"; import "../../errors/InvalidArgumentErrors.sol"; +import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import "../../roles/IERC173.sol"; -contract IdentityRegistry is IIdentityRegistry, AgentRoleUpgradeable, IRStorage { +contract IdentityRegistry is IIdentityRegistry, AgentRoleUpgradeable, IRStorage, IERC165 { /** * @dev the constructor initiates the Identity Registry smart contract @@ -279,4 +281,14 @@ contract IdentityRegistry is IIdentityRegistry, AgentRoleUpgradeable, IRStorage function identity(address _userAddress) public view override returns (IIdentity) { return _tokenIdentityStorage.storedIdentity(_userAddress); } + + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { + return + interfaceId == type(IIdentityRegistry).interfaceId || + interfaceId == type(IERC173).interfaceId || + interfaceId == type(IERC165).interfaceId; + } } diff --git a/contracts/registry/implementation/IdentityRegistryStorage.sol b/contracts/registry/implementation/IdentityRegistryStorage.sol index 3dffdb42..b2cb19ab 100644 --- a/contracts/registry/implementation/IdentityRegistryStorage.sol +++ b/contracts/registry/implementation/IdentityRegistryStorage.sol @@ -68,6 +68,8 @@ import "../../roles/AgentRoleUpgradeable.sol"; import "../interface/IIdentityRegistryStorage.sol"; import "../storage/IRSStorage.sol"; import "../../errors/InvalidArgumentErrors.sol"; +import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import "../../roles/IERC173.sol"; /// Errors @@ -85,7 +87,7 @@ error IdentityRegistryNotStored(); error MaxIRByIRSReached(uint256 _max); -contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeable, IRSStorage { +contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeable, IRSStorage, IERC165 { function init() external initializer { __Ownable_init(); @@ -193,4 +195,14 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab function storedInvestorCountry(address _userAddress) external view override returns (uint16) { return _identities[_userAddress].investorCountry; } + + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { + return + interfaceId == type(IIdentityRegistryStorage).interfaceId || + interfaceId == type(IERC173).interfaceId || + interfaceId == type(IERC165).interfaceId; + } } diff --git a/contracts/registry/implementation/TrustedIssuersRegistry.sol b/contracts/registry/implementation/TrustedIssuersRegistry.sol index bd2e0a93..559f0a54 100644 --- a/contracts/registry/implementation/TrustedIssuersRegistry.sol +++ b/contracts/registry/implementation/TrustedIssuersRegistry.sol @@ -68,6 +68,8 @@ import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../interface/ITrustedIssuersRegistry.sol"; import "../storage/TIRStorage.sol"; import "../../errors/InvalidArgumentErrors.sol"; +import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import "../../roles/IERC173.sol"; /// Errors @@ -95,7 +97,7 @@ error TrustedIssuerAlreadyExists(); error TrustedIssuerDoesNotExist(); -contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, TIRStorage { +contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, TIRStorage, IERC165 { /// Functions @@ -226,4 +228,14 @@ contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, } return false; } + + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { + return + interfaceId == type(ITrustedIssuersRegistry).interfaceId || + interfaceId == type(IERC173).interfaceId || + interfaceId == type(IERC165).interfaceId; + } } diff --git a/contracts/roles/AgentRole.sol b/contracts/roles/AgentRole.sol index 7d76355a..dbd8b80c 100644 --- a/contracts/roles/AgentRole.sol +++ b/contracts/roles/AgentRole.sol @@ -72,11 +72,11 @@ import "../errors/RoleErrors.sol"; /// Events -/// @dev This event is emmited when an agent is added. +/// @dev This event is emitted when an agent is added. /// @param _agent Address of agent contract event AgentAdded(address indexed _agent); -/// @dev This event is emmited when an agent is removed. +/// @dev This event is emitted when an agent is removed. /// @param _agent Address of agent contract event AgentRemoved(address indexed _agent); diff --git a/contracts/roles/IERC173.sol b/contracts/roles/IERC173.sol new file mode 100644 index 00000000..16c1b33e --- /dev/null +++ b/contracts/roles/IERC173.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +/// @title ERC-173 Contract Ownership Standard +/// Note: the ERC-165 identifier for this interface is 0x7f5828d0 +/* is ERC165 */ +interface IERC173 { + /// @dev This emits when ownership of a contract changes. + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + /// @notice Set the address of the new owner of the contract + /// @dev Set _newOwner to address(0) to renounce any ownership. + /// @param _newOwner The address of the new owner of the contract + function transferOwnership(address _newOwner) external; + + /// @notice Get the address of the owner + /// @return owner_ The address of the owner. + function owner() external view returns (address owner_); +} diff --git a/contracts/token/Token.sol b/contracts/token/Token.sol index aa4114b2..ea99ce57 100755 --- a/contracts/token/Token.sol +++ b/contracts/token/Token.sol @@ -67,8 +67,10 @@ import "./IToken.sol"; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; import "./TokenStorage.sol"; import "../roles/AgentRoleUpgradeable.sol"; +import "../roles/IERC173.sol"; import "../errors/InvalidArgumentErrors.sol"; import "../errors/CommonErrors.sol"; +import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /// errors @@ -117,7 +119,7 @@ error DefaultAllowanceAlreadyDisabled(address _user); error DefaultAllowanceAlreadySet(address _target); -contract Token is IToken, AgentRoleUpgradeable, TokenStorage { +contract Token is IToken, AgentRoleUpgradeable, TokenStorage, IERC165 { /// modifiers @@ -652,6 +654,17 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage { return _agentsRestrictions[agent]; } + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { + return + interfaceId == type(IERC20).interfaceId || // 0x36372b07 + interfaceId == type(IToken).interfaceId || // 0x4768ee17 + interfaceId == type(IERC173).interfaceId || // 0x7f5828d0 + interfaceId == type(IERC165).interfaceId; // 0x01ffc9a7 + } + /** * @dev See {ERC20-_transfer}. */ diff --git a/contracts/utils/InterfaceIdCalculator.sol b/contracts/utils/InterfaceIdCalculator.sol new file mode 100644 index 00000000..40be8b12 --- /dev/null +++ b/contracts/utils/InterfaceIdCalculator.sol @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: GPL-3.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// + +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2023, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +pragma solidity 0.8.26; + +import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "../roles/IERC173.sol"; +import "../token/IToken.sol"; +import "../proxy/authority/ITREXImplementationAuthority.sol"; +import "../proxy/authority/IIAFactory.sol"; +import "../factory/ITREXGateway.sol"; +import "../DVA/IDVATransferManager.sol"; +import "../compliance/modular/modules/IModule.sol"; + +contract InterfaceIdCalculator { + /** + * @dev Returns the interface ID for the IERC20 interface. + * IERC20 interface ID is 0x36372b07 + */ + function getIERC20InterfaceId() external pure returns (bytes4) { + return type(IERC20).interfaceId; + } + + /** + * @dev Returns the interface ID for the IToken interface. + * IToken interface ID is 0x4768ee17 + */ + function getITokenInterfaceId() external pure returns (bytes4) { + return type(IToken).interfaceId; + } + + /** + * @dev Returns the interface ID for the IERC173 interface. + * IERC173 interface ID is 0x7f5828d0 + */ + function getIERC173InterfaceId() external pure returns (bytes4) { + return type(IERC173).interfaceId; + } + + /** + * @dev Returns the interface ID for the IERC165 interface. + * IERC165 interface ID is 0x01ffc9a7 + */ + function getIERC165InterfaceId() external pure returns (bytes4) { + return type(IERC165).interfaceId; + } + + /** + * @dev Returns the interface ID for the IClaimTopicsRegistry interface. + * IClaimTopicsRegistry interface ID is 0x10928b13 + */ + function getIClaimTopicsRegistryInterfaceId() external pure returns (bytes4) { + return type(IClaimTopicsRegistry).interfaceId; + } + + /** + * @dev Returns the interface ID for the IIdentityRegistry interface. + * IIdentityRegistry interface ID is 0x8ff89f73 + */ + function getIIdentityRegistryInterfaceId() external pure returns (bytes4) { + return type(IIdentityRegistry).interfaceId; + } + + /** + * @dev Returns the interface ID for the IIdentityRegistryStorage interface. + * IIdentityRegistryStorage interface ID is 0x57defe0d + */ + function getIIdentityRegistryStorageInterfaceId() external pure returns (bytes4) { + return type(IIdentityRegistryStorage).interfaceId; + } + + /** + * @dev Returns the interface ID for the ITrustedIssuersRegistry interface. + * ITrustedIssuersRegistry interface ID is 0xb0f773b8 + */ + function getITrustedIssuersRegistryInterfaceId() external pure returns (bytes4) { + return type(ITrustedIssuersRegistry).interfaceId; + } + + /** + * @dev Returns the interface ID for the ITREXImplementationAuthority interface. + * ITREXImplementationAuthority interface ID is 0x62dd69be + */ + function getITREXImplementationAuthorityInterfaceId() external pure returns (bytes4) { + return type(ITREXImplementationAuthority).interfaceId; + } + + /** + * @dev Returns the interface ID for the IIAFactory interface. + * IIAFactory interface ID is 0x8c76edf0 + */ + function getIIAFactoryInterfaceId() external pure returns (bytes4) { + return type(IIAFactory).interfaceId; + } + + /** + * @dev Returns the interface ID for the ITREXGateway interface. + * ITREXGateway interface ID is 0x80e89461 + */ + function getITREXGatewayInterfaceId() external pure returns (bytes4) { + return type(ITREXGateway).interfaceId; + } + + /** + * @dev Returns the interface ID for the IDVATransferManager interface. + * IDVATransferManager interface ID is 0xb9eabd9b + */ + function getIDVATransferManagerInterfaceId() external pure returns (bytes4) { + return type(IDVATransferManager).interfaceId; + } + + /** + * @dev Returns the interface ID for the IModularCompliance interface. + * IModularCompliance interface ID is 0xef7cedae + */ + function getIModularComplianceInterfaceId() external pure returns (bytes4) { + return type(IModularCompliance).interfaceId; + } + + /** + * @dev Returns the interface ID for the IModule interface. + * IModule interface ID is 0xb795d01e + */ + function getIModuleInterfaceId() external pure returns (bytes4) { + return type(IModule).interfaceId; + } +} diff --git a/hardhat.config.ts b/hardhat.config.ts index 421a3c58..da2b5bf4 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -15,7 +15,7 @@ const config: HardhatUserConfig = { enabled: true, runs: 200, }, - viaIR: true + viaIR: true, }, }, gasReporter: { @@ -24,7 +24,7 @@ const config: HardhatUserConfig = { dodoc: { runOnCompile: false, debugMode: true, - outputDir: "./docgen", + outputDir: './docgen', freshOutput: true, }, }; diff --git a/package-lock.json b/package-lock.json index 246cfc8a..33d74852 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,7 +34,7 @@ "eth-gas-reporter": "^0.2.27", "fs-extra": "^11.2.0", "glob": "^10.4.1", - "hardhat": "^2.22.6", + "hardhat": "^2.22.8", "husky": "^9.0.11", "lint-staged": "^15.2.5", "prettier": "^3.2.5", @@ -1655,82 +1655,74 @@ } }, "node_modules/@nomicfoundation/edr": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.4.1.tgz", - "integrity": "sha512-NgrMo2rI9r28uidumvd+K2/AJLdxtXsUlJr3hj/pM6S1FCd/HiWaLeLa/cjCVPcE2u1rYAa3W6UFxLCB7S5Dhw==", - "license": "MIT", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.5.2.tgz", + "integrity": "sha512-hW/iLvUQZNTVjFyX/I40rtKvvDOqUEyIi96T28YaLfmPL+3LW2lxmYLUXEJ6MI14HzqxDqrLyhf6IbjAa2r3Dw==", "dependencies": { - "@nomicfoundation/edr-darwin-arm64": "0.4.1", - "@nomicfoundation/edr-darwin-x64": "0.4.1", - "@nomicfoundation/edr-linux-arm64-gnu": "0.4.1", - "@nomicfoundation/edr-linux-arm64-musl": "0.4.1", - "@nomicfoundation/edr-linux-x64-gnu": "0.4.1", - "@nomicfoundation/edr-linux-x64-musl": "0.4.1", - "@nomicfoundation/edr-win32-x64-msvc": "0.4.1" + "@nomicfoundation/edr-darwin-arm64": "0.5.2", + "@nomicfoundation/edr-darwin-x64": "0.5.2", + "@nomicfoundation/edr-linux-arm64-gnu": "0.5.2", + "@nomicfoundation/edr-linux-arm64-musl": "0.5.2", + "@nomicfoundation/edr-linux-x64-gnu": "0.5.2", + "@nomicfoundation/edr-linux-x64-musl": "0.5.2", + "@nomicfoundation/edr-win32-x64-msvc": "0.5.2" }, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-darwin-arm64": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.4.1.tgz", - "integrity": "sha512-XuiUUnWAVNw7JYv7nRqDWfpBm21HOxCRBQ8lQnRnmiets9Ss2X5Ul9mvBheIPh/D0wBzwJ8TRtsSrorpwE79cA==", - "license": "MIT", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.5.2.tgz", + "integrity": "sha512-Gm4wOPKhbDjGTIRyFA2QUAPfCXA1AHxYOKt3yLSGJkQkdy9a5WW+qtqKeEKHc/+4wpJSLtsGQfpzyIzggFfo/A==", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-darwin-x64": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.4.1.tgz", - "integrity": "sha512-N1MfJqEX5ixaXlyyrHnaYxzwIT27Nc/jUgLI7ts4/9kRvPTvyZRYmXS1ciKhmUFr/WvFckTCix2RJbZoGGtX7g==", - "license": "MIT", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.5.2.tgz", + "integrity": "sha512-ClyABq2dFCsrYEED3/UIO0c7p4H1/4vvlswFlqUyBpOkJccr75qIYvahOSJRM62WgUFRhbSS0OJXFRwc/PwmVg==", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.4.1.tgz", - "integrity": "sha512-bSPOfmcFjJwDgWOV5kgZHeqg2OWu1cINrHSGjig0aVHehjcoX4Sgayrj6fyAxcOV5NQKA6WcyTFll6NrCxzWRA==", - "license": "MIT", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.5.2.tgz", + "integrity": "sha512-HWMTVk1iOabfvU2RvrKLDgtFjJZTC42CpHiw2h6rfpsgRqMahvIlx2jdjWYzFNy1jZKPTN1AStQ/91MRrg5KnA==", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-arm64-musl": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.4.1.tgz", - "integrity": "sha512-F/+DgOdeBFQDrk+SX4aFffJFBgJfd75ZtE2mjcWNAh/qWiS7NfUxdQX/5OvNo/H6EY4a+3bZH6Bgzqg4mEWvMw==", - "license": "MIT", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.5.2.tgz", + "integrity": "sha512-CwsQ10xFx/QAD5y3/g5alm9+jFVuhc7uYMhrZAu9UVF+KtVjeCvafj0PaVsZ8qyijjqVuVsJ8hD1x5ob7SMcGg==", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-x64-gnu": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.4.1.tgz", - "integrity": "sha512-POHhTWczIXCPhzKtY0Vt/l+VCqqCx5gNR5ErwSrNnLz/arfQobZFAU+nc61BX3Jch82TW8b3AbfGI73Kh7gO0w==", - "license": "MIT", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.5.2.tgz", + "integrity": "sha512-CWVCEdhWJ3fmUpzWHCRnC0/VLBDbqtqTGTR6yyY1Ep3S3BOrHEAvt7h5gx85r2vLcztisu2vlDq51auie4IU1A==", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-x64-musl": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.4.1.tgz", - "integrity": "sha512-uu8oNp4Ozg3H1x1We0FF+rwXfFiAvsOm5GQ+OBx9YYOXnfDPWqguQfGIkhrti9GD0iYhfQ/WOG5wvp0IzzgGSg==", - "license": "MIT", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.5.2.tgz", + "integrity": "sha512-+aJDfwhkddy2pP5u1ISg3IZVAm0dO836tRlDTFWtvvSMQ5hRGqPcWwlsbobhDQsIxhPJyT7phL0orCg5W3WMeA==", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-win32-x64-msvc": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.4.1.tgz", - "integrity": "sha512-PaZHFw455z89ZiKYNTnKu+/TiVZVRI+mRJsbRTe2N0VlYfUBS1o2gdXBM12oP1t198HR7xQwEPPAslTFxGBqHA==", - "license": "MIT", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.5.2.tgz", + "integrity": "sha512-CcvvuA3sAv7liFNPsIR/68YlH6rrybKzYttLlMr80d4GKJjwJ5OKb3YgE6FdZZnOfP19HEHhsLcE0DPLtY3r0w==", "engines": { "node": ">= 18" } @@ -7317,14 +7309,13 @@ } }, "node_modules/hardhat": { - "version": "2.22.6", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.6.tgz", - "integrity": "sha512-abFEnd9QACwEtSvZZGSmzvw7N3zhQN1cDKz5SLHAupfG24qTHofCjqvD5kT5Wwsq5XOL0ON1Mq5rr4v0XX5ciw==", - "license": "MIT", + "version": "2.22.8", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.8.tgz", + "integrity": "sha512-hPh2feBGRswkXkoXUFW6NbxgiYtEzp/3uvVFjYROy6fA9LH8BobUyxStlyhSKj4+v1Y23ZoUBOVWL84IcLACrA==", "dependencies": { "@ethersproject/abi": "^5.1.2", "@metamask/eth-sig-util": "^4.0.0", - "@nomicfoundation/edr": "^0.4.1", + "@nomicfoundation/edr": "^0.5.2", "@nomicfoundation/ethereumjs-common": "4.0.4", "@nomicfoundation/ethereumjs-tx": "5.0.4", "@nomicfoundation/ethereumjs-util": "9.0.4", diff --git a/package.json b/package.json index 3d0258aa..1d1e6491 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "eth-gas-reporter": "^0.2.27", "fs-extra": "^11.2.0", "glob": "^10.4.1", - "hardhat": "^2.22.6", + "hardhat": "^2.22.8", "husky": "^9.0.11", "lint-staged": "^15.2.5", "prettier": "^3.2.5", diff --git a/test/authorities/trex-implementation-authority.test.ts b/test/authorities/trex-implementation-authority.test.ts index 64462cbf..689822dd 100644 --- a/test/authorities/trex-implementation-authority.test.ts +++ b/test/authorities/trex-implementation-authority.test.ts @@ -589,4 +589,103 @@ describe('TrexImplementationAuthority', () => { }); }); }); + describe('ERC165 tests', () => { + describe('TREXImplementationAuthority', () => { + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const { + authorities: { trexImplementationAuthority }, + } = await loadFixture(deployFullSuiteFixture); + + const unsupportedInterfaceId = '0x12345678'; + expect(await trexImplementationAuthority.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the ITREXImplementationAuthority interface ID', async () => { + const { + authorities: { trexImplementationAuthority }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iTREXImplementationAuthorityInterfaceId = await interfaceIdCalculator.getITREXImplementationAuthorityInterfaceId(); + expect(await trexImplementationAuthority.supportsInterface(iTREXImplementationAuthorityInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const { + authorities: { trexImplementationAuthority }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await trexImplementationAuthority.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const { + authorities: { trexImplementationAuthority }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await trexImplementationAuthority.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); + }); + describe('IAFactory', () => { + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const { + accounts: { deployer }, + authorities: { trexImplementationAuthority }, + factories: { identityFactory }, + } = await loadFixture(deployFullSuiteFixture); + const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.target, identityFactory.target], deployer); + await trexImplementationAuthority.setTREXFactory(trexFactory.target); + + const iaFactory = await ethers.deployContract('IAFactory', [trexFactory.target], deployer); + + const unsupportedInterfaceId = '0x12345678'; + expect(await iaFactory.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the IIAFactory interface ID', async () => { + const { + accounts: { deployer }, + authorities: { trexImplementationAuthority }, + factories: { identityFactory }, + } = await loadFixture(deployFullSuiteFixture); + const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.target, identityFactory.target], deployer); + await trexImplementationAuthority.setTREXFactory(trexFactory.target); + + const iaFactory = await ethers.deployContract('IAFactory', [trexFactory.target], deployer); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iIAFactoryInterfaceId = await interfaceIdCalculator.getIIAFactoryInterfaceId(); + expect(await iaFactory.supportsInterface(iIAFactoryInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const { + accounts: { deployer }, + authorities: { trexImplementationAuthority }, + factories: { identityFactory }, + } = await loadFixture(deployFullSuiteFixture); + const trexFactory = await ethers.deployContract('TREXFactory', [trexImplementationAuthority.target, identityFactory.target], deployer); + await trexImplementationAuthority.setTREXFactory(trexFactory.target); + + const iaFactory = await ethers.deployContract('IAFactory', [trexFactory.target], deployer); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await iaFactory.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); + }); + }); }); diff --git a/test/compliance.test.ts b/test/compliance.test.ts index 91b50259..9d7adf96 100644 --- a/test/compliance.test.ts +++ b/test/compliance.test.ts @@ -504,4 +504,47 @@ describe('ModularCompliance', () => { }); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const { + suite: { compliance }, + } = await loadFixture(deploySuiteWithModularCompliancesFixture); + + const unsupportedInterfaceId = '0x12345678'; + expect(await compliance.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the IModularCompliance interface ID', async () => { + const { + suite: { compliance }, + } = await loadFixture(deploySuiteWithModularCompliancesFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iModularComplianceInterfaceId = await interfaceIdCalculator.getIModularComplianceInterfaceId(); + expect(await compliance.supportsInterface(iModularComplianceInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const { + suite: { compliance }, + } = await loadFixture(deploySuiteWithModularCompliancesFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await compliance.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const { + suite: { compliance }, + } = await loadFixture(deploySuiteWithModularCompliancesFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await compliance.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); diff --git a/test/compliances/module-conditional-transfer.test.ts b/test/compliances/module-conditional-transfer.test.ts index 3e7634eb..7e93192e 100644 --- a/test/compliances/module-conditional-transfer.test.ts +++ b/test/compliances/module-conditional-transfer.test.ts @@ -469,4 +469,47 @@ describe('ConditionalTransferModule', () => { }); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const { + suite: { conditionalTransferModule }, + } = await loadFixture(deployComplianceWithConditionalTransferModule); + + const unsupportedInterfaceId = '0x12345678'; + expect(await conditionalTransferModule.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the IModule interface ID', async () => { + const { + suite: { conditionalTransferModule }, + } = await loadFixture(deployComplianceWithConditionalTransferModule); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iModuleInterfaceId = await interfaceIdCalculator.getIModuleInterfaceId(); + expect(await conditionalTransferModule.supportsInterface(iModuleInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const { + suite: { conditionalTransferModule }, + } = await loadFixture(deployComplianceWithConditionalTransferModule); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await conditionalTransferModule.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const { + suite: { conditionalTransferModule }, + } = await loadFixture(deployComplianceWithConditionalTransferModule); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await conditionalTransferModule.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); diff --git a/test/compliances/module-country-allow.test.ts b/test/compliances/module-country-allow.test.ts index 920a2f5b..6bedded4 100644 --- a/test/compliances/module-country-allow.test.ts +++ b/test/compliances/module-country-allow.test.ts @@ -480,4 +480,47 @@ describe('CountryAllowModule', () => { }); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const { + suite: { countryAllowModule }, + } = await loadFixture(deployComplianceWithCountryAllowModule); + + const unsupportedInterfaceId = '0x12345678'; + expect(await countryAllowModule.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the IModule interface ID', async () => { + const { + suite: { countryAllowModule }, + } = await loadFixture(deployComplianceWithCountryAllowModule); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iModuleInterfaceId = await interfaceIdCalculator.getIModuleInterfaceId(); + expect(await countryAllowModule.supportsInterface(iModuleInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const { + suite: { countryAllowModule }, + } = await loadFixture(deployComplianceWithCountryAllowModule); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await countryAllowModule.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const { + suite: { countryAllowModule }, + } = await loadFixture(deployComplianceWithCountryAllowModule); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await countryAllowModule.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); diff --git a/test/compliances/module-country-restrict.test.ts b/test/compliances/module-country-restrict.test.ts index 655de3d2..a5665d6e 100644 --- a/test/compliances/module-country-restrict.test.ts +++ b/test/compliances/module-country-restrict.test.ts @@ -632,4 +632,47 @@ describe('CountryRestrictModule', () => { }); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const { + suite: { countryRestrictModule }, + } = await loadFixture(deployComplianceWithCountryRestrictModule); + + const unsupportedInterfaceId = '0x12345678'; + expect(await countryRestrictModule.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the IModule interface ID', async () => { + const { + suite: { countryRestrictModule }, + } = await loadFixture(deployComplianceWithCountryRestrictModule); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iModuleInterfaceId = await interfaceIdCalculator.getIModuleInterfaceId(); + expect(await countryRestrictModule.supportsInterface(iModuleInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const { + suite: { countryRestrictModule }, + } = await loadFixture(deployComplianceWithCountryRestrictModule); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await countryRestrictModule.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const { + suite: { countryRestrictModule }, + } = await loadFixture(deployComplianceWithCountryRestrictModule); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await countryRestrictModule.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); diff --git a/test/compliances/module-exchange-monthly-limits.test.ts b/test/compliances/module-exchange-monthly-limits.test.ts index af8500b0..aa45a942 100644 --- a/test/compliances/module-exchange-monthly-limits.test.ts +++ b/test/compliances/module-exchange-monthly-limits.test.ts @@ -711,4 +711,39 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { }); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const context = await loadFixture(deployExchangeMonthlyLimitsFixture); + + const unsupportedInterfaceId = '0x12345678'; + expect(await context.contracts.complianceModule.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the IModule interface ID', async () => { + const context = await loadFixture(deployExchangeMonthlyLimitsFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iModuleInterfaceId = await interfaceIdCalculator.getIModuleInterfaceId(); + expect(await context.contracts.complianceModule.supportsInterface(iModuleInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const context = await loadFixture(deployExchangeMonthlyLimitsFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await context.contracts.complianceModule.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const context = await loadFixture(deployExchangeMonthlyLimitsFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await context.contracts.complianceModule.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); diff --git a/test/compliances/module-max-balance.test.ts b/test/compliances/module-max-balance.test.ts index 52bc1969..eb8bb1ed 100644 --- a/test/compliances/module-max-balance.test.ts +++ b/test/compliances/module-max-balance.test.ts @@ -575,4 +575,39 @@ describe('Compliance Module: MaxBalance', () => { }); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const context = await loadFixture(deployMaxBalanceFullSuite); + + const unsupportedInterfaceId = '0x12345678'; + expect(await context.suite.complianceModule.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the IModule interface ID', async () => { + const context = await loadFixture(deployMaxBalanceFullSuite); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iModuleInterfaceId = await interfaceIdCalculator.getIModuleInterfaceId(); + expect(await context.suite.complianceModule.supportsInterface(iModuleInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const context = await loadFixture(deployMaxBalanceFullSuite); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await context.suite.complianceModule.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const context = await loadFixture(deployMaxBalanceFullSuite); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await context.suite.complianceModule.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); diff --git a/test/compliances/module-supply-limit.test.ts b/test/compliances/module-supply-limit.test.ts index b514f09c..da88229f 100644 --- a/test/compliances/module-supply-limit.test.ts +++ b/test/compliances/module-supply-limit.test.ts @@ -301,4 +301,39 @@ describe('Compliance Module: SupplyLimit', () => { }); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const context = await loadFixture(deploySupplyLimitFixture); + + const unsupportedInterfaceId = '0x12345678'; + expect(await context.suite.complianceModule.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the IModule interface ID', async () => { + const context = await loadFixture(deploySupplyLimitFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iModuleInterfaceId = await interfaceIdCalculator.getIModuleInterfaceId(); + expect(await context.suite.complianceModule.supportsInterface(iModuleInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const context = await loadFixture(deploySupplyLimitFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await context.suite.complianceModule.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const context = await loadFixture(deploySupplyLimitFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await context.suite.complianceModule.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); diff --git a/test/compliances/module-time-exchange-limits.test.ts b/test/compliances/module-time-exchange-limits.test.ts index 6a7a43f8..ee27e1a6 100644 --- a/test/compliances/module-time-exchange-limits.test.ts +++ b/test/compliances/module-time-exchange-limits.test.ts @@ -853,4 +853,39 @@ describe('Compliance Module: TimeExchangeLimits', () => { }); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const context = await loadFixture(deployTimeExchangeLimitsFixture); + + const unsupportedInterfaceId = '0x12345678'; + expect(await context.contracts.complianceModule.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the IModule interface ID', async () => { + const context = await loadFixture(deployTimeExchangeLimitsFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iModuleInterfaceId = await interfaceIdCalculator.getIModuleInterfaceId(); + expect(await context.contracts.complianceModule.supportsInterface(iModuleInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const context = await loadFixture(deployTimeExchangeLimitsFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await context.contracts.complianceModule.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const context = await loadFixture(deployTimeExchangeLimitsFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await context.contracts.complianceModule.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); diff --git a/test/compliances/module-time-transfer-limits.test.ts b/test/compliances/module-time-transfer-limits.test.ts index 52c08cca..f627d5e7 100644 --- a/test/compliances/module-time-transfer-limits.test.ts +++ b/test/compliances/module-time-transfer-limits.test.ts @@ -630,4 +630,39 @@ describe('Compliance Module: TimeTransferLimits', () => { }); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const context = await loadFixture(deployTimeTransferLimitsFixture); + + const unsupportedInterfaceId = '0x12345678'; + expect(await context.contracts.complianceModule.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the IModule interface ID', async () => { + const context = await loadFixture(deployTimeTransferLimitsFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iModuleInterfaceId = await interfaceIdCalculator.getIModuleInterfaceId(); + expect(await context.contracts.complianceModule.supportsInterface(iModuleInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const context = await loadFixture(deployTimeTransferLimitsFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await context.contracts.complianceModule.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const context = await loadFixture(deployTimeTransferLimitsFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await context.contracts.complianceModule.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); diff --git a/test/compliances/module-transfer-fees.test.ts b/test/compliances/module-transfer-fees.test.ts index 28a7fed3..d15087cd 100644 --- a/test/compliances/module-transfer-fees.test.ts +++ b/test/compliances/module-transfer-fees.test.ts @@ -457,4 +457,39 @@ describe('Compliance Module: TransferFees', () => { expect(await context.suite.complianceModule.name()).to.be.equal('TransferFeesModule'); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const context = await loadFixture(deployTransferFeesFullSuite); + + const unsupportedInterfaceId = '0x12345678'; + expect(await context.suite.complianceModule.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the IModule interface ID', async () => { + const context = await loadFixture(deployTransferFeesFullSuite); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iModuleInterfaceId = await interfaceIdCalculator.getIModuleInterfaceId(); + expect(await context.suite.complianceModule.supportsInterface(iModuleInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const context = await loadFixture(deployTransferFeesFullSuite); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await context.suite.complianceModule.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const context = await loadFixture(deployTransferFeesFullSuite); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await context.suite.complianceModule.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); diff --git a/test/compliances/module-transfer-restrict.test.ts b/test/compliances/module-transfer-restrict.test.ts index c46ae48d..4a36e1b5 100644 --- a/test/compliances/module-transfer-restrict.test.ts +++ b/test/compliances/module-transfer-restrict.test.ts @@ -430,4 +430,39 @@ describe('Compliance Module: TransferRestrict', () => { }); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const context = await loadFixture(deployTransferRestrictFullSuite); + + const unsupportedInterfaceId = '0x12345678'; + expect(await context.suite.complianceModule.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the IModule interface ID', async () => { + const context = await loadFixture(deployTransferRestrictFullSuite); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iModuleInterfaceId = await interfaceIdCalculator.getIModuleInterfaceId(); + expect(await context.suite.complianceModule.supportsInterface(iModuleInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const context = await loadFixture(deployTransferRestrictFullSuite); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await context.suite.complianceModule.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const context = await loadFixture(deployTransferRestrictFullSuite); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await context.suite.complianceModule.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); diff --git a/test/dva.test.ts b/test/dva.test.ts index 5d1d8e4b..3d33421e 100644 --- a/test/dva.test.ts +++ b/test/dva.test.ts @@ -1118,4 +1118,39 @@ describe('DVATransferManager', () => { expect(await context.suite.transferManager.name()).to.be.equal('DVATransferManager'); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); + + const unsupportedInterfaceId = '0x12345678'; + expect(await context.suite.transferManager.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the IDVATransferManager interface ID', async () => { + const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iDVATransferManagerInterfaceId = await interfaceIdCalculator.getIDVATransferManagerInterfaceId(); + expect(await context.suite.transferManager.supportsInterface(iDVATransferManagerInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await context.suite.transferManager.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const context = await loadFixture(deployFullSuiteWithVerifiedTransferManager); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await context.suite.transferManager.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); diff --git a/test/gateway.test.ts b/test/gateway.test.ts index b2d27553..1e95ee57 100644 --- a/test/gateway.test.ts +++ b/test/gateway.test.ts @@ -1361,4 +1361,47 @@ describe('TREXGateway', () => { }); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const context = await loadFixture(deployFullSuiteFixture); + + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + + const unsupportedInterfaceId = '0x12345678'; + expect(await gateway.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the ITREXGateway interface ID', async () => { + const context = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + + const iTREXGatewayInterfaceId = await interfaceIdCalculator.getITREXGatewayInterfaceId(); + expect(await gateway.supportsInterface(iTREXGatewayInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const context = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await gateway.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const context = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const gateway = await ethers.deployContract('TREXGateway', [context.factories.trexFactory.target, false], context.accounts.deployer); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await gateway.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); diff --git a/test/registries/claim-topics-registry.test.ts b/test/registries/claim-topics-registry.test.ts index 7dc305c0..6b18d539 100644 --- a/test/registries/claim-topics-registry.test.ts +++ b/test/registries/claim-topics-registry.test.ts @@ -1,5 +1,6 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { expect } from 'chai'; +import { ethers } from 'hardhat'; import { deployFullSuiteFixture } from '../fixtures/deploy-full-suite.fixture'; describe('ClaimTopicsRegistry', () => { @@ -90,4 +91,47 @@ describe('ClaimTopicsRegistry', () => { }); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const { + suite: { claimTopicsRegistry }, + } = await loadFixture(deployFullSuiteFixture); + + const unsupportedInterfaceId = '0x12345678'; + expect(await claimTopicsRegistry.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the IClaimTopicsRegistry interface ID', async () => { + const { + suite: { claimTopicsRegistry }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iClaimTopicsRegistryInterfaceId = await interfaceIdCalculator.getIClaimTopicsRegistryInterfaceId(); + expect(await claimTopicsRegistry.supportsInterface(iClaimTopicsRegistryInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const { + suite: { claimTopicsRegistry }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await claimTopicsRegistry.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const { + suite: { claimTopicsRegistry }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await claimTopicsRegistry.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); diff --git a/test/registries/identity-registry-storage.test.ts b/test/registries/identity-registry-storage.test.ts index 178a1bf9..cf85851b 100644 --- a/test/registries/identity-registry-storage.test.ts +++ b/test/registries/identity-registry-storage.test.ts @@ -360,4 +360,47 @@ describe('IdentityRegistryStorage', () => { }); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const { + suite: { identityRegistryStorage }, + } = await loadFixture(deployFullSuiteFixture); + + const unsupportedInterfaceId = '0x12345678'; + expect(await identityRegistryStorage.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the IIdentityRegistryStorage interface ID', async () => { + const { + suite: { identityRegistryStorage }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iIdentityRegistryStorageInterfaceId = await interfaceIdCalculator.getIIdentityRegistryStorageInterfaceId(); + expect(await identityRegistryStorage.supportsInterface(iIdentityRegistryStorageInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const { + suite: { identityRegistryStorage }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await identityRegistryStorage.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const { + suite: { identityRegistryStorage }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await identityRegistryStorage.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); diff --git a/test/registries/identity-registry.test.ts b/test/registries/identity-registry.test.ts index addc90d5..3256b5d6 100644 --- a/test/registries/identity-registry.test.ts +++ b/test/registries/identity-registry.test.ts @@ -280,4 +280,47 @@ describe('IdentityRegistry', () => { }); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const { + suite: { identityRegistry }, + } = await loadFixture(deployFullSuiteFixture); + + const unsupportedInterfaceId = '0x12345678'; + expect(await identityRegistry.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the IIdentityRegistry interface ID', async () => { + const { + suite: { identityRegistry }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iIdentityRegistryInterfaceId = await interfaceIdCalculator.getIIdentityRegistryInterfaceId(); + expect(await identityRegistry.supportsInterface(iIdentityRegistryInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const { + suite: { identityRegistry }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await identityRegistry.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const { + suite: { identityRegistry }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await identityRegistry.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); diff --git a/test/registries/trusted-issuers-registry.test.ts b/test/registries/trusted-issuers-registry.test.ts index bf880fd6..c3ee8bdc 100644 --- a/test/registries/trusted-issuers-registry.test.ts +++ b/test/registries/trusted-issuers-registry.test.ts @@ -280,4 +280,47 @@ describe('TrustedIssuersRegistry', () => { }); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const { + suite: { trustedIssuersRegistry }, + } = await loadFixture(deployFullSuiteFixture); + + const unsupportedInterfaceId = '0x12345678'; + expect(await trustedIssuersRegistry.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the ITrustedIssuersRegistry interface ID', async () => { + const { + suite: { trustedIssuersRegistry }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iTrustedIssuersRegistryInterfaceId = await interfaceIdCalculator.getITrustedIssuersRegistryInterfaceId(); + expect(await trustedIssuersRegistry.supportsInterface(iTrustedIssuersRegistryInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const { + suite: { trustedIssuersRegistry }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await trustedIssuersRegistry.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const { + suite: { trustedIssuersRegistry }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await trustedIssuersRegistry.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); diff --git a/test/token/token-information.test.ts b/test/token/token-information.test.ts index 2d45d2af..0668b018 100644 --- a/test/token/token-information.test.ts +++ b/test/token/token-information.test.ts @@ -334,4 +334,58 @@ describe('Token - Information', () => { }); }); }); + describe('.supportsInterface()', () => { + it('should return false for unsupported interfaces', async () => { + const { + suite: { token }, + } = await loadFixture(deployFullSuiteFixture); + + const unsupportedInterfaceId = '0x12345678'; + expect(await token.supportsInterface(unsupportedInterfaceId)).to.equal(false); + }); + + it('should correctly identify the IERC20 interface ID', async () => { + const { + suite: { token }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc20InterfaceId = await interfaceIdCalculator.getIERC20InterfaceId(); + expect(await token.supportsInterface(ierc20InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IToken interface ID', async () => { + const { + suite: { token }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iTokenInterfaceId = await interfaceIdCalculator.getITokenInterfaceId(); + expect(await token.supportsInterface(iTokenInterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC173 interface ID', async () => { + const { + suite: { token }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc173InterfaceId = await interfaceIdCalculator.getIERC173InterfaceId(); + expect(await token.supportsInterface(ierc173InterfaceId)).to.equal(true); + }); + + it('should correctly identify the IERC165 interface ID', async () => { + const { + suite: { token }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); + expect(await token.supportsInterface(ierc165InterfaceId)).to.equal(true); + }); + }); }); From 0e4c3dd472bccb0ba5dc9a672eac8f931ea1a16a Mon Sep 17 00:00:00 2001 From: Joachim Date: Tue, 20 Aug 2024 16:29:58 +0800 Subject: [PATCH 32/55] TREX-121 : recovery function update (#220) - recovery function re-implementation - tests - Natspec update - Changelog update --- CHANGELOG.md | 11 +++ contracts/token/IToken.sol | 53 ++++++++++--- contracts/token/Token.sol | 41 ++++++---- test/token/token-recovery.test.ts | 126 +++++++++++++++++++++++++----- 4 files changed, 184 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ac8aa59..5bad06f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,17 @@ All notable changes to this project will be documented in this file. - `IAFactory` - Each contract now implements the `supportsInterface` function to identify the supported interfaces, ensuring compliance with ERC-165 standards. +### Updated + +- **Token Recovery Function**: + - The `recoveryAddress` function was significantly improved to handle more complex scenarios and prevent potential bugs: + - Removed the requirement for the `newWallet` to be a key on the `onchainID`, simplifying the process and reducing potential errors. + - Enhanced compatibility with shared identity registry storage, ensuring the function works correctly even when multiple tokens share the same identity registry storage. + - Added logic to handle recovery to an existing wallet that is already linked to the investor's identity, addressing scenarios where the `newWallet` is an existing wallet. + - The function now accurately updates the identity registry, preventing errors related to attempting to add or remove identities that are already present or absent. + - Improved overall logic to ensure smooth and error-free recovery operations, with events (`RecoverySuccess`, `TokensFrozen`, `TokensUnfrozen`, etc.) emitted to provide detailed feedback. + + ## [4.1.5] ### Update diff --git a/contracts/token/IToken.sol b/contracts/token/IToken.sol index 9709da05..fe34e2d0 100644 --- a/contracts/token/IToken.sol +++ b/contracts/token/IToken.sol @@ -319,18 +319,47 @@ interface IToken is IERC20 { function burn(address _userAddress, uint256 _amount) external; /** - * @dev Initiates a recovery process to force transfer tokens from a lost wallet to a new wallet for an investor. - * @param _lostWallet The wallet that the investor lost. - * @param _newWallet The newly provided wallet to which tokens must be transferred. - * @param _investorOnchainID The onchainID of the investor requesting recovery. - * This function can only be called by a wallet designated as an agent of the token, - * provided the agent is not restricted from initiating recovery processes. - * Emits a `TokensUnfrozen` event if there are frozen tokens on the lost wallet and the recovery process is successful. - * Also emits a `Transfer` event and a `RecoverySuccess` event upon successful recovery. - * Emits a `RecoveryFails` event if the recovery process fails. - * To execute this function, the calling agent must not be restricted from initiating recovery processes. - * If the agent is restricted from this capability, the function call will fail. - */ + * @dev Initiates a recovery process to transfer tokens and associated states + * from a lost wallet to a new wallet for an investor. + * + * This function allows an authorized agent to recover tokens from a lost wallet, + * transferring them to a new wallet while preserving the investor's + * identity and status within the token ecosystem. The function ensures that all relevant data, + * including frozen tokens and address freezing status, is accurately transferred to the new wallet. + * + * @param _lostWallet The wallet that the investor lost, containing the tokens to be recovered. + * @param _newWallet The newly provided wallet to which tokens and associated statuses must be transferred. + * @param _investorOnchainID The ONCHAINID of the investor whose tokens are being recovered. + * + * Requirements: + * - The caller must be an agent authorized to perform recovery operations, with no restrictions on this capability. + * - The `_lostWallet` must have a non-zero token balance; otherwise, the recovery is unnecessary and will revert. + * - Either the `_lostWallet` or the `_newWallet` must be present in the identity registry; + * if neither is present, the function will revert. + * + * Operations: + * - Transfers the entire token balance from `_lostWallet` to `_newWallet`. + * - Transfers any frozen tokens from `_lostWallet` to `_newWallet`, updating the frozen token count accordingly. + * - Transfers the address freeze status from `_lostWallet` to `_newWallet`, + * ensuring the new wallet retains any restrictions if applicable. + * - Updates the identity registry: + * - If `_lostWallet` is listed in the identity registry, it will be removed, + * and `_newWallet` will be registered unless already present. + * + * Emits the following events: + * - `TokensUnfrozen` if there are frozen tokens on `_lostWallet` that are transferred. + * - `TokensFrozen` if frozen tokens are added to `_newWallet`. + * - `AddressFrozen` if the freeze status of either wallet changes. + * - `Transfer` to reflect the movement of tokens from `_lostWallet` to `_newWallet`. + * - `RecoverySuccess` upon successful completion of the recovery process. + * + * Reverts if: + * - The agent calling the function does not have the necessary permissions to perform recovery (`AgentNotAuthorized`). + * - The `_lostWallet` has no tokens to recover (`NoTokenToRecover`). + * - Neither `_lostWallet` nor `_newWallet` is present in the identity registry (`RecoveryNotPossible`). + * + * @return A boolean value indicating whether the recovery process was successful. + */ function recoveryAddress( address _lostWallet, address _newWallet, diff --git a/contracts/token/Token.sol b/contracts/token/Token.sol index ea99ce57..c2742ba9 100755 --- a/contracts/token/Token.sol +++ b/contracts/token/Token.sol @@ -377,25 +377,36 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage, IERC165 { ) external override onlyAgent returns (bool) { require(!getAgentRestrictions(msg.sender).disableRecovery, AgentNotAuthorized(msg.sender, "recovery disabled")); require(balanceOf(_lostWallet) != 0, NoTokenToRecover()); - IIdentity _onchainID = IIdentity(_investorOnchainID); - bytes32 _key = keccak256(abi.encode(_newWallet)); - if (_onchainID.keyHasPurpose(_key, 1)) { - uint256 investorTokens = balanceOf(_lostWallet); - uint256 frozenTokens = _frozenTokens[_lostWallet]; - _tokenIdentityRegistry.registerIdentity(_newWallet, _onchainID, _tokenIdentityRegistry.investorCountry - (_lostWallet)); - forcedTransfer(_lostWallet, _newWallet, investorTokens); - if (frozenTokens > 0) { - freezePartialTokens(_newWallet, frozenTokens); + require(_tokenIdentityRegistry.contains(_lostWallet) || + _tokenIdentityRegistry.contains(_newWallet), RecoveryNotPossible()); + uint256 investorTokens = balanceOf(_lostWallet); + uint256 frozenTokens = _frozenTokens[_lostWallet]; + bool addressFreeze = _frozen[_lostWallet]; + _transfer(_lostWallet, _newWallet, investorTokens); + if(frozenTokens > 0) { + _frozenTokens[_lostWallet] = 0; + emit TokensUnfrozen(_lostWallet, frozenTokens); + _frozenTokens[_newWallet] += frozenTokens; + emit TokensFrozen(_newWallet, frozenTokens); + } + if(addressFreeze) { + _frozen[_lostWallet] = false; + emit AddressFrozen(_lostWallet, false, address(this)); + if(!_frozen[_newWallet]){ + _frozen[_newWallet] = true; + emit AddressFrozen(_newWallet, true, address(this)); } - if (_frozen[_lostWallet] == true) { - setAddressFrozen(_newWallet, true); + } + if(_tokenIdentityRegistry.contains(_lostWallet)) { + if(!_tokenIdentityRegistry.contains(_newWallet)) { + _tokenIdentityRegistry.registerIdentity( + _newWallet, IIdentity(_investorOnchainID), + _tokenIdentityRegistry.investorCountry(_lostWallet)); } _tokenIdentityRegistry.deleteIdentity(_lostWallet); - emit RecoverySuccess(_lostWallet, _newWallet, _investorOnchainID); - return true; } - revert RecoveryNotPossible(); + emit RecoverySuccess(_lostWallet, _newWallet, _investorOnchainID); + return true; } /// @dev See {IToken-setAllowanceForAll}. diff --git a/test/token/token-recovery.test.ts b/test/token/token-recovery.test.ts index bafa30ea..dc82b7eb 100644 --- a/test/token/token-recovery.test.ts +++ b/test/token/token-recovery.test.ts @@ -67,60 +67,146 @@ describe('Token - Recovery', () => { ).to.be.revertedWithCustomError(token, 'NoTokenToRecover'); }); }); + describe('when wallet has frozen token', () => { + it('should recover and freeze tokens on the new wallet', async () => { + const { + suite: { token }, + accounts: { tokenAgent, bobWallet, anotherWallet }, + identities: { bobIdentity }, + } = await loadFixture(deployFullSuiteFixture); + + await bobIdentity + .connect(bobWallet) + .addKey(ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address'], [anotherWallet.address])), 1, 1); + + await token.connect(tokenAgent).freezePartialTokens(bobWallet.address, 50); - describe('when new wallet is not authorized on the identity', () => { + const tx = await token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target); + await expect(token.getFrozenTokens(anotherWallet.address)).to.be.eventually.eq(50); + await expect(tx).to.emit(token, 'RecoverySuccess').withArgs(bobWallet.address, anotherWallet.address, bobIdentity.target); + await expect(tx).to.emit(token, 'TokensFrozen').withArgs(anotherWallet.address, 50); + }); + }); + describe('when identity registry does not contain the lost or new wallet', () => { it('should revert', async () => { const { - suite: { token }, + suite: { token, identityRegistry }, accounts: { tokenAgent, bobWallet, anotherWallet }, identities: { bobIdentity }, } = await loadFixture(deployFullSuiteFixture); + await identityRegistry.connect(tokenAgent).deleteIdentity(bobWallet.address); + await expect( token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target), ).to.be.revertedWithCustomError(token, 'RecoveryNotPossible'); }); }); - describe('when wallet is frozen', () => { - it('should recover and freeze the new wallet', async () => { + describe('when recovery is successful with identity transfer', () => { + it('should update the identity registry correctly', async () => { const { - suite: { token }, + suite: { token, identityRegistry }, accounts: { tokenAgent, bobWallet, anotherWallet }, identities: { bobIdentity }, } = await loadFixture(deployFullSuiteFixture); - await bobIdentity - .connect(bobWallet) - .addKey(ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address'], [anotherWallet.address])), 1, 1); + const tx = await token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target); - await token.connect(tokenAgent).setAddressFrozen(bobWallet.address, true); + await expect(identityRegistry.contains(bobWallet.address)).to.eventually.be.false; + await expect(identityRegistry.contains(anotherWallet.address)).to.eventually.be.true; + await expect(tx).to.emit(token, 'RecoverySuccess').withArgs(bobWallet.address, anotherWallet.address, bobIdentity.target); + }); + }); + + describe('when the new wallet is already in the identity registry', () => { + it('should only remove the lost wallet from the registry', async () => { + const { + suite: { token, identityRegistry }, + accounts: { tokenAgent, bobWallet, anotherWallet }, + identities: { bobIdentity }, + } = await loadFixture(deployFullSuiteFixture); + + await identityRegistry.connect(tokenAgent).registerIdentity(anotherWallet.address, bobIdentity.target, 1); const tx = await token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target); - await expect(token.isFrozen(anotherWallet.address)).to.be.eventually.true; + + await expect(identityRegistry.contains(bobWallet.address)).to.eventually.be.false; + await expect(identityRegistry.contains(anotherWallet.address)).to.eventually.be.true; await expect(tx).to.emit(token, 'RecoverySuccess').withArgs(bobWallet.address, anotherWallet.address, bobIdentity.target); - await expect(tx).to.emit(token, 'AddressFrozen').withArgs(anotherWallet.address, true, tokenAgent.address); }); }); - describe('when wallet has frozen token', () => { - it('should recover and freeze tokens on the new wallet', async () => { + describe('when a recovery already happened on another token with same IRS', () => { + it('should recover without touching IRS', async () => { const { - suite: { token }, + suite: { token, identityRegistry }, accounts: { tokenAgent, bobWallet, anotherWallet }, identities: { bobIdentity }, } = await loadFixture(deployFullSuiteFixture); - await bobIdentity - .connect(bobWallet) - .addKey(ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address'], [anotherWallet.address])), 1, 1); + await identityRegistry.connect(tokenAgent).deleteIdentity(bobWallet.address); + await identityRegistry.connect(tokenAgent).registerIdentity(anotherWallet.address, bobIdentity.target, 1); - await token.connect(tokenAgent).freezePartialTokens(bobWallet.address, 50); + const tx = await token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target); + + await expect(identityRegistry.contains(bobWallet.address)).to.eventually.be.false; + await expect(identityRegistry.contains(anotherWallet.address)).to.eventually.be.true; + await expect(tx).to.emit(token, 'RecoverySuccess').withArgs(bobWallet.address, anotherWallet.address, bobIdentity.target); + }); + }); + + describe('when the old wallet is frozen', () => { + describe('when the new wallet is not frozen', () => { + it('should transfer the frozen status and transfer frozen tokens', async () => { + const { + suite: { token }, + accounts: { tokenAgent, bobWallet, anotherWallet }, + identities: { bobIdentity }, + } = await loadFixture(deployFullSuiteFixture); + + await token.connect(tokenAgent).setAddressFrozen(bobWallet.address, true); + await token.connect(tokenAgent).freezePartialTokens(bobWallet.address, 50); + + const tx = await token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target); + + await expect(token.isFrozen(anotherWallet.address)).to.eventually.be.true; + await expect(token.getFrozenTokens(anotherWallet.address)).to.eventually.eq(50); + await expect(tx).to.emit(token, 'TokensFrozen').withArgs(anotherWallet.address, 50); + }); + }); + describe('when the new wallet is already frozen', () => { + it('should transfer frozen tokens and keep freeze status', async () => { + const { + suite: { token }, + accounts: { tokenAgent, bobWallet, anotherWallet }, + identities: { bobIdentity }, + } = await loadFixture(deployFullSuiteFixture); + + await token.connect(tokenAgent).setAddressFrozen(bobWallet.address, true); + await token.connect(tokenAgent).setAddressFrozen(anotherWallet.address, true); + await token.connect(tokenAgent).freezePartialTokens(bobWallet.address, 30); + + const tx = await token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target); + + await expect(token.isFrozen(anotherWallet.address)).to.eventually.be.true; + await expect(token.getFrozenTokens(anotherWallet.address)).to.eventually.eq(30); + await expect(tx).to.emit(token, 'TokensFrozen').withArgs(anotherWallet.address, 30); + }); + }); + }); + describe('when there are no frozen tokens', () => { + it('should recover tokens without freezing any', async () => { + const { + suite: { token }, + accounts: { tokenAgent, bobWallet, anotherWallet }, + identities: { bobIdentity }, + } = await loadFixture(deployFullSuiteFixture); const tx = await token.connect(tokenAgent).recoveryAddress(bobWallet.address, anotherWallet.address, bobIdentity.target); - await expect(token.getFrozenTokens(anotherWallet.address)).to.be.eventually.eq(50); + + await expect(token.getFrozenTokens(anotherWallet.address)).to.eventually.eq(0); await expect(tx).to.emit(token, 'RecoverySuccess').withArgs(bobWallet.address, anotherWallet.address, bobIdentity.target); - await expect(tx).to.emit(token, 'TokensFrozen').withArgs(anotherWallet.address, 50); }); }); }); From da86c443eec2e249c904bf336c787e1584a50f54 Mon Sep 17 00:00:00 2001 From: Joachim Date: Tue, 20 Aug 2024 16:32:06 +0800 Subject: [PATCH 33/55] TREX-84 optional eligibility checks (#221) - add functions for optional eligibility - add tests - add natspec - update changelog --- CHANGELOG.md | 9 ++ .../implementation/IdentityRegistry.sol | 26 ++++ .../registry/interface/IIdentityRegistry.sol | 39 ++++++ contracts/registry/storage/IRStorage.sol | 5 +- test/registries/identity-registry.test.ts | 116 ++++++++++++++++++ 5 files changed, 194 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bad06f2..658ee0e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,15 @@ All notable changes to this project will be documented in this file. - Events: `DefaultAllowance`, `DefaultAllowanceDisabled`, `DefaultAllowanceEnabled`. - Enhanced the `allowance` function to return `type(uint256).max` for addresses with default allowance enabled, unless the user has opted out. +- **Eligibility Checks Toggle**: + - Added the ability for the token owner to enable or disable eligibility checks on the `IdentityRegistry` contract. + - **`disableEligibilityChecks`**: Allows the token owner to disable eligibility checks, making all addresses automatically verified by the `isVerified` function. + - **`enableEligibilityChecks`**: Allows the token owner to re-enable eligibility checks, restoring the full verification process. + - Introduced custom errors and events: + - Custom errors: `EligibilityChecksDisabledAlready`, `EligibilityChecksEnabledAlready`. + - Events: `EligibilityChecksDisabled`, `EligibilityChecksEnabled`. + - This feature provides flexibility for issuers to launch tokens with or without eligibility checks, based on their needs. + - **ERC-165 Interface Implementation**: - Implemented ERC-165 support across all major contracts in the suite, allowing them to explicitly declare the interfaces they support. This enhancement improves interoperability and makes it easier for external contracts and tools to interact with T-REX contracts. - ERC-165 support was added to the following contracts: diff --git a/contracts/registry/implementation/IdentityRegistry.sol b/contracts/registry/implementation/IdentityRegistry.sol index 97adbfa6..052e3a78 100644 --- a/contracts/registry/implementation/IdentityRegistry.sol +++ b/contracts/registry/implementation/IdentityRegistry.sol @@ -75,6 +75,11 @@ import "../../errors/InvalidArgumentErrors.sol"; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import "../../roles/IERC173.sol"; +/// error triggered when eligibility checks are disabled and the disable function is called +error EligibilityChecksDisabledAlready(); + +/// error triggered when eligibility checks are enabled and the enable function is called +error EligibilityChecksEnabledAlready(); contract IdentityRegistry is IIdentityRegistry, AgentRoleUpgradeable, IRStorage, IERC165 { @@ -100,9 +105,11 @@ contract IdentityRegistry is IIdentityRegistry, AgentRoleUpgradeable, IRStorage, _tokenTopicsRegistry = IClaimTopicsRegistry(_claimTopicsRegistry); _tokenIssuersRegistry = ITrustedIssuersRegistry(_trustedIssuersRegistry); _tokenIdentityStorage = IIdentityRegistryStorage(_identityStorage); + _checksDisabled = false; emit ClaimTopicsRegistrySet(_claimTopicsRegistry); emit TrustedIssuersRegistrySet(_trustedIssuersRegistry); emit IdentityStorageSet(_identityStorage); + emit EligibilityChecksEnabled(); __Ownable_init(); } @@ -169,11 +176,30 @@ contract IdentityRegistry is IIdentityRegistry, AgentRoleUpgradeable, IRStorage, emit TrustedIssuersRegistrySet(_trustedIssuersRegistry); } + /** + * @dev See {IIdentityRegistry-disableEligibilityChecks}. + */ + function disableEligibilityChecks() external override onlyOwner { + require(!_checksDisabled, EligibilityChecksDisabledAlready()); + _checksDisabled = true; + emit EligibilityChecksDisabled(); + } + + /** + * @dev See {IIdentityRegistry-enableEligibilityChecks}. + */ + function enableEligibilityChecks() external override onlyOwner { + require(_checksDisabled, EligibilityChecksEnabledAlready()); + _checksDisabled = false; + emit EligibilityChecksEnabled(); + } + /** * @dev See {IIdentityRegistry-isVerified}. */ // solhint-disable-next-line code-complexity function isVerified(address _userAddress) external view override returns (bool) { + if(_checksDisabled) {return true;} if (address(identity(_userAddress)) == address(0)) {return false;} uint256[] memory requiredClaimTopics = _tokenTopicsRegistry.getClaimTopics(); if (requiredClaimTopics.length == 0) { diff --git a/contracts/registry/interface/IIdentityRegistry.sol b/contracts/registry/interface/IIdentityRegistry.sol index 60b29d7b..7639687f 100644 --- a/contracts/registry/interface/IIdentityRegistry.sol +++ b/contracts/registry/interface/IIdentityRegistry.sol @@ -103,6 +103,12 @@ event IdentityUpdated(IIdentity indexed _oldIdentity, IIdentity indexed _newIden /// @param _country is the numeric code (ISO 3166-1) of the new country event CountryUpdated(address indexed _investorAddress, uint16 indexed _country); +/// @dev This event is emitted when Eligibility checks are disabled. +event EligibilityChecksDisabled(); + +/// @dev This event is emitted when Eligibility checks are enabled. +event EligibilityChecksEnabled(); + interface IIdentityRegistry { @@ -192,6 +198,39 @@ interface IIdentityRegistry { uint16[] calldata _countries ) external; + /** + * @dev Disables the eligibility checks for token transfers and other operations. + * + * This function allows the token owner to disable the eligibility checks, effectively bypassing the + * complex verification process normally required for token operations. Once the eligibility checks + * are disabled, all users will be considered verified by the `isVerified` function, allowing them + * to interact with the token without requiring specific claims or issuer validation. + * + * Requirements: + * - The caller must be the owner of the contract. + * - The eligibility checks must not already be disabled; otherwise, the function will revert with an + * `EligibilityChecksDisabledAlready` error. + * + * Emits an `EligibilityChecksDisabled` event upon successful execution. + */ + function disableEligibilityChecks() external; + + /** + * @dev Enables the eligibility checks for token transfers and other operations. + * + * This function allows the token owner to re-enable the eligibility checks after they have been + * disabled. Once re-enabled, the `isVerified` function will resume performing the full verification + * process, checking for the required claims and validating them through trusted issuers. + * + * Requirements: + * - The caller must be the owner of the contract. + * - The eligibility checks must currently be disabled; otherwise, the function will revert with an + * `EligibilityChecksEnabledAlready` error. + * + * Emits an `EligibilityChecksEnabled` event upon successful execution. + */ + function enableEligibilityChecks() external; + /** * @dev This functions checks whether a wallet has its Identity registered or not * in the Identity Registry. diff --git a/contracts/registry/storage/IRStorage.sol b/contracts/registry/storage/IRStorage.sol index edc8c024..a0a1d587 100644 --- a/contracts/registry/storage/IRStorage.sol +++ b/contracts/registry/storage/IRStorage.sol @@ -77,9 +77,12 @@ contract IRStorage { /// @dev Address of the IdentityRegistryStorage Contract IIdentityRegistryStorage internal _tokenIdentityStorage; + /// @dev disables the whole eligibility check system + bool internal _checksDisabled; + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. */ - uint256[49] private __gap; + uint256[48] private __gap; } \ No newline at end of file diff --git a/test/registries/identity-registry.test.ts b/test/registries/identity-registry.test.ts index 3256b5d6..4a8ea631 100644 --- a/test/registries/identity-registry.test.ts +++ b/test/registries/identity-registry.test.ts @@ -280,6 +280,122 @@ describe('IdentityRegistry', () => { }); }); }); + describe('.disableEligibilityChecks()', () => { + describe('when called by a non-owner', () => { + it('should revert with Ownable: caller is not the owner', async () => { + const { + suite: { identityRegistry }, + accounts: { anotherWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await expect(identityRegistry.connect(anotherWallet).disableEligibilityChecks()).to.be.revertedWith('Ownable: caller is not the owner'); + }); + }); + describe('when called by the owner', () => { + it('should disable eligibility checks and allow all addresses to be verified', async () => { + const { + suite: { identityRegistry }, + accounts: { deployer, aliceWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await expect(identityRegistry.connect(deployer).disableEligibilityChecks()).to.emit(identityRegistry, 'EligibilityChecksDisabled'); + + await expect(identityRegistry.isVerified(aliceWallet.address)).to.eventually.be.true; + }); + }); + + describe('when eligibility checks are already disabled', () => { + it('should revert with EligibilityChecksDisabledAlready', async () => { + const { + suite: { identityRegistry }, + accounts: { deployer }, + } = await loadFixture(deployFullSuiteFixture); + + await identityRegistry.connect(deployer).disableEligibilityChecks(); + + await expect(identityRegistry.connect(deployer).disableEligibilityChecks()).to.be.revertedWithCustomError( + identityRegistry, + 'EligibilityChecksDisabledAlready', + ); + }); + }); + }); + describe('.enableEligibilityChecks()', () => { + describe('when called by a non-owner', () => { + it('should revert with Ownable: caller is not the owner', async () => { + const { + suite: { identityRegistry }, + accounts: { anotherWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await expect(identityRegistry.connect(anotherWallet).enableEligibilityChecks()).to.be.revertedWith('Ownable: caller is not the owner'); + }); + }); + describe('when called by the owner after disabling', () => { + it('should re-enable eligibility checks and enforce normal verification', async () => { + const { + suite: { identityRegistry }, + accounts: { deployer, anotherWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await identityRegistry.connect(deployer).disableEligibilityChecks(); + await expect(identityRegistry.isVerified(anotherWallet.address)).to.eventually.be.true; + + await expect(identityRegistry.connect(deployer).enableEligibilityChecks()).to.emit(identityRegistry, 'EligibilityChecksEnabled'); + + await expect(identityRegistry.isVerified(anotherWallet.address)).to.eventually.be.false; + }); + }); + + describe('when eligibility checks are already enabled', () => { + it('should revert with EligibilityChecksEnabledAlready', async () => { + const { + suite: { identityRegistry }, + accounts: { deployer }, + } = await loadFixture(deployFullSuiteFixture); + + await expect(identityRegistry.connect(deployer).enableEligibilityChecks()).to.be.revertedWithCustomError( + identityRegistry, + 'EligibilityChecksEnabledAlready', + ); + }); + }); + }); + + describe('.isVerified()', () => { + describe('when eligibility checks are disabled', () => { + it('should return true for any address', async () => { + const { + suite: { identityRegistry }, + accounts: { deployer, charlieWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await identityRegistry.connect(deployer).disableEligibilityChecks(); + await expect(identityRegistry.isVerified(charlieWallet.address)).to.eventually.be.true; + }); + }); + + describe('when eligibility checks are re-enabled', () => { + it('should resume normal eligibility checks', async () => { + const { + suite: { identityRegistry, claimTopicsRegistry }, + accounts: { deployer, charlieWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await identityRegistry.connect(deployer).disableEligibilityChecks(); + await expect(identityRegistry.isVerified(charlieWallet.address)).to.eventually.be.true; + + await identityRegistry.connect(deployer).enableEligibilityChecks(); + + const topics = await claimTopicsRegistry.getClaimTopics(); + if (topics.length > 0) { + await expect(identityRegistry.isVerified(charlieWallet.address)).to.eventually.be.false; + } else { + await expect(identityRegistry.isVerified(charlieWallet.address)).to.eventually.be.true; + } + }); + }); + }); describe('.supportsInterface()', () => { it('should return false for unsupported interfaces', async () => { const { From 7dbc59d450479e2a8ebb5238eb6ef1a070840d3e Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 21 Aug 2024 11:57:03 +0800 Subject: [PATCH 34/55] TREX-162 : bind and set module (#222) - add function addAndSetModule - add Natspec - add tests - update changelog --- CHANGELOG.md | 4 + .../compliance/modular/IModularCompliance.sol | 34 ++++++ .../compliance/modular/ModularCompliance.sol | 110 ++++++++++-------- test/compliances/module-country-allow.test.ts | 99 ++++++++++++++++ 4 files changed, 198 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 658ee0e9..4b1182ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,10 @@ All notable changes to this project will be documented in this file. - `IAFactory` - Each contract now implements the `supportsInterface` function to identify the supported interfaces, ensuring compliance with ERC-165 standards. +- **Add and Set Module in a Single Transaction**: + - Introduced the `addAndSetModule` function in the `ModularCompliance` contract, allowing the contract owner to add a new compliance module and interact with it in a single transaction. + - This function supports adding a module and performing up to 5 interactions with the module in one call, streamlining the setup process for compliance modules. + ### Updated - **Token Recovery Function**: diff --git a/contracts/compliance/modular/IModularCompliance.sol b/contracts/compliance/modular/IModularCompliance.sol index c43298c4..53b79e28 100644 --- a/contracts/compliance/modular/IModularCompliance.sol +++ b/contracts/compliance/modular/IModularCompliance.sol @@ -138,6 +138,40 @@ interface IModularCompliance { */ function callModuleFunction(bytes calldata callData, address _module) external; + /** + * @dev Adds a module to the modular compliance contract and performs multiple interactions with it in a single transaction. + * + * This function allows the contract owner to add a new compliance module and immediately configure it by calling + * specified functions on the module. This can be useful for setting up the module with initial parameters or configurations + * right after it is added. + * + * @param _module The address of the module to add. The module must either be "plug and play" + * or be able to bind with the compliance contract. + * @param _interactions An array of bytecode representing function calls to be made on the module. + * These interactions are performed after the module is added. + * + * Requirements: + * - The caller must be the owner of the `ModularCompliance` contract. + * - The `_module` address must not be a zero address. + * - The `_module` must not already be bound to the contract. + * - The total number of modules must not exceed 25 after adding the new module. + * - The `_interactions` array must contain no more than 5 elements to prevent out-of-gas errors. + * + * Operations: + * - The function first adds the module using the `addModule` function. + * - Then, it iterates over the `_interactions` array, performing each + * interaction on the module using the `callModuleFunction`. + * + * Emits: + * - A `ModuleAdded` event upon successful addition of the module. + * - A `ModuleInteraction` event for each function call made to the module during the interaction phase. + * + * Reverts if: + * - Any of the above requirements are not met. + * - Any of the module interactions fail during execution. + */ + function addAndSetModule(address _module, bytes[] calldata _interactions) external; + /** * @dev function called whenever tokens are transferred * from one wallet to another diff --git a/contracts/compliance/modular/ModularCompliance.sol b/contracts/compliance/modular/ModularCompliance.sol index f319a2ff..67310fc8 100644 --- a/contracts/compliance/modular/ModularCompliance.sol +++ b/contracts/compliance/modular/ModularCompliance.sol @@ -68,6 +68,7 @@ import "./IModularCompliance.sol"; import "./MCStorage.sol"; import "./modules/IModule.sol"; import "../../errors/ComplianceErrors.sol"; +import "../../errors/CommonErrors.sol"; import "../../errors/InvalidArgumentErrors.sol"; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import "../../roles/IERC173.sol"; @@ -128,23 +129,6 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage, emit TokenUnbound(_token); } - /** - * @dev See {IModularCompliance-addModule}. - */ - function addModule(address _module) external override onlyOwner { - require(_module != address(0), ZeroAddress()); - require(!_moduleBound[_module], ModuleAlreadyBound()); - require(_modules.length <= 24, MaxModulesReached(25)); - IModule module = IModule(_module); - require(module.isPlugAndPlay() || module.canComplianceBind(address(this)), - ComplianceNotSuitableForBindingToModule(_module)); - - module.bindCompliance(address(this)); - _modules.push(_module); - _moduleBound[_module] = true; - emit ModuleAdded(_module); - } - /** * @dev See {IModularCompliance-removeModule}. */ @@ -204,40 +188,14 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage, } /** - * @dev see {IModularCompliance-callModuleFunction}. + * @dev See {IModularCompliance-addAndSetModule}. */ - function callModuleFunction(bytes calldata callData, address _module) external override onlyOwner { - require(_moduleBound[_module], ModuleNotBound()); - // NOTE: Use assembly to call the interaction instead of a low level - // call for two reasons: - // - We don't want to copy the return data, since we discard it for - // interactions. - // - Solidity will under certain conditions generate code to copy input - // calldata twice to memory (the second being a "memcopy loop"). - // solhint-disable-next-line no-inline-assembly - assembly { - let freeMemoryPointer := mload(0x40) // Load the free memory pointer from memory location 0x40 - - // Copy callData from calldata to the free memory location - calldatacopy(freeMemoryPointer, callData.offset, callData.length) - - if iszero( // Check if the call returns zero (indicating failure) - call( // Perform the external call - gas(), // Provide all available gas - _module, // Address of the target module - 0, // No ether is sent with the call - freeMemoryPointer, // Input data starts at the free memory pointer - callData.length, // Input data length - 0, // Output data location (not used) - 0 // Output data size (not used) - ) - ) { - returndatacopy(0, 0, returndatasize()) // Copy return data to memory starting at position 0 - revert(0, returndatasize()) // Revert the transaction with the return data - } + function addAndSetModule(address _module, bytes[] calldata _interactions) external onlyOwner override { + require(_interactions.length <= 5, ArraySizeLimited(5)); + addModule(_module); + for (uint256 i = 0; i < _interactions.length; i++) { + callModuleFunction(_interactions[i], _module); } - - emit ModuleInteraction(_module, _selector(callData)); } /** @@ -274,6 +232,60 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage, return true; } + /** + * @dev See {IModularCompliance-addModule}. + */ + function addModule(address _module) public override onlyOwner { + require(_module != address(0), ZeroAddress()); + require(!_moduleBound[_module], ModuleAlreadyBound()); + require(_modules.length <= 24, MaxModulesReached(25)); + IModule module = IModule(_module); + require(module.isPlugAndPlay() || module.canComplianceBind(address(this)), + ComplianceNotSuitableForBindingToModule(_module)); + + module.bindCompliance(address(this)); + _modules.push(_module); + _moduleBound[_module] = true; + emit ModuleAdded(_module); + } + + /** + * @dev see {IModularCompliance-callModuleFunction}. + */ + function callModuleFunction(bytes calldata callData, address _module) public override onlyOwner { + require(_moduleBound[_module], ModuleNotBound()); + // NOTE: Use assembly to call the interaction instead of a low level + // call for two reasons: + // - We don't want to copy the return data, since we discard it for + // interactions. + // - Solidity will under certain conditions generate code to copy input + // calldata twice to memory (the second being a "memcopy loop"). + // solhint-disable-next-line no-inline-assembly + assembly { + let freeMemoryPointer := mload(0x40) // Load the free memory pointer from memory location 0x40 + + // Copy callData from calldata to the free memory location + calldatacopy(freeMemoryPointer, callData.offset, callData.length) + + if iszero( // Check if the call returns zero (indicating failure) + call( // Perform the external call + gas(), // Provide all available gas + _module, // Address of the target module + 0, // No ether is sent with the call + freeMemoryPointer, // Input data starts at the free memory pointer + callData.length, // Input data length + 0, // Output data location (not used) + 0 // Output data size (not used) + ) + ) { + returndatacopy(0, 0, returndatasize()) // Copy return data to memory starting at position 0 + revert(0, returndatasize()) // Revert the transaction with the return data + } + } + + emit ModuleInteraction(_module, _selector(callData)); + } + /** * @dev See {IERC165-supportsInterface}. */ diff --git a/test/compliances/module-country-allow.test.ts b/test/compliances/module-country-allow.test.ts index 6bedded4..583e9019 100644 --- a/test/compliances/module-country-allow.test.ts +++ b/test/compliances/module-country-allow.test.ts @@ -523,4 +523,103 @@ describe('CountryAllowModule', () => { expect(await countryAllowModule.supportsInterface(ierc165InterfaceId)).to.equal(true); }); }); + describe('.addAndSetModule()', () => { + describe('when module is already bound', () => { + it('should revert', async () => { + const { + suite: { compliance, countryAllowModule }, + accounts: { deployer }, + } = await loadFixture(deployComplianceWithCountryAllowModule); + + await expect(compliance.connect(deployer).addAndSetModule(countryAllowModule.target, [])).to.be.revertedWithCustomError( + compliance, + 'ModuleAlreadyBound', + ); + }); + }); + describe('when calling batchAllowCountries not as owner', () => { + it('should revert', async () => { + const { + suite: { compliance, countryAllowModule }, + accounts: { deployer, anotherWallet }, + } = await loadFixture(deployComplianceWithCountryAllowModule); + + // Remove the module first + await compliance.connect(deployer).removeModule(countryAllowModule.target); + + await expect( + compliance + .connect(anotherWallet) + .addAndSetModule(countryAllowModule.target, [ + new ethers.Interface(['function batchAllowCountries(uint16[] calldata countries)']).encodeFunctionData('batchAllowCountries', [[42]]), + ]), + ).to.be.revertedWith('Ownable: caller is not the owner'); + }); + }); + describe('when providing more than 5 interactions', () => { + it('should revert', async () => { + const { + suite: { compliance, countryAllowModule }, + accounts: { deployer }, + } = await loadFixture(deployComplianceWithCountryAllowModule); + + // Remove the module first + await compliance.connect(deployer).removeModule(countryAllowModule.target); + + const interactions = Array.from({ length: 6 }, () => + new ethers.Interface(['function batchAllowCountries(uint16[] calldata countries)']).encodeFunctionData('batchAllowCountries', [[42]]), + ); + + await expect(compliance.connect(deployer).addAndSetModule(countryAllowModule.target, interactions)).to.be.revertedWithCustomError( + compliance, + 'ArraySizeLimited', + ); + }); + }); + describe('when calling addAllowedCountry twice with the same country code', () => { + it('should revert with CountryAlreadyAllowed', async () => { + const { + suite: { compliance, countryAllowModule }, + accounts: { deployer }, + } = await loadFixture(deployComplianceWithCountryAllowModule); + + // Remove the module first to simulate a fresh start + await compliance.connect(deployer).removeModule(countryAllowModule.target); + + await expect( + compliance + .connect(deployer) + .addAndSetModule(countryAllowModule.target, [ + new ethers.Interface(['function addAllowedCountry(uint16 country)']).encodeFunctionData('addAllowedCountry', [42]), + new ethers.Interface(['function addAllowedCountry(uint16 country)']).encodeFunctionData('addAllowedCountry', [42]), + ]), + ).to.be.revertedWithCustomError(countryAllowModule, 'CountryAlreadyAllowed'); + }); + }); + describe('when calling batchAllowCountries twice successfully', () => { + it('should add the module and interact with it', async () => { + const { + suite: { compliance, countryAllowModule }, + accounts: { deployer }, + } = await loadFixture(deployComplianceWithCountryAllowModule); + + // Remove the module first + await compliance.connect(deployer).removeModule(countryAllowModule.target); + + const tx = await compliance + .connect(deployer) + .addAndSetModule(countryAllowModule.target, [ + new ethers.Interface(['function batchAllowCountries(uint16[] calldata countries)']).encodeFunctionData('batchAllowCountries', [[42]]), + new ethers.Interface(['function batchAllowCountries(uint16[] calldata countries)']).encodeFunctionData('batchAllowCountries', [[66]]), + ]); + + await expect(tx).to.emit(compliance, 'ModuleAdded').withArgs(countryAllowModule.target); + await expect(tx).to.emit(countryAllowModule, 'CountryAllowed').withArgs(compliance.target, 42); + await expect(tx).to.emit(countryAllowModule, 'CountryAllowed').withArgs(compliance.target, 66); + + expect(await countryAllowModule.isCountryAllowed(compliance.target, 42)).to.be.true; + expect(await countryAllowModule.isCountryAllowed(compliance.target, 66)).to.be.true; + }); + }); + }); }); From 23f34e0d5ced11e86c427eda80c5bff52cc44752 Mon Sep 17 00:00:00 2001 From: Joachim Date: Fri, 23 Aug 2024 17:34:16 +0800 Subject: [PATCH 35/55] ERC-3643 interfaces management (#223) - add official ERC-3643 interfaces - separate actual interfaces from official ones, inheriting official interfaces - add official ERC-3643 interfaces detection in ERC-165 implementation - tests - changelog --- CHANGELOG.md | 16 +- contracts/DVD/DVDTransferManager.sol | 16 +- contracts/ERC-3643/IERC3643.sol | 470 ++++++++++++++++++ .../ERC-3643/IERC3643ClaimTopicsRegistry.sol | 74 +++ contracts/ERC-3643/IERC3643Compliance.sol | 150 ++++++ .../ERC-3643/IERC3643IdentityRegistry.sol | 220 ++++++++ .../IERC3643IdentityRegistryStorage.sol | 154 ++++++ .../IERC3643TrustedIssuersRegistry.sol | 136 +++++ .../compliance/modular/IModularCompliance.sol | 98 +--- .../compliance/modular/ModularCompliance.sol | 25 +- .../modular/modules/TransferFeesModule.sol | 2 +- .../authority/TREXImplementationAuthority.sol | 6 +- .../implementation/ClaimTopicsRegistry.sol | 2 +- .../implementation/IdentityRegistry.sol | 7 +- .../IdentityRegistryStorage.sol | 2 +- .../implementation/TrustedIssuersRegistry.sol | 2 +- .../interface/IClaimTopicsRegistry.sol | 36 +- .../registry/interface/IIdentityRegistry.sol | 171 +------ .../interface/IIdentityRegistryStorage.sol | 117 +---- .../interface/ITrustedIssuersRegistry.sol | 93 +--- contracts/token/IToken.sol | 444 +---------------- contracts/token/Token.sol | 17 +- contracts/token/TokenStorage.sol | 8 +- contracts/utils/InterfaceIdCalculator.sol | 60 ++- test/compliance.test.ts | 11 + test/dvd.test.ts | 6 +- test/registries/claim-topics-registry.test.ts | 4 +- .../identity-registry-storage.test.ts | 4 +- test/registries/identity-registry.test.ts | 11 + .../trusted-issuers-registry.test.ts | 4 +- test/token/token-information.test.ts | 11 + 31 files changed, 1361 insertions(+), 1016 deletions(-) create mode 100644 contracts/ERC-3643/IERC3643.sol create mode 100644 contracts/ERC-3643/IERC3643ClaimTopicsRegistry.sol create mode 100644 contracts/ERC-3643/IERC3643Compliance.sol create mode 100644 contracts/ERC-3643/IERC3643IdentityRegistry.sol create mode 100644 contracts/ERC-3643/IERC3643IdentityRegistryStorage.sol create mode 100644 contracts/ERC-3643/IERC3643TrustedIssuersRegistry.sol diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b1182ee..272fe03e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,19 +23,11 @@ All notable changes to this project will be documented in this file. - **ERC-165 Interface Implementation**: - Implemented ERC-165 support across all major contracts in the suite, allowing them to explicitly declare the interfaces they support. This enhancement improves interoperability and makes it easier for external contracts and tools to interact with T-REX contracts. - - ERC-165 support was added to the following contracts: - - `Token` - - `IdentityRegistry` - - `IdentityRegistryStorage` - - `TrustedIssuersRegistry` - - `ClaimTopicsRegistry` - - `TREXGateway` - - `DVATransferManager` - - `ModularCompliance` - - Compliance Modules (e.g., `CountryAllowModule`, `TransferRestrictModule`) - - `TREXImplementationAuthority` - - `IAFactory` - Each contract now implements the `supportsInterface` function to identify the supported interfaces, ensuring compliance with ERC-165 standards. + - In addition to implementing ERC-165, the ERC-3643 interfaces were organized into a new directory, with each interface inheriting from the original ERC-3643 standard interface. This setup allows for future expansion and maintains uniformity across the suite: + - `IERC3643`, `IERC3643IdentityRegistry`, `IERC3643Compliance`, `IERC3643ClaimTopicsRegistry`, `IERC3643TrustedIssuersRegistry`, `IERC3643IdentityRegistryStorage` + - For contracts that extend the ERC-3643 standard with new functions, `supportsInterface` now checks for both the new interface ID and the original ERC-3643 interface ID. + - For interfaces that did not change, `supportsInterface` checks for the ERC-3643 interface ID directly, omitting the empty version-specific interface to avoid redundancy. - **Add and Set Module in a Single Transaction**: - Introduced the `addAndSetModule` function in the `ModularCompliance` contract, allowing the contract owner to add a new compliance module and interact with it in a single transaction. diff --git a/contracts/DVD/DVDTransferManager.sol b/contracts/DVD/DVDTransferManager.sol index 58255c42..a0ce737e 100644 --- a/contracts/DVD/DVDTransferManager.sol +++ b/contracts/DVD/DVDTransferManager.sol @@ -72,6 +72,8 @@ import "../roles/AgentRole.sol"; import "../token/IToken.sol"; import "../errors/CommonErrors.sol"; import "../errors/InvalidArgumentErrors.sol"; +import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; + /// events @@ -388,20 +390,14 @@ contract DVDTransferManager is Ownable { } /** - * @dev check if `_token` corresponds to a functional TREX token (with identity registry initiated) + * @dev check if `_token` corresponds to a TREX token * @param _token the address token to check - * the function will try to call `identityRegistry()` on - * the address, which is a getter specific to TREX tokens - * if the call pass and returns an address it means that - * the token is a TREX, otherwise it's not a TREX + * the function will check if the address implements IERC3643 * return `true` if the token is a TREX, `false` otherwise */ function isTREX(address _token) public view returns (bool) { - try IToken(_token).identityRegistry() returns (IIdentityRegistry _ir) { - if (address(_ir) != address(0)) { - return true; - } - return false; + try IERC165(_token).supportsInterface(type(IERC3643).interfaceId) returns (bool _trex) { + return _trex; } catch { return false; diff --git a/contracts/ERC-3643/IERC3643.sol b/contracts/ERC-3643/IERC3643.sol new file mode 100644 index 00000000..8af2604e --- /dev/null +++ b/contracts/ERC-3643/IERC3643.sol @@ -0,0 +1,470 @@ +// SPDX-License-Identifier: CC0-1.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// + +pragma solidity 0.8.26; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "./IERC3643IdentityRegistry.sol"; +import "./IERC3643Compliance.sol"; + +/// Events + +/// @dev This event is emitted when the token information is updated. +/// @param _newName is the name of the token. +/// @param _newSymbol is the symbol of the token. +/// @param _newDecimals is the decimals of the token. +/// @param _newVersion is the version of the token. +/// @param _newOnchainID is the address of the onchainID of the token. +event UpdatedTokenInformation(string indexed _newName, string indexed _newSymbol, uint8 _newDecimals, + string _newVersion, address indexed _newOnchainID); + +/// @dev This event is emitted when the IdentityRegistry has been set for the token. +/// @param _identityRegistry is the address of the Identity Registry of the token. +event IdentityRegistryAdded(address indexed _identityRegistry); + +/// @dev This event is emitted when the Compliance has been set for the token. +/// @param _compliance is the address of the Compliance contract of the token. +event ComplianceAdded(address indexed _compliance); + +/// @dev This event is emitted when an investor successfully recovers his tokens. +/// @param _lostWallet is the address of the wallet that the investor lost access to. +/// @param _newWallet is the address of the wallet that the investor provided for the recovery. +/// @param _investorOnchainID is the address of the onchainID of the investor who asked for a recovery. +event RecoverySuccess(address indexed _lostWallet, address indexed _newWallet, address indexed _investorOnchainID); + +/// @dev This event is emitted when the wallet of an investor is frozen or unfrozen. +/// @param _userAddress is the wallet of the investor that is concerned by the freezing status. +/// @param _isFrozen is the freezing status of the wallet. +/// @param _isFrozen equals `true` the wallet is frozen after emission of the event. +/// @param _isFrozen equals `false` the wallet is unfrozen after emission of the event. +/// @param _owner is the address of the agent who called the function to freeze the wallet. +event AddressFrozen(address indexed _userAddress, bool indexed _isFrozen, address indexed _owner); + +/// @dev This event is emitted when a certain amount of tokens is frozen on a wallet. +/// @param _userAddress is the wallet of the investor that is concerned by the freezing status. +/// @param _amount is the amount of tokens that are frozen. +event TokensFrozen(address indexed _userAddress, uint256 _amount); + +/// @dev This event is emitted when a certain amount of tokens is unfrozen on a wallet. +/// @param _userAddress is the wallet of the investor that is concerned by the freezing status. +/// @param _amount is the amount of tokens that are unfrozen. +event TokensUnfrozen(address indexed _userAddress, uint256 _amount); + +/// @dev This event is emitted when the token is paused. +/// @param _userAddress is the address of the wallet that called the pause function +event Paused(address _userAddress); + +/// @dev This event is emitted when the token is unpaused. +/// @param _userAddress is the address of the wallet that called the unpause function. +event Unpaused(address _userAddress); + + +interface IERC3643 is IERC20, IERC20Metadata { + + /// Functions + + /// Setters + + /** + * @dev sets the token name + * @param _name the name of token to set + * Only the owner of the token smart contract can call this function + * emits a `UpdatedTokenInformation` event + */ + function setName(string calldata _name) external; + + /** + * @dev sets the token symbol + * @param _symbol the token symbol to set + * Only the owner of the token smart contract can call this function + * emits a `UpdatedTokenInformation` event + */ + function setSymbol(string calldata _symbol) external; + + /** + * @dev sets the onchain ID of the token + * @param _onchainID the address of the onchain ID to set + * Only the owner of the token smart contract can call this function + * emits a `UpdatedTokenInformation` event + */ + function setOnchainID(address _onchainID) external; + + /** + * @dev Pauses the token contract. When the contract is paused, investors cannot transfer tokens anymore. + * This function can only be called by an agent of the token, provided the agent is not restricted from pausing the token. + * emits a `Paused` event upon successful execution. + * To pause token transfers, the calling agent must have pausing capabilities enabled. + * If the agent is disabled from pausing, the function call will fail. + * The function can be called only when the contract is not already paused. + * error AgentNotAuthorized - Thrown if the agent is disabled from pausing the token, + * indicating they do not have the necessary permissions to execute this function. + */ + function pause() external; + + /** + * @dev Unpauses the token contract, allowing investors to resume token transfers under normal conditions + * This function can only be called by an agent of the token, provided the agent is not restricted from pausing the token. + * emits an `Unpaused` event upon successful execution. + * To unpause token transfers, the calling agent must have pausing capabilities enabled. + * If the agent is disabled from pausing, the function call will fail. + * The function can be called only when the contract is currently paused. + * error AgentNotAuthorized - Thrown if the agent is disabled from pausing the token, + * indicating they do not have the necessary permissions to execute this function. + */ + function unpause() external; + + /** + * @dev Sets an address's frozen status for this token, + * either freezing or unfreezing the address based on the provided boolean value. + * This function can be called by an agent of the token, assuming the agent is not restricted from freezing addresses. + * emits an `AddressFrozen` event upon successful execution. + * @param _userAddress The address for which to update the frozen status. + * @param _freeze The frozen status to be applied: `true` to freeze, `false` to unfreeze. + * @notice To change an address's frozen status, the calling agent must have the capability to freeze addresses enabled. + * If the agent is disabled from freezing addresses, the function call will fail. + * error AgentNotAuthorized - Thrown if the agent is disabled from freezing addresses, + * indicating they do not have the necessary permissions to execute this function. + */ + function setAddressFrozen(address _userAddress, bool _freeze) external; + + /** + * @dev Freezes a specified token amount for a given address, preventing those tokens from being transferred. + * This function can be called by an agent of the token, provided the agent is not restricted from freezing tokens. + * emits a `TokensFrozen` event upon successful execution. + * @param _userAddress The address for which to freeze tokens. + * @param _amount The amount of tokens to be frozen. + * @notice To freeze tokens for an address, the calling agent must have the capability to freeze tokens enabled. + * If the agent is disabled from freezing tokens, the function call will fail. + * error AgentNotAuthorized - Thrown if the agent is disabled from freezing tokens, + * indicating they do not have the necessary permissions to execute this function. + */ + function freezePartialTokens(address _userAddress, uint256 _amount) external; + + /** + * @dev Unfreezes a specified token amount for a given address, allowing those tokens to be transferred again. + * This function can be called by an agent of the token, assuming the agent is not restricted from unfreezing tokens. + * emits a `TokensUnfrozen` event upon successful execution. + * @param _userAddress The address for which to unfreeze tokens. + * @param _amount The amount of tokens to be unfrozen. + * @notice To unfreeze tokens for an address, the calling agent must have the capability to unfreeze tokens enabled. + * If the agent is disabled from unfreezing tokens, the function call will fail. + * error AgentNotAuthorized - Thrown if the agent is disabled from unfreezing tokens, + * indicating they do not have the necessary permissions to execute this function. + */ + function unfreezePartialTokens(address _userAddress, uint256 _amount) external; + + /** + * @dev sets the Identity Registry for the token + * @param _identityRegistry the address of the Identity Registry to set + * Only the owner of the token smart contract can call this function + * emits an `IdentityRegistryAdded` event + */ + function setIdentityRegistry(address _identityRegistry) external; + + /** + * @dev sets the compliance contract of the token + * @param _compliance the address of the compliance contract to set + * Only the owner of the token smart contract can call this function + * calls bindToken on the compliance contract + * emits a `ComplianceAdded` event + */ + function setCompliance(address _compliance) external; + + /// Transfer Actions + + /** + * @dev Initiates a forced transfer of tokens between two whitelisted wallets. + * If the `from` address does not have sufficient free tokens (unfrozen tokens) + * but possesses a total balance equal to or greater than the specified `amount`, + * the frozen token amount is reduced to ensure enough free tokens for the transfer. + * In such cases, the remaining balance in the `from` account consists entirely of frozen tokens post-transfer. + * It is imperative that the `to` address is a verified and whitelisted address. + * @param _from The address of the sender. + * @param _to The address of the receiver. + * @param _amount The number of tokens to be transferred. + * This function can only be invoked by a wallet designated as an agent of the token, + * provided the agent is not restricted from initiating forced transfers of the token. + * Emits a `TokensUnfrozen` event if `_amount` is higher than the free balance of `_from`. + * Also emits a `Transfer` event. + * To execute this function, the calling agent must not be restricted from initiating forced transfers of the token. + * If the agent is restricted from this capability, the function call will fail. + * The function can only be called when the contract is not already paused. + * error `AgentNotAuthorized` - Thrown if the agent is restricted from initiating forced transfers of the token, + * indicating they do not have the necessary permissions to execute this function. + */ + function forcedTransfer( + address _from, + address _to, + uint256 _amount + ) external returns (bool); + + /** + * @dev Mints tokens to a specified address. + * This enhanced version of the default mint method allows tokens to be minted + * to an address only if it is a verified and whitelisted address according to the security token. + * @param _to Address to mint the tokens to. + * @param _amount Amount of tokens to mint. + * This function can only be called by a wallet designated as an agent of the token, + * provided the agent is not restricted from minting tokens. + * Emits a `Transfer` event upon successful minting. + * To execute this function, the calling agent must not be restricted from minting tokens. + * If the agent is restricted from this capability, the function call will fail. + */ + function mint(address _to, uint256 _amount) external; + + /** + * @dev Burns tokens from a specified address. + * If the account address does not have sufficient free tokens (unfrozen tokens) + * but possesses a total balance equal to or greater than the specified value, + * the frozen token amount is reduced to ensure enough free tokens for the burn. + * In such cases, the remaining balance in the account consists entirely of frozen tokens post-transaction. + * @param _userAddress Address to burn the tokens from. + * @param _amount Amount of tokens to burn. + * This function can only be called by a wallet designated as an agent of the token, + * provided the agent is not restricted from burning tokens. + * Emits a `TokensUnfrozen` event if `_amount` exceeds the free balance of `_userAddress`. + * Also emits a `Transfer` event. + * To execute this function, the calling agent must not be restricted from burning tokens. + * If the agent is restricted from this capability, the function call will fail. + */ + function burn(address _userAddress, uint256 _amount) external; + + /** + * @dev Initiates a recovery process to transfer tokens and associated states + * from a lost wallet to a new wallet for an investor. + * + * This function allows an authorized agent to recover tokens from a lost wallet, + * transferring them to a new wallet while preserving the investor's + * identity and status within the token ecosystem. The function ensures that all relevant data, + * including frozen tokens and address freezing status, is accurately transferred to the new wallet. + * + * @param _lostWallet The wallet that the investor lost, containing the tokens to be recovered. + * @param _newWallet The newly provided wallet to which tokens and associated statuses must be transferred. + * @param _investorOnchainID The ONCHAINID of the investor whose tokens are being recovered. + * + * Requirements: + * - The caller must be an agent authorized to perform recovery operations, with no restrictions on this capability. + * - The `_lostWallet` must have a non-zero token balance; otherwise, the recovery is unnecessary and will revert. + * - Either the `_lostWallet` or the `_newWallet` must be present in the identity registry; + * if neither is present, the function will revert. + * + * Operations: + * - Transfers the entire token balance from `_lostWallet` to `_newWallet`. + * - Transfers any frozen tokens from `_lostWallet` to `_newWallet`, updating the frozen token count accordingly. + * - Transfers the address freeze status from `_lostWallet` to `_newWallet`, + * ensuring the new wallet retains any restrictions if applicable. + * - Updates the identity registry: + * - If `_lostWallet` is listed in the identity registry, it will be removed, + * and `_newWallet` will be registered unless already present. + * + * Emits the following events: + * - `TokensUnfrozen` if there are frozen tokens on `_lostWallet` that are transferred. + * - `TokensFrozen` if frozen tokens are added to `_newWallet`. + * - `AddressFrozen` if the freeze status of either wallet changes. + * - `Transfer` to reflect the movement of tokens from `_lostWallet` to `_newWallet`. + * - `RecoverySuccess` upon successful completion of the recovery process. + * + * Reverts if: + * - The agent calling the function does not have the necessary permissions to perform recovery (`AgentNotAuthorized`). + * - The `_lostWallet` has no tokens to recover (`NoTokenToRecover`). + * - Neither `_lostWallet` nor `_newWallet` is present in the identity registry (`RecoveryNotPossible`). + * + * @return A boolean value indicating whether the recovery process was successful. + */ + function recoveryAddress( + address _lostWallet, + address _newWallet, + address _investorOnchainID + ) external returns (bool); + + /// Batch Actions + + /** + * @dev function allowing to issue transfers in batch + * Require that the msg.sender and `to` addresses are not frozen. + * Require that the total value should not exceed available balance. + * Require that the `to` addresses are all verified addresses, + * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_toList.length` IS TOO HIGH, + * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION + * @param _toList The addresses of the receivers + * @param _amounts The number of tokens to transfer to the corresponding receiver + * emits _toList.length `Transfer` events + */ + function batchTransfer(address[] calldata _toList, uint256[] calldata _amounts) external; + + /** + * @dev Initiates forced transfers in batch. + * Requires that each _amounts[i] does not exceed the available balance of _fromList[i]. + * Requires that the _toList addresses are all verified and whitelisted addresses. + * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF _fromList.length IS TOO HIGH. + * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. + * @param _fromList The addresses of the senders. + * @param _toList The addresses of the receivers. + * @param _amounts The number of tokens to transfer to the corresponding receiver. + * This function can only be called by a wallet designated as an agent of the token, + * provided the agent is not restricted from initiating forced transfers in batch. + * Emits `TokensUnfrozen` events for each `_amounts[i]` that exceeds the free balance of `_fromList[i]`. + * Also emits _fromList.length `Transfer` events upon successful batch transfer. + * To execute this function, the calling agent must not be restricted from initiating forced transfer. + * If the agent is restricted from this capability, the function call will fail. + */ + function batchForcedTransfer( + address[] calldata _fromList, + address[] calldata _toList, + uint256[] calldata _amounts + ) external; + + /** + * @dev Initiates minting of tokens in batch. + * Requires that the `_toList` addresses are all verified and whitelisted addresses. + * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_toList.length` IS TOO HIGH. + * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. + * @param _toList The addresses of the receivers. + * @param _amounts The number of tokens to mint to the corresponding receiver. + * This function can only be called by a wallet designated as an agent of the token, + * provided the agent is not restricted from minting tokens. + * Emits _toList.length `Transfer` events upon successful batch minting. + * To execute this function, the calling agent must not be restricted from minting tokens. + * If the agent is restricted from this capability, the function call will fail. + */ + function batchMint(address[] calldata _toList, uint256[] calldata _amounts) external; + + /** + * @dev Initiates burning of tokens in batch. + * Requires that the `_userAddresses` addresses are all verified and whitelisted addresses. + * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH. + * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. + * @param _userAddresses The addresses of the wallets concerned by the burn. + * @param _amounts The number of tokens to burn from the corresponding wallets. + * This function can only be called by a wallet designated as an agent of the token, + * provided the agent is not restricted from burning tokens. + * Emits _userAddresses.length `Transfer` events upon successful batch burn. + * To execute this function, the calling agent must not be restricted from burning tokens. + * If the agent is restricted from this capability, the function call will fail. + */ + function batchBurn(address[] calldata _userAddresses, uint256[] calldata _amounts) external; + + /** + * @dev Initiates setting of frozen status for addresses in batch. + * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH. + * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. + * @param _userAddresses The addresses for which to update frozen status. + * @param _freeze Frozen status of the corresponding address. + * This function can only be called by a wallet designated as an agent of the token, + * provided the agent is not restricted from setting frozen addresses. + * Emits _userAddresses.length `AddressFrozen` events upon successful batch update of frozen status. + * To execute this function, the calling agent must not be restricted from setting frozen addresses. + * If the agent is restricted from this capability, the function call will fail. + */ + function batchSetAddressFrozen(address[] calldata _userAddresses, bool[] calldata _freeze) external; + + /** + * @dev Initiates partial freezing of tokens in batch. + * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH. + * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. + * @param _userAddresses The addresses on which tokens need to be partially frozen. + * @param _amounts The amount of tokens to freeze on the corresponding address. + * This function can only be called by a wallet designated as an agent of the token, + * provided the agent is not restricted from partially freezing tokens. + * Emits _userAddresses.length `TokensFrozen` events upon successful batch partial freezing. + * To execute this function, the calling agent must not be restricted from partially freezing tokens. + * If the agent is restricted from this capability, the function call will fail. + */ + function batchFreezePartialTokens(address[] calldata _userAddresses, uint256[] calldata _amounts) external; + + /** + * @dev Initiates partial unfreezing of tokens in batch. + * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH. + * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. + * @param _userAddresses The addresses on which tokens need to be partially unfrozen. + * @param _amounts The amount of tokens to unfreeze on the corresponding address. + * This function can only be called by a wallet designated as an agent of the token, + * provided the agent is not restricted from partially freezing tokens. + * Emits _userAddresses.length `TokensUnfrozen` events upon successful batch partial unfreezing. + * To execute this function, the calling agent must not be restricted from partially freezing tokens. + * If the agent is restricted from this capability, the function call will fail. + */ + function batchUnfreezePartialTokens(address[] calldata _userAddresses, uint256[] calldata _amounts) external; + + /// Getters + + /** + * @dev Returns the address of the onchainID of the token. + * the onchainID of the token gives all the information available + * about the token and is managed by the token issuer or his agent. + */ + function onchainID() external view returns (address); + /** + * @dev Returns the TREX version of the token. + */ + function version() external view returns (string memory); + + /** + * @dev Returns the Identity Registry linked to the token + */ + function identityRegistry() external view returns (IERC3643IdentityRegistry); + + /** + * @dev Returns the Compliance contract linked to the token + */ + function compliance() external view returns (IERC3643Compliance); + + /** + * @dev Returns true if the contract is paused, and false otherwise. + */ + function paused() external view returns (bool); + + /** + * @dev Returns the freezing status of a wallet + * if isFrozen returns `true` the wallet is frozen + * if isFrozen returns `false` the wallet is not frozen + * isFrozen returning `true` doesn't mean that the balance is free, tokens could be blocked by + * a partial freeze or the whole token could be blocked by pause + * @param _userAddress the address of the wallet on which isFrozen is called + */ + function isFrozen(address _userAddress) external view returns (bool); + + /** + * @dev Returns the amount of tokens that are partially frozen on a wallet + * the amount of frozen tokens is always <= to the total balance of the wallet + * @param _userAddress the address of the wallet on which getFrozenTokens is called + */ + function getFrozenTokens(address _userAddress) external view returns (uint256); +} diff --git a/contracts/ERC-3643/IERC3643ClaimTopicsRegistry.sol b/contracts/ERC-3643/IERC3643ClaimTopicsRegistry.sol new file mode 100644 index 00000000..256230ca --- /dev/null +++ b/contracts/ERC-3643/IERC3643ClaimTopicsRegistry.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: CC0-1.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// +pragma solidity 0.8.26; + +/// Events + +/// @dev This event is emitted when a claim topic has been added to the ClaimTopicsRegistry. +/// @param _claimTopic is the required claim added to the Claim Topics Registry. +event ClaimTopicAdded(uint256 indexed _claimTopic); + +/// @dev This event is emitted when a claim topic has been removed from the ClaimTopicsRegistry. +/// @param _claimTopic is the required claim removed from the Claim Topics Registry. +event ClaimTopicRemoved(uint256 indexed _claimTopic); + +interface IERC3643ClaimTopicsRegistry { + /** + * @dev Add a trusted claim topic (For example: KYC=1, AML=2). + * Only owner can call. + * emits `ClaimTopicAdded` event + * cannot add more than 15 topics for 1 token as adding more could create gas issues + * @param _claimTopic The claim topic index + */ + function addClaimTopic(uint256 _claimTopic) external; + + /** + * @dev Remove a trusted claim topic (For example: KYC=1, AML=2). + * Only owner can call. + * emits `ClaimTopicRemoved` event + * @param _claimTopic The claim topic index + */ + function removeClaimTopic(uint256 _claimTopic) external; + + /** + * @dev Get the trusted claim topics for the security token + * @return Array of trusted claim topics + */ + function getClaimTopics() external view returns (uint256[] memory); +} diff --git a/contracts/ERC-3643/IERC3643Compliance.sol b/contracts/ERC-3643/IERC3643Compliance.sol new file mode 100644 index 00000000..6f7a3e61 --- /dev/null +++ b/contracts/ERC-3643/IERC3643Compliance.sol @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: CC0-1.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// +pragma solidity 0.8.26; + +/// Events + +/// @dev This event is emitted when a token has been bound to the compliance contract. +/// @param _token is the address of the token to bind. +event TokenBound(address _token); + +/// @dev This event is emitted when a token has been unbound from the compliance contract. +/// @param _token is the address of the token to unbind. +event TokenUnbound(address _token); + +interface IERC3643Compliance { + + + /// Functions + + /// initialization of the compliance contract + + /** + * @dev binds a token to the compliance contract + * @param _token address of the token to bind + * This function can be called ONLY by the owner of the compliance contract + * Emits a TokenBound event + */ + function bindToken(address _token) external; + + /** + * @dev unbinds a token from the compliance contract + * @param _token address of the token to unbind + * This function can be called ONLY by the owner of the compliance contract + * Emits a TokenUnbound event + */ + function unbindToken(address _token) external; + + + + // compliance check and state update + /** + * @dev function called whenever tokens are transferred + * from one wallet to another + * this function can update state variables in the modules bound to the compliance + * these state variables being used by the module checks to decide if a transfer + * is compliant or not depending on the values stored in these state variables and on + * the parameters of the modules + * This function can be called ONLY by the token contract bound to the compliance + * @param _from The address of the sender + * @param _to The address of the receiver + * @param _amount The amount of tokens involved in the transfer + * This function calls moduleTransferAction() on each module bound to the compliance contract + */ + function transferred( + address _from, + address _to, + uint256 _amount + ) external; + + /** + * @dev function called whenever tokens are created on a wallet + * this function can update state variables in the modules bound to the compliance + * these state variables being used by the module checks to decide if a transfer + * is compliant or not depending on the values stored in these state variables and on + * the parameters of the modules + * This function can be called ONLY by the token contract bound to the compliance + * @param _to The address of the receiver + * @param _amount The amount of tokens involved in the minting + * This function calls moduleMintAction() on each module bound to the compliance contract + */ + function created(address _to, uint256 _amount) external; + + /** + * @dev function called whenever tokens are destroyed from a wallet + * this function can update state variables in the modules bound to the compliance + * these state variables being used by the module checks to decide if a transfer + * is compliant or not depending on the values stored in these state variables and on + * the parameters of the modules + * This function can be called ONLY by the token contract bound to the compliance + * @param _from The address on which tokens are burnt + * @param _amount The amount of tokens involved in the burn + * This function calls moduleBurnAction() on each module bound to the compliance contract + */ + function destroyed(address _from, uint256 _amount) external; + + /** + * @dev checks that the transfer is compliant. + * default compliance always returns true + * READ ONLY FUNCTION, this function cannot be used to increment + * counters, emit events, ... + * @param _from The address of the sender + * @param _to The address of the receiver + * @param _amount The amount of tokens involved in the transfer + * This function will call moduleCheck() on every module bound to the compliance + * If each of the module checks return TRUE, this function will return TRUE as well + * returns FALSE otherwise + */ + function canTransfer( + address _from, + address _to, + uint256 _amount + ) external view returns (bool); + + /// check the parameters of the compliance contract + + function isTokenBound(address _token) external view returns (bool); + + /** + * @dev getter for the address of the token bound + * returns the address of the token + */ + function getTokenBound() external view returns (address); + +} diff --git a/contracts/ERC-3643/IERC3643IdentityRegistry.sol b/contracts/ERC-3643/IERC3643IdentityRegistry.sol new file mode 100644 index 00000000..d64d8a59 --- /dev/null +++ b/contracts/ERC-3643/IERC3643IdentityRegistry.sol @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: CC0-1.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// +pragma solidity 0.8.26; + +import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; +import "./IERC3643IdentityRegistryStorage.sol"; +import "./IERC3643TrustedIssuersRegistry.sol"; +import "./IERC3643ClaimTopicsRegistry.sol"; + +/// Events + +/// @dev This event is emitted when the ClaimTopicsRegistry has been set for the IdentityRegistry. +/// @param _claimTopicsRegistry is the address of the Claim Topics Registry contract. +event ClaimTopicsRegistrySet(address indexed _claimTopicsRegistry); + +/// @dev This event is emitted when the IdentityRegistryStorage has been set for the IdentityRegistry. +/// @param _identityStorage is the address of the Identity Registry Storage contract. +event IdentityStorageSet(address indexed _identityStorage); + +/// @dev This event is emitted when the TrustedIssuersRegistry has been set for the IdentityRegistry. +/// @param _trustedIssuersRegistry is the address of the Trusted Issuers Registry contract. +event TrustedIssuersRegistrySet(address indexed _trustedIssuersRegistry); + +/// @dev This event is emitted when an Identity is registered into the Identity Registry. +/// @param _investorAddress is the address of the investor's wallet. +/// @param _identity is the address of the Identity smart contract (onchainID). +event IdentityRegistered(address indexed _investorAddress, IIdentity indexed _identity); + +/// @dev This event is emitted when an Identity is removed from the Identity Registry. +/// @param _investorAddress is the address of the investor's wallet. +/// @param _identity is the address of the Identity smart contract (onchainID). +event IdentityRemoved(address indexed _investorAddress, IIdentity indexed _identity); + +/// @dev This event is emitted when an Identity has been updated. +/// @param _oldIdentity is the old Identity contract's address to update. +/// @param _newIdentity is the new Identity contract's. +event IdentityUpdated(IIdentity indexed _oldIdentity, IIdentity indexed _newIdentity); + +/// @dev This event is emitted when an Identity's country has been updated. +/// @param _investorAddress is the address on which the country has been updated +/// @param _country is the numeric code (ISO 3166-1) of the new country +event CountryUpdated(address indexed _investorAddress, uint16 indexed _country); + +interface IERC3643IdentityRegistry { + + /// Functions + + /// Identity Registry Setters + + /** + * @dev Replace the actual identityRegistryStorage contract with a new one. + * This function can only be called by the wallet set as owner of the smart contract + * @param _identityRegistryStorage The address of the new Identity Registry Storage + * emits `IdentityStorageSet` event + */ + function setIdentityRegistryStorage(address _identityRegistryStorage) external; + + /** + * @dev Replace the actual claimTopicsRegistry contract with a new one. + * This function can only be called by the wallet set as owner of the smart contract + * @param _claimTopicsRegistry The address of the new claim Topics Registry + * emits `ClaimTopicsRegistrySet` event + */ + function setClaimTopicsRegistry(address _claimTopicsRegistry) external; + + /** + * @dev Replace the actual trustedIssuersRegistry contract with a new one. + * This function can only be called by the wallet set as owner of the smart contract + * @param _trustedIssuersRegistry The address of the new Trusted Issuers Registry + * emits `TrustedIssuersRegistrySet` event + */ + function setTrustedIssuersRegistry(address _trustedIssuersRegistry) external; + + /// Registry Actions + /** + * @dev Register an identity contract corresponding to a user address. + * Requires that the user doesn't have an identity contract already registered. + * This function can only be called by a wallet set as agent of the smart contract + * @param _userAddress The address of the user + * @param _identity The address of the user's identity contract + * @param _country The country of the investor + * emits `IdentityRegistered` event + */ + function registerIdentity( + address _userAddress, + IIdentity _identity, + uint16 _country + ) external; + + /** + * @dev Removes an user from the identity registry. + * Requires that the user have an identity contract already deployed that will be deleted. + * This function can only be called by a wallet set as agent of the smart contract + * @param _userAddress The address of the user to be removed + * emits `IdentityRemoved` event + */ + function deleteIdentity(address _userAddress) external; + + /** + * @dev Updates the country corresponding to a user address. + * Requires that the user should have an identity contract already deployed that will be replaced. + * This function can only be called by a wallet set as agent of the smart contract + * @param _userAddress The address of the user + * @param _country The new country of the user + * emits `CountryUpdated` event + */ + function updateCountry(address _userAddress, uint16 _country) external; + + /** + * @dev Updates an identity contract corresponding to a user address. + * Requires that the user address should be the owner of the identity contract. + * Requires that the user should have an identity contract already deployed that will be replaced. + * This function can only be called by a wallet set as agent of the smart contract + * @param _userAddress The address of the user + * @param _identity The address of the user's new identity contract + * emits `IdentityUpdated` event + */ + function updateIdentity(address _userAddress, IIdentity _identity) external; + + /** + * @dev function allowing to register identities in batch + * This function can only be called by a wallet set as agent of the smart contract + * Requires that none of the users has an identity contract already registered. + * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH, + * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION + * @param _userAddresses The addresses of the users + * @param _identities The addresses of the corresponding identity contracts + * @param _countries The countries of the corresponding investors + * emits _userAddresses.length `IdentityRegistered` events + */ + function batchRegisterIdentity( + address[] calldata _userAddresses, + IIdentity[] calldata _identities, + uint16[] calldata _countries + ) external; + + /// Registry Consultation + + /** + * @dev This functions checks whether a wallet has its Identity registered or not + * in the Identity Registry. + * @param _userAddress The address of the user to be checked. + * @return 'True' if the address is contained in the Identity Registry, 'false' if not. + */ + function contains(address _userAddress) external view returns (bool); + + /** + * @dev This functions checks whether an identity contract + * corresponding to the provided user address has the required claims or not based + * on the data fetched from trusted issuers registry and from the claim topics registry + * @param _userAddress The address of the user to be verified. + * @return 'True' if the address is verified, 'false' if not. + */ + function isVerified(address _userAddress) external view returns (bool); + + /** + * @dev Returns the onchainID of an investor. + * @param _userAddress The wallet of the investor + */ + function identity(address _userAddress) external view returns (IIdentity); + + /** + * @dev Returns the country code of an investor. + * @param _userAddress The wallet of the investor + */ + function investorCountry(address _userAddress) external view returns (uint16); + + // identity registry getters + /** + * @dev Returns the IdentityRegistryStorage linked to the current IdentityRegistry. + */ + function identityStorage() external view returns (IERC3643IdentityRegistryStorage); + + /** + * @dev Returns the TrustedIssuersRegistry linked to the current IdentityRegistry. + */ + function issuersRegistry() external view returns (IERC3643TrustedIssuersRegistry); + + /** + * @dev Returns the ClaimTopicsRegistry linked to the current IdentityRegistry. + */ + function topicsRegistry() external view returns (IERC3643ClaimTopicsRegistry); + +} diff --git a/contracts/ERC-3643/IERC3643IdentityRegistryStorage.sol b/contracts/ERC-3643/IERC3643IdentityRegistryStorage.sol new file mode 100644 index 00000000..db68bb8e --- /dev/null +++ b/contracts/ERC-3643/IERC3643IdentityRegistryStorage.sol @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: CC0-1.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// +pragma solidity 0.8.26; +import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; + +/// events + +/// @dev This event is emitted when an Identity is registered into the storage contract. +/// @param _investorAddress` is the address of the investor's wallet. +/// @param _identity` is the address of the Identity smart contract (onchainID). +event IdentityStored(address indexed _investorAddress, IIdentity indexed _identity); + +/// @dev This event is emitted when an Identity is removed from the storage contract. +/// @param _investorAddress is the address of the investor's wallet. +/// @param _identity is the address of the Identity smart contract (onchainID). +event IdentityUnstored(address indexed _investorAddress, IIdentity indexed _identity); + +/// @dev This event is emitted when an Identity has been updated. +/// @param _oldIdentity is the old Identity contract's address to update. +/// @param _newIdentity is the new Identity contract's. +event IdentityModified(IIdentity indexed _oldIdentity, IIdentity indexed _newIdentity); + +/// @dev This event is emitted when an Identity's country has been updated. +/// @param _investorAddress is the address on which the country has been updated. +/// @param _country is the numeric code (ISO 3166-1) of the new country. +event CountryModified(address indexed _investorAddress, uint16 indexed _country); + +/// @dev This event is emitted when an Identity Registry is bound to the storage contract. +/// @param _identityRegistry is the address of the identity registry added. +event IdentityRegistryBound(address indexed _identityRegistry); + +/// @dev This event is emitted when an Identity Registry is unbound from the storage contract. +/// @param _identityRegistry is the address of the identity registry removed. +event IdentityRegistryUnbound(address indexed _identityRegistry); + +interface IERC3643IdentityRegistryStorage { + + /// functions + + /** + * @dev adds an identity contract corresponding to a user address in the storage. + * Requires that the user doesn't have an identity contract already registered. + * This function can only be called by an address set as agent of the smart contract + * @param _userAddress The address of the user + * @param _identity The address of the user's identity contract + * @param _country The country of the investor + * emits `IdentityStored` event + */ + function addIdentityToStorage( + address _userAddress, + IIdentity _identity, + uint16 _country + ) external; + + /** + * @dev Removes an user from the storage. + * Requires that the user have an identity contract already deployed that will be deleted. + * This function can only be called by an address set as agent of the smart contract + * @param _userAddress The address of the user to be removed + * emits `IdentityUnstored` event + */ + function removeIdentityFromStorage(address _userAddress) external; + + /** + * @dev Updates the country corresponding to a user address. + * Requires that the user should have an identity contract already deployed that will be replaced. + * This function can only be called by an address set as agent of the smart contract + * @param _userAddress The address of the user + * @param _country The new country of the user + * emits `CountryModified` event + */ + function modifyStoredInvestorCountry(address _userAddress, uint16 _country) external; + + /** + * @dev Updates an identity contract corresponding to a user address. + * Requires that the user address should be the owner of the identity contract. + * Requires that the user should have an identity contract already deployed that will be replaced. + * This function can only be called by an address set as agent of the smart contract + * @param _userAddress The address of the user + * @param _identity The address of the user's new identity contract + * emits `IdentityModified` event + */ + function modifyStoredIdentity(address _userAddress, IIdentity _identity) external; + + /** + * @notice Adds an identity registry as agent of the Identity Registry Storage Contract. + * This function can only be called by the wallet set as owner of the smart contract + * This function adds the identity registry to the list of identityRegistries linked to the storage contract + * cannot bind more than 300 IR to 1 IRS + * @param _identityRegistry The identity registry address to add. + */ + function bindIdentityRegistry(address _identityRegistry) external; + + /** + * @notice Removes an identity registry from being agent of the Identity Registry Storage Contract. + * This function can only be called by the wallet set as owner of the smart contract + * This function removes the identity registry from the list of identityRegistries linked to the storage contract + * @param _identityRegistry The identity registry address to remove. + */ + function unbindIdentityRegistry(address _identityRegistry) external; + + /** + * @dev Returns the identity registries linked to the storage contract + */ + function linkedIdentityRegistries() external view returns (address[] memory); + + /** + * @dev Returns the onchainID of an investor. + * @param _userAddress The wallet of the investor + */ + function storedIdentity(address _userAddress) external view returns (IIdentity); + + /** + * @dev Returns the country code of an investor. + * @param _userAddress The wallet of the investor + */ + function storedInvestorCountry(address _userAddress) external view returns (uint16); +} diff --git a/contracts/ERC-3643/IERC3643TrustedIssuersRegistry.sol b/contracts/ERC-3643/IERC3643TrustedIssuersRegistry.sol new file mode 100644 index 00000000..06ed14f0 --- /dev/null +++ b/contracts/ERC-3643/IERC3643TrustedIssuersRegistry.sol @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: CC0-1.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// +pragma solidity 0.8.26; +import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; + +/// Events + +/// @dev This event is emitted when a trusted issuer is added in the registry. +/// @param _trustedIssuer is the address of the trusted issuer's ClaimIssuer contract. +/// @param _claimTopics is the set of claims that the trusted issuer is allowed to emit. +event TrustedIssuerAdded(IClaimIssuer indexed _trustedIssuer, uint256[] _claimTopics); + +/// @dev This event is emitted when a trusted issuer is removed from the registry. +/// @param _trustedIssuer is the address of the trusted issuer's ClaimIssuer contract. +event TrustedIssuerRemoved(IClaimIssuer indexed _trustedIssuer); + +/// &dev This event is emitted when the set of claim topics is changed for a given trusted issuer. +/// @param _trustedIssuer is the address of the trusted issuer's ClaimIssuer contract +/// @param _claimTopics is the set of claims that the trusted issuer is allowed to emit. +event ClaimTopicsUpdated(IClaimIssuer indexed _trustedIssuer, uint256[] _claimTopics); + + +interface IERC3643TrustedIssuersRegistry { + + // Functions + + // Setters + /** + * @dev registers a ClaimIssuer contract as trusted claim issuer. + * Requires that a ClaimIssuer contract doesn't already exist + * Requires that the claimTopics set is not empty + * Requires that there is no more than 15 claimTopics + * Requires that there is no more than 50 Trusted issuers + * @param _trustedIssuer The ClaimIssuer contract address of the trusted claim issuer. + * @param _claimTopics the set of claim topics that the trusted issuer is allowed to emit + * This function can only be called by the owner of the Trusted Issuers Registry contract + * emits a `TrustedIssuerAdded` event + */ + function addTrustedIssuer(IClaimIssuer _trustedIssuer, uint256[] calldata _claimTopics) external; + + /** + * @dev Removes the ClaimIssuer contract of a trusted claim issuer. + * Requires that the claim issuer contract to be registered first + * @param _trustedIssuer the claim issuer to remove. + * This function can only be called by the owner of the Trusted Issuers Registry contract + * emits a `TrustedIssuerRemoved` event + */ + function removeTrustedIssuer(IClaimIssuer _trustedIssuer) external; + + /** + * @dev Updates the set of claim topics that a trusted issuer is allowed to emit. + * Requires that this ClaimIssuer contract already exists in the registry + * Requires that the provided claimTopics set is not empty + * Requires that there is no more than 15 claimTopics + * @param _trustedIssuer the claim issuer to update. + * @param _claimTopics the set of claim topics that the trusted issuer is allowed to emit + * This function can only be called by the owner of the Trusted Issuers Registry contract + * emits a `ClaimTopicsUpdated` event + */ + function updateIssuerClaimTopics(IClaimIssuer _trustedIssuer, uint256[] calldata _claimTopics) external; + + /// Getters + + /** + * @dev Function for getting all the trusted claim issuers stored. + * @return array of all claim issuers registered. + */ + function getTrustedIssuers() external view returns (IClaimIssuer[] memory); + + /** + * @dev Function for getting all the trusted issuer allowed for a given claim topic. + * @param claimTopic the claim topic to get the trusted issuers for. + * @return array of all claim issuer addresses that are allowed for the given claim topic. + */ + function getTrustedIssuersForClaimTopic(uint256 claimTopic) external view returns (IClaimIssuer[] memory); + + /** + * @dev Checks if the ClaimIssuer contract is trusted + * @param _issuer the address of the ClaimIssuer contract + * @return true if the issuer is trusted, false otherwise. + */ + function isTrustedIssuer(address _issuer) external view returns (bool); + + /** + * @dev Function for getting all the claim topic of trusted claim issuer + * Requires the provided ClaimIssuer contract to be registered in the trusted issuers registry. + * @param _trustedIssuer the trusted issuer concerned. + * @return The set of claim topics that the trusted issuer is allowed to emit + */ + function getTrustedIssuerClaimTopics(IClaimIssuer _trustedIssuer) external view returns (uint256[] memory); + + /** + * @dev Function for checking if the trusted claim issuer is allowed + * to emit a certain claim topic + * @param _issuer the address of the trusted issuer's ClaimIssuer contract + * @param _claimTopic the Claim Topic that has to be checked to know if the `issuer` is allowed to emit it + * @return true if the issuer is trusted for this claim topic. + */ + function hasClaimTopic(address _issuer, uint256 _claimTopic) external view returns (bool); +} diff --git a/contracts/compliance/modular/IModularCompliance.sol b/contracts/compliance/modular/IModularCompliance.sol index 53b79e28..40a1ed99 100644 --- a/contracts/compliance/modular/IModularCompliance.sol +++ b/contracts/compliance/modular/IModularCompliance.sol @@ -62,6 +62,8 @@ pragma solidity 0.8.26; +import "../../ERC-3643/IERC3643Compliance.sol"; + /// events /// @dev Event emitted for each executed interaction with a module contract. @@ -72,15 +74,6 @@ pragma solidity 0.8.26; event ModuleInteraction(address indexed _target, bytes4 _selector); -/// @dev This event is emitted when a token has been bound to the compliance contract. -/// @param _token is the address of the token to bind. -event TokenBound(address _token); - -/// @dev This event is emitted when a token has been unbound from the compliance contract. -/// @param _token is the address of the token to unbind. -event TokenUnbound(address _token); - - /// @dev This event is emitted when a module has been added to the list of modules bound to the compliance contract. /// @param _module The address of the compliance module. event ModuleAdded(address indexed _module); @@ -91,26 +84,10 @@ event ModuleAdded(address indexed _module); event ModuleRemoved(address indexed _module); -interface IModularCompliance { +interface IModularCompliance is IERC3643Compliance { /// functions - /** - * @dev binds a token to the compliance contract - * @param _token address of the token to bind - * This function can be called ONLY by the owner of the compliance contract - * Emits a TokenBound event - */ - function bindToken(address _token) external; - - /** - * @dev unbinds a token from the compliance contract - * @param _token address of the token to unbind - * This function can be called ONLY by the owner of the compliance contract - * Emits a TokenUnbound event - */ - function unbindToken(address _token) external; - /** * @dev adds a module to the list of compliance modules * @param _module address of the module to add @@ -172,81 +149,12 @@ interface IModularCompliance { */ function addAndSetModule(address _module, bytes[] calldata _interactions) external; - /** - * @dev function called whenever tokens are transferred - * from one wallet to another - * this function can update state variables in the modules bound to the compliance - * these state variables being used by the module checks to decide if a transfer - * is compliant or not depending on the values stored in these state variables and on - * the parameters of the modules - * This function can be called ONLY by the token contract bound to the compliance - * @param _from The address of the sender - * @param _to The address of the receiver - * @param _amount The amount of tokens involved in the transfer - * This function calls moduleTransferAction() on each module bound to the compliance contract - */ - function transferred( - address _from, - address _to, - uint256 _amount - ) external; - - /** - * @dev function called whenever tokens are created on a wallet - * this function can update state variables in the modules bound to the compliance - * these state variables being used by the module checks to decide if a transfer - * is compliant or not depending on the values stored in these state variables and on - * the parameters of the modules - * This function can be called ONLY by the token contract bound to the compliance - * @param _to The address of the receiver - * @param _amount The amount of tokens involved in the minting - * This function calls moduleMintAction() on each module bound to the compliance contract - */ - function created(address _to, uint256 _amount) external; - - /** - * @dev function called whenever tokens are destroyed from a wallet - * this function can update state variables in the modules bound to the compliance - * these state variables being used by the module checks to decide if a transfer - * is compliant or not depending on the values stored in these state variables and on - * the parameters of the modules - * This function can be called ONLY by the token contract bound to the compliance - * @param _from The address on which tokens are burnt - * @param _amount The amount of tokens involved in the burn - * This function calls moduleBurnAction() on each module bound to the compliance contract - */ - function destroyed(address _from, uint256 _amount) external; - - /** - * @dev checks that the transfer is compliant. - * default compliance always returns true - * READ ONLY FUNCTION, this function cannot be used to increment - * counters, emit events, ... - * @param _from The address of the sender - * @param _to The address of the receiver - * @param _amount The amount of tokens involved in the transfer - * This function will call moduleCheck() on every module bound to the compliance - * If each of the module checks return TRUE, this function will return TRUE as well - * returns FALSE otherwise - */ - function canTransfer( - address _from, - address _to, - uint256 _amount - ) external view returns (bool); - /** * @dev getter for the modules bound to the compliance contract * returns address array of module contracts bound to the compliance */ function getModules() external view returns (address[] memory); - /** - * @dev getter for the address of the token bound - * returns the address of the token - */ - function getTokenBound() external view returns (address); - /** * @dev checks if a module is bound to the compliance contract * returns true if module is bound, false otherwise diff --git a/contracts/compliance/modular/ModularCompliance.sol b/contracts/compliance/modular/ModularCompliance.sol index 67310fc8..d2ecf752 100644 --- a/contracts/compliance/modular/ModularCompliance.sol +++ b/contracts/compliance/modular/ModularCompliance.sol @@ -109,7 +109,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage, } /** - * @dev See {IModularCompliance-bindToken}. + * @dev See {IERC3643Compliance-bindToken}. */ function bindToken(address _token) external override { require(owner() == msg.sender || (_tokenBound == address(0) && msg.sender == _token), OnlyOwnerOrTokenCanCall()); @@ -119,7 +119,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage, } /** - * @dev See {IModularCompliance-unbindToken}. + * @dev See {IERC3643Compliance-unbindToken}. */ function unbindToken(address _token) external override { require(owner() == msg.sender || msg.sender == _token , OnlyOwnerOrTokenCanCall()); @@ -149,7 +149,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage, } /** - * @dev See {IModularCompliance-transferred}. + * @dev See {IERC3643Compliance-transferred}. */ function transferred(address _from, address _to, uint256 _value) external onlyToken override { require( @@ -164,7 +164,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage, } /** - * @dev See {IModularCompliance-created}. + * @dev See {IERC3643Compliance-created}. */ function created(address _to, uint256 _value) external onlyToken override { require(_to != address(0), ZeroAddress()); @@ -176,7 +176,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage, } /** - * @dev See {IModularCompliance-destroyed}. + * @dev See {IERC3643Compliance-destroyed}. */ function destroyed(address _from, uint256 _value) external onlyToken override { require(_from != address(0), ZeroAddress()); @@ -213,14 +213,24 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage, } /** - * @dev See {IModularCompliance-getTokenBound}. + * @dev See {IERC3643Compliance-getTokenBound}. */ function getTokenBound() external view override returns (address) { return _tokenBound; } /** - * @dev See {IModularCompliance-canTransfer}. + * @dev See {IERC3643Compliance-getTokenBound}. + */ + function isTokenBound(address _token) external view override returns (bool) { + if(_token == _tokenBound) { + return true; + } + return false; + } + + /** + * @dev See {IERC3643Compliance-canTransfer}. */ function canTransfer(address _from, address _to, uint256 _value) external view override returns (bool) { uint256 length = _modules.length; @@ -292,6 +302,7 @@ contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage, function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { return interfaceId == type(IModularCompliance).interfaceId || + interfaceId == type(IERC3643Compliance).interfaceId || interfaceId == type(IERC173).interfaceId || interfaceId == type(IERC165).interfaceId; } diff --git a/contracts/compliance/modular/modules/TransferFeesModule.sol b/contracts/compliance/modular/modules/TransferFeesModule.sol index 672ce857..b57cbc83 100644 --- a/contracts/compliance/modular/modules/TransferFeesModule.sol +++ b/contracts/compliance/modular/modules/TransferFeesModule.sol @@ -127,7 +127,7 @@ contract TransferFeesModule is AbstractModuleUpgradeable { address tokenAddress = IModularCompliance(msg.sender).getTokenBound(); require(_rate <= 10000, FeeRateIsOutOfRange(msg.sender, _rate)); - IIdentityRegistry identityRegistry = IToken(tokenAddress).identityRegistry(); + IERC3643IdentityRegistry identityRegistry = IToken(tokenAddress).identityRegistry(); require(identityRegistry.isVerified(_collector), CollectorAddressIsNotVerified(msg.sender, _collector)); _fees[msg.sender].rate = _rate; diff --git a/contracts/proxy/authority/TREXImplementationAuthority.sol b/contracts/proxy/authority/TREXImplementationAuthority.sol index 761affe3..95a8009a 100644 --- a/contracts/proxy/authority/TREXImplementationAuthority.sol +++ b/contracts/proxy/authority/TREXImplementationAuthority.sol @@ -197,9 +197,9 @@ contract TREXImplementationAuthority is ITREXImplementationAuthority, Ownable, I address _ir = address(IToken(_token).identityRegistry()); address _mc = address(IToken(_token).compliance()); - address _irs = address(IIdentityRegistry(_ir).identityStorage()); - address _ctr = address(IIdentityRegistry(_ir).topicsRegistry()); - address _tir = address(IIdentityRegistry(_ir).issuersRegistry()); + address _irs = address(IERC3643IdentityRegistry(_ir).identityStorage()); + address _ctr = address(IERC3643IdentityRegistry(_ir).topicsRegistry()); + address _tir = address(IERC3643IdentityRegistry(_ir).issuersRegistry()); // calling this function requires ownership of ALL contracts of the T-REX suite require( diff --git a/contracts/registry/implementation/ClaimTopicsRegistry.sol b/contracts/registry/implementation/ClaimTopicsRegistry.sol index 638d5c4d..a9129cda 100644 --- a/contracts/registry/implementation/ClaimTopicsRegistry.sol +++ b/contracts/registry/implementation/ClaimTopicsRegistry.sol @@ -124,7 +124,7 @@ contract ClaimTopicsRegistry is IClaimTopicsRegistry, OwnableUpgradeable, CTRSto */ function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { return - interfaceId == type(IClaimTopicsRegistry).interfaceId || + interfaceId == type(IERC3643ClaimTopicsRegistry).interfaceId || interfaceId == type(IERC173).interfaceId || interfaceId == type(IERC165).interfaceId; } diff --git a/contracts/registry/implementation/IdentityRegistry.sol b/contracts/registry/implementation/IdentityRegistry.sol index 052e3a78..9193ee13 100644 --- a/contracts/registry/implementation/IdentityRegistry.sol +++ b/contracts/registry/implementation/IdentityRegistry.sol @@ -261,21 +261,21 @@ contract IdentityRegistry is IIdentityRegistry, AgentRoleUpgradeable, IRStorage, /** * @dev See {IIdentityRegistry-issuersRegistry}. */ - function issuersRegistry() external view override returns (ITrustedIssuersRegistry) { + function issuersRegistry() external view override returns (IERC3643TrustedIssuersRegistry) { return _tokenIssuersRegistry; } /** * @dev See {IIdentityRegistry-topicsRegistry}. */ - function topicsRegistry() external view override returns (IClaimTopicsRegistry) { + function topicsRegistry() external view override returns (IERC3643ClaimTopicsRegistry) { return _tokenTopicsRegistry; } /** * @dev See {IIdentityRegistry-identityStorage}. */ - function identityStorage() external view override returns (IIdentityRegistryStorage) { + function identityStorage() external view override returns (IERC3643IdentityRegistryStorage) { return _tokenIdentityStorage; } @@ -314,6 +314,7 @@ contract IdentityRegistry is IIdentityRegistry, AgentRoleUpgradeable, IRStorage, function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { return interfaceId == type(IIdentityRegistry).interfaceId || + interfaceId == type(IERC3643IdentityRegistry).interfaceId || interfaceId == type(IERC173).interfaceId || interfaceId == type(IERC165).interfaceId; } diff --git a/contracts/registry/implementation/IdentityRegistryStorage.sol b/contracts/registry/implementation/IdentityRegistryStorage.sol index b2cb19ab..2291a1e4 100644 --- a/contracts/registry/implementation/IdentityRegistryStorage.sol +++ b/contracts/registry/implementation/IdentityRegistryStorage.sol @@ -201,7 +201,7 @@ contract IdentityRegistryStorage is IIdentityRegistryStorage, AgentRoleUpgradeab */ function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { return - interfaceId == type(IIdentityRegistryStorage).interfaceId || + interfaceId == type(IERC3643IdentityRegistryStorage).interfaceId || interfaceId == type(IERC173).interfaceId || interfaceId == type(IERC165).interfaceId; } diff --git a/contracts/registry/implementation/TrustedIssuersRegistry.sol b/contracts/registry/implementation/TrustedIssuersRegistry.sol index 559f0a54..acc6d50c 100644 --- a/contracts/registry/implementation/TrustedIssuersRegistry.sol +++ b/contracts/registry/implementation/TrustedIssuersRegistry.sol @@ -234,7 +234,7 @@ contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, */ function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { return - interfaceId == type(ITrustedIssuersRegistry).interfaceId || + interfaceId == type(IERC3643TrustedIssuersRegistry).interfaceId || interfaceId == type(IERC173).interfaceId || interfaceId == type(IERC165).interfaceId; } diff --git a/contracts/registry/interface/IClaimTopicsRegistry.sol b/contracts/registry/interface/IClaimTopicsRegistry.sol index d117e451..b83c29bf 100644 --- a/contracts/registry/interface/IClaimTopicsRegistry.sol +++ b/contracts/registry/interface/IClaimTopicsRegistry.sol @@ -62,39 +62,11 @@ pragma solidity 0.8.26; -/// Events +import "../../ERC-3643/IERC3643ClaimTopicsRegistry.sol"; -/// @dev This event is emitted when a claim topic has been added to the ClaimTopicsRegistry. -/// @param _claimTopic is the required claim added to the Claim Topics Registry. -event ClaimTopicAdded(uint256 indexed _claimTopic); +// solhint-disable-next-line no-empty-blocks +interface IClaimTopicsRegistry is IERC3643ClaimTopicsRegistry { -/// @dev This event is emitted when a claim topic has been removed from the ClaimTopicsRegistry. -/// @param _claimTopic is the required claim removed from the Claim Topics Registry. -event ClaimTopicRemoved(uint256 indexed _claimTopic); +// functions that are not part of the original standard can be added here in future versions - -interface IClaimTopicsRegistry { - - /** - * @dev Add a trusted claim topic (For example: KYC=1, AML=2). - * Only owner can call. - * emits `ClaimTopicAdded` event - * cannot add more than 15 topics for 1 token as adding more could create gas issues - * @param _claimTopic The claim topic index - */ - function addClaimTopic(uint256 _claimTopic) external; - - /** - * @dev Remove a trusted claim topic (For example: KYC=1, AML=2). - * Only owner can call. - * emits `ClaimTopicRemoved` event - * @param _claimTopic The claim topic index - */ - function removeClaimTopic(uint256 _claimTopic) external; - - /** - * @dev Get the trusted claim topics for the security token - * @return Array of trusted claim topics - */ - function getClaimTopics() external view returns (uint256[] memory); } diff --git a/contracts/registry/interface/IIdentityRegistry.sol b/contracts/registry/interface/IIdentityRegistry.sol index 7639687f..26469b19 100644 --- a/contracts/registry/interface/IIdentityRegistry.sol +++ b/contracts/registry/interface/IIdentityRegistry.sol @@ -62,47 +62,10 @@ pragma solidity 0.8.26; -import "./ITrustedIssuersRegistry.sol"; -import "./IClaimTopicsRegistry.sol"; -import "./IIdentityRegistryStorage.sol"; - -import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; -import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; +import "../../ERC-3643/IERC3643IdentityRegistry.sol"; /// Events -/// @dev This event is emitted when the ClaimTopicsRegistry has been set for the IdentityRegistry. -/// @param _claimTopicsRegistry is the address of the Claim Topics Registry contract. -event ClaimTopicsRegistrySet(address indexed _claimTopicsRegistry); - -/// @dev This event is emitted when the IdentityRegistryStorage has been set for the IdentityRegistry. -/// @param _identityStorage is the address of the Identity Registry Storage contract. -event IdentityStorageSet(address indexed _identityStorage); - -/// @dev This event is emitted when the TrustedIssuersRegistry has been set for the IdentityRegistry. -/// @param _trustedIssuersRegistry is the address of the Trusted Issuers Registry contract. -event TrustedIssuersRegistrySet(address indexed _trustedIssuersRegistry); - -/// @dev This event is emitted when an Identity is registered into the Identity Registry. -/// @param _investorAddress is the address of the investor's wallet. -/// @param _identity is the address of the Identity smart contract (onchainID). -event IdentityRegistered(address indexed _investorAddress, IIdentity indexed _identity); - -/// @dev This event is emitted when an Identity is removed from the Identity Registry. -/// @param _investorAddress is the address of the investor's wallet. -/// @param _identity is the address of the Identity smart contract (onchainID). -event IdentityRemoved(address indexed _investorAddress, IIdentity indexed _identity); - -/// @dev This event is emitted when an Identity has been updated. -/// @param _oldIdentity is the old Identity contract's address to update. -/// @param _newIdentity is the new Identity contract's. -event IdentityUpdated(IIdentity indexed _oldIdentity, IIdentity indexed _newIdentity); - -/// @dev This event is emitted when an Identity's country has been updated. -/// @param _investorAddress is the address on which the country has been updated -/// @param _country is the numeric code (ISO 3166-1) of the new country -event CountryUpdated(address indexed _investorAddress, uint16 indexed _country); - /// @dev This event is emitted when Eligibility checks are disabled. event EligibilityChecksDisabled(); @@ -110,93 +73,7 @@ event EligibilityChecksDisabled(); event EligibilityChecksEnabled(); -interface IIdentityRegistry { - - /** - * @dev Register an identity contract corresponding to a user address. - * Requires that the user doesn't have an identity contract already registered. - * This function can only be called by a wallet set as agent of the smart contract - * @param _userAddress The address of the user - * @param _identity The address of the user's identity contract - * @param _country The country of the investor - * emits `IdentityRegistered` event - */ - function registerIdentity( - address _userAddress, - IIdentity _identity, - uint16 _country - ) external; - - /** - * @dev Removes an user from the identity registry. - * Requires that the user have an identity contract already deployed that will be deleted. - * This function can only be called by a wallet set as agent of the smart contract - * @param _userAddress The address of the user to be removed - * emits `IdentityRemoved` event - */ - function deleteIdentity(address _userAddress) external; - - /** - * @dev Replace the actual identityRegistryStorage contract with a new one. - * This function can only be called by the wallet set as owner of the smart contract - * @param _identityRegistryStorage The address of the new Identity Registry Storage - * emits `IdentityStorageSet` event - */ - function setIdentityRegistryStorage(address _identityRegistryStorage) external; - - /** - * @dev Replace the actual claimTopicsRegistry contract with a new one. - * This function can only be called by the wallet set as owner of the smart contract - * @param _claimTopicsRegistry The address of the new claim Topics Registry - * emits `ClaimTopicsRegistrySet` event - */ - function setClaimTopicsRegistry(address _claimTopicsRegistry) external; - - /** - * @dev Replace the actual trustedIssuersRegistry contract with a new one. - * This function can only be called by the wallet set as owner of the smart contract - * @param _trustedIssuersRegistry The address of the new Trusted Issuers Registry - * emits `TrustedIssuersRegistrySet` event - */ - function setTrustedIssuersRegistry(address _trustedIssuersRegistry) external; - - /** - * @dev Updates the country corresponding to a user address. - * Requires that the user should have an identity contract already deployed that will be replaced. - * This function can only be called by a wallet set as agent of the smart contract - * @param _userAddress The address of the user - * @param _country The new country of the user - * emits `CountryUpdated` event - */ - function updateCountry(address _userAddress, uint16 _country) external; - - /** - * @dev Updates an identity contract corresponding to a user address. - * Requires that the user address should be the owner of the identity contract. - * Requires that the user should have an identity contract already deployed that will be replaced. - * This function can only be called by a wallet set as agent of the smart contract - * @param _userAddress The address of the user - * @param _identity The address of the user's new identity contract - * emits `IdentityUpdated` event - */ - function updateIdentity(address _userAddress, IIdentity _identity) external; - - /** - * @dev function allowing to register identities in batch - * This function can only be called by a wallet set as agent of the smart contract - * Requires that none of the users has an identity contract already registered. - * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH, - * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION - * @param _userAddresses The addresses of the users - * @param _identities The addresses of the corresponding identity contracts - * @param _countries The countries of the corresponding investors - * emits _userAddresses.length `IdentityRegistered` events - */ - function batchRegisterIdentity( - address[] calldata _userAddresses, - IIdentity[] calldata _identities, - uint16[] calldata _countries - ) external; +interface IIdentityRegistry is IERC3643IdentityRegistry { /** * @dev Disables the eligibility checks for token transfers and other operations. @@ -230,48 +107,4 @@ interface IIdentityRegistry { * Emits an `EligibilityChecksEnabled` event upon successful execution. */ function enableEligibilityChecks() external; - - /** - * @dev This functions checks whether a wallet has its Identity registered or not - * in the Identity Registry. - * @param _userAddress The address of the user to be checked. - * @return 'True' if the address is contained in the Identity Registry, 'false' if not. - */ - function contains(address _userAddress) external view returns (bool); - - /** - * @dev This functions checks whether an identity contract - * corresponding to the provided user address has the required claims or not based - * on the data fetched from trusted issuers registry and from the claim topics registry - * @param _userAddress The address of the user to be verified. - * @return 'True' if the address is verified, 'false' if not. - */ - function isVerified(address _userAddress) external view returns (bool); - - /** - * @dev Returns the onchainID of an investor. - * @param _userAddress The wallet of the investor - */ - function identity(address _userAddress) external view returns (IIdentity); - - /** - * @dev Returns the country code of an investor. - * @param _userAddress The wallet of the investor - */ - function investorCountry(address _userAddress) external view returns (uint16); - - /** - * @dev Returns the IdentityRegistryStorage linked to the current IdentityRegistry. - */ - function identityStorage() external view returns (IIdentityRegistryStorage); - - /** - * @dev Returns the TrustedIssuersRegistry linked to the current IdentityRegistry. - */ - function issuersRegistry() external view returns (ITrustedIssuersRegistry); - - /** - * @dev Returns the ClaimTopicsRegistry linked to the current IdentityRegistry. - */ - function topicsRegistry() external view returns (IClaimTopicsRegistry); } diff --git a/contracts/registry/interface/IIdentityRegistryStorage.sol b/contracts/registry/interface/IIdentityRegistryStorage.sol index e394a040..318fdf10 100644 --- a/contracts/registry/interface/IIdentityRegistryStorage.sol +++ b/contracts/registry/interface/IIdentityRegistryStorage.sol @@ -62,120 +62,11 @@ pragma solidity 0.8.26; -import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; +import "../../ERC-3643/IERC3643IdentityRegistryStorage.sol"; +// solhint-disable-next-line no-empty-blocks +interface IIdentityRegistryStorage is IERC3643IdentityRegistryStorage { -/// events +// functions that are not part of the original standard can be added here in future versions -/// @dev This event is emitted when an Identity is registered into the storage contract. -/// @param _investorAddress` is the address of the investor's wallet. -/// @param _identity` is the address of the Identity smart contract (onchainID). -event IdentityStored(address indexed _investorAddress, IIdentity indexed _identity); - -/// @dev This event is emitted when an Identity is removed from the storage contract. -/// @param _investorAddress is the address of the investor's wallet. -/// @param _identity is the address of the Identity smart contract (onchainID). -event IdentityUnstored(address indexed _investorAddress, IIdentity indexed _identity); - -/// @dev This event is emitted when an Identity has been updated. -/// @param _oldIdentity is the old Identity contract's address to update. -/// @param _newIdentity is the new Identity contract's. -event IdentityModified(IIdentity indexed _oldIdentity, IIdentity indexed _newIdentity); - -/// @dev This event is emitted when an Identity's country has been updated. -/// @param _investorAddress is the address on which the country has been updated. -/// @param _country is the numeric code (ISO 3166-1) of the new country. -event CountryModified(address indexed _investorAddress, uint16 indexed _country); - -/// @dev This event is emitted when an Identity Registry is bound to the storage contract. -/// @param _identityRegistry is the address of the identity registry added. -event IdentityRegistryBound(address indexed _identityRegistry); - -/// @dev This event is emitted when an Identity Registry is unbound from the storage contract. -/// @param _identityRegistry is the address of the identity registry removed. -event IdentityRegistryUnbound(address indexed _identityRegistry); - - -interface IIdentityRegistryStorage { - - /// functions - - /** - * @dev adds an identity contract corresponding to a user address in the storage. - * Requires that the user doesn't have an identity contract already registered. - * This function can only be called by an address set as agent of the smart contract - * @param _userAddress The address of the user - * @param _identity The address of the user's identity contract - * @param _country The country of the investor - * emits `IdentityStored` event - */ - function addIdentityToStorage( - address _userAddress, - IIdentity _identity, - uint16 _country - ) external; - - /** - * @dev Removes an user from the storage. - * Requires that the user have an identity contract already deployed that will be deleted. - * This function can only be called by an address set as agent of the smart contract - * @param _userAddress The address of the user to be removed - * emits `IdentityUnstored` event - */ - function removeIdentityFromStorage(address _userAddress) external; - - /** - * @dev Updates the country corresponding to a user address. - * Requires that the user should have an identity contract already deployed that will be replaced. - * This function can only be called by an address set as agent of the smart contract - * @param _userAddress The address of the user - * @param _country The new country of the user - * emits `CountryModified` event - */ - function modifyStoredInvestorCountry(address _userAddress, uint16 _country) external; - - /** - * @dev Updates an identity contract corresponding to a user address. - * Requires that the user address should be the owner of the identity contract. - * Requires that the user should have an identity contract already deployed that will be replaced. - * This function can only be called by an address set as agent of the smart contract - * @param _userAddress The address of the user - * @param _identity The address of the user's new identity contract - * emits `IdentityModified` event - */ - function modifyStoredIdentity(address _userAddress, IIdentity _identity) external; - - /** - * @notice Adds an identity registry as agent of the Identity Registry Storage Contract. - * This function can only be called by the wallet set as owner of the smart contract - * This function adds the identity registry to the list of identityRegistries linked to the storage contract - * cannot bind more than 300 IR to 1 IRS - * @param _identityRegistry The identity registry address to add. - */ - function bindIdentityRegistry(address _identityRegistry) external; - - /** - * @notice Removes an identity registry from being agent of the Identity Registry Storage Contract. - * This function can only be called by the wallet set as owner of the smart contract - * This function removes the identity registry from the list of identityRegistries linked to the storage contract - * @param _identityRegistry The identity registry address to remove. - */ - function unbindIdentityRegistry(address _identityRegistry) external; - - /** - * @dev Returns the identity registries linked to the storage contract - */ - function linkedIdentityRegistries() external view returns (address[] memory); - - /** - * @dev Returns the onchainID of an investor. - * @param _userAddress The wallet of the investor - */ - function storedIdentity(address _userAddress) external view returns (IIdentity); - - /** - * @dev Returns the country code of an investor. - * @param _userAddress The wallet of the investor - */ - function storedInvestorCountry(address _userAddress) external view returns (uint16); } diff --git a/contracts/registry/interface/ITrustedIssuersRegistry.sol b/contracts/registry/interface/ITrustedIssuersRegistry.sol index 91fdabaa..b5cc75a7 100644 --- a/contracts/registry/interface/ITrustedIssuersRegistry.sol +++ b/contracts/registry/interface/ITrustedIssuersRegistry.sol @@ -62,96 +62,11 @@ */ pragma solidity 0.8.26; +import "../../ERC-3643/IERC3643TrustedIssuersRegistry.sol"; -import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; +// solhint-disable-next-line no-empty-blocks +interface ITrustedIssuersRegistry is IERC3643TrustedIssuersRegistry { -/// Events +// functions that are not part of the original standard can be added here in future versions -/// @dev This event is emitted when a trusted issuer is added in the registry. -/// @param _trustedIssuer is the address of the trusted issuer's ClaimIssuer contract. -/// @param _claimTopics is the set of claims that the trusted issuer is allowed to emit. -event TrustedIssuerAdded(IClaimIssuer indexed _trustedIssuer, uint256[] _claimTopics); - -/// @dev This event is emitted when a trusted issuer is removed from the registry. -/// @param _trustedIssuer is the address of the trusted issuer's ClaimIssuer contract. -event TrustedIssuerRemoved(IClaimIssuer indexed _trustedIssuer); - -/// &dev This event is emitted when the set of claim topics is changed for a given trusted issuer. -/// @param _trustedIssuer is the address of the trusted issuer's ClaimIssuer contract -/// @param _claimTopics is the set of claims that the trusted issuer is allowed to emit. -event ClaimTopicsUpdated(IClaimIssuer indexed _trustedIssuer, uint256[] _claimTopics); - - -interface ITrustedIssuersRegistry { - - /** - * @dev registers a ClaimIssuer contract as trusted claim issuer. - * Requires that a ClaimIssuer contract doesn't already exist - * Requires that the claimTopics set is not empty - * Requires that there is no more than 15 claimTopics - * Requires that there is no more than 50 Trusted issuers - * @param _trustedIssuer The ClaimIssuer contract address of the trusted claim issuer. - * @param _claimTopics the set of claim topics that the trusted issuer is allowed to emit - * This function can only be called by the owner of the Trusted Issuers Registry contract - * emits a `TrustedIssuerAdded` event - */ - function addTrustedIssuer(IClaimIssuer _trustedIssuer, uint256[] calldata _claimTopics) external; - - /** - * @dev Removes the ClaimIssuer contract of a trusted claim issuer. - * Requires that the claim issuer contract to be registered first - * @param _trustedIssuer the claim issuer to remove. - * This function can only be called by the owner of the Trusted Issuers Registry contract - * emits a `TrustedIssuerRemoved` event - */ - function removeTrustedIssuer(IClaimIssuer _trustedIssuer) external; - - /** - * @dev Updates the set of claim topics that a trusted issuer is allowed to emit. - * Requires that this ClaimIssuer contract already exists in the registry - * Requires that the provided claimTopics set is not empty - * Requires that there is no more than 15 claimTopics - * @param _trustedIssuer the claim issuer to update. - * @param _claimTopics the set of claim topics that the trusted issuer is allowed to emit - * This function can only be called by the owner of the Trusted Issuers Registry contract - * emits a `ClaimTopicsUpdated` event - */ - function updateIssuerClaimTopics(IClaimIssuer _trustedIssuer, uint256[] calldata _claimTopics) external; - - /** - * @dev Function for getting all the trusted claim issuers stored. - * @return array of all claim issuers registered. - */ - function getTrustedIssuers() external view returns (IClaimIssuer[] memory); - - /** - * @dev Function for getting all the trusted issuer allowed for a given claim topic. - * @param claimTopic the claim topic to get the trusted issuers for. - * @return array of all claim issuer addresses that are allowed for the given claim topic. - */ - function getTrustedIssuersForClaimTopic(uint256 claimTopic) external view returns (IClaimIssuer[] memory); - - /** - * @dev Checks if the ClaimIssuer contract is trusted - * @param _issuer the address of the ClaimIssuer contract - * @return true if the issuer is trusted, false otherwise. - */ - function isTrustedIssuer(address _issuer) external view returns (bool); - - /** - * @dev Function for getting all the claim topic of trusted claim issuer - * Requires the provided ClaimIssuer contract to be registered in the trusted issuers registry. - * @param _trustedIssuer the trusted issuer concerned. - * @return The set of claim topics that the trusted issuer is allowed to emit - */ - function getTrustedIssuerClaimTopics(IClaimIssuer _trustedIssuer) external view returns (uint256[] memory); - - /** - * @dev Function for checking if the trusted claim issuer is allowed - * to emit a certain claim topic - * @param _issuer the address of the trusted issuer's ClaimIssuer contract - * @param _claimTopic the Claim Topic that has to be checked to know if the `issuer` is allowed to emit it - * @return true if the issuer is trusted for this claim topic. - */ - function hasClaimTopic(address _issuer, uint256 _claimTopic) external view returns (bool); } diff --git a/contracts/token/IToken.sol b/contracts/token/IToken.sol index fe34e2d0..487f9c07 100644 --- a/contracts/token/IToken.sol +++ b/contracts/token/IToken.sol @@ -63,61 +63,8 @@ pragma solidity 0.8.26; -import "../registry/interface/IIdentityRegistry.sol"; -import "../compliance/modular/IModularCompliance.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./TokenStructs.sol"; - -/// events - -/// @dev This event is emitted when the token information is updated. -/// @param _newName is the name of the token. -/// @param _newSymbol is the symbol of the token. -/// @param _newDecimals is the decimals of the token. -/// @param _newVersion is the version of the token. -/// @param _newOnchainID is the address of the onchainID of the token. -event UpdatedTokenInformation(string indexed _newName, string indexed _newSymbol, uint8 _newDecimals, - string _newVersion, address indexed _newOnchainID); - -/// @dev This event is emitted when the IdentityRegistry has been set for the token. -/// @param _identityRegistry is the address of the Identity Registry of the token. -event IdentityRegistryAdded(address indexed _identityRegistry); - -/// @dev This event is emitted when the Compliance has been set for the token. -/// @param _compliance is the address of the Compliance contract of the token. -event ComplianceAdded(address indexed _compliance); - -/// @dev This event is emitted when an investor successfully recovers his tokens. -/// @param _lostWallet is the address of the wallet that the investor lost access to. -/// @param _newWallet is the address of the wallet that the investor provided for the recovery. -/// @param _investorOnchainID is the address of the onchainID of the investor who asked for a recovery. -event RecoverySuccess(address indexed _lostWallet, address indexed _newWallet, address indexed _investorOnchainID); - -/// @dev This event is emitted when the wallet of an investor is frozen or unfrozen. -/// @param _userAddress is the wallet of the investor that is concerned by the freezing status. -/// @param _isFrozen is the freezing status of the wallet. -/// @param _isFrozen equals `true` the wallet is frozen after emission of the event. -/// @param _isFrozen equals `false` the wallet is unfrozen after emission of the event. -/// @param _owner is the address of the agent who called the function to freeze the wallet. -event AddressFrozen(address indexed _userAddress, bool indexed _isFrozen, address indexed _owner); - -/// @dev This event is emitted when a certain amount of tokens is frozen on a wallet. -/// @param _userAddress is the wallet of the investor that is concerned by the freezing status. -/// @param _amount is the amount of tokens that are frozen. -event TokensFrozen(address indexed _userAddress, uint256 _amount); - -/// @dev This event is emitted when a certain amount of tokens is unfrozen on a wallet. -/// @param _userAddress is the wallet of the investor that is concerned by the freezing status. -/// @param _amount is the amount of tokens that are unfrozen. -event TokensUnfrozen(address indexed _userAddress, uint256 _amount); - -/// @dev This event is emitted when the token is paused. -/// @param _userAddress is the address of the wallet that called the pause function -event Paused(address _userAddress); - -/// @dev This event is emitted when the token is unpaused. -/// @param _userAddress is the address of the wallet that called the unpause function. -event Unpaused(address _userAddress); +import "../ERC-3643/IERC3643.sol"; /// @dev This event is emitted when restrictions on an agent's roles are updated. /// @param _agent is the address of the agent whose roles are being restricted. @@ -152,220 +99,10 @@ event DefaultAllowanceDisabled(address _user); event DefaultAllowanceEnabled(address _user); /// @dev interface -interface IToken is IERC20 { +interface IToken is IERC3643 { /// functions - /** - * @dev sets the token name - * @param _name the name of token to set - * Only the owner of the token smart contract can call this function - * emits a `UpdatedTokenInformation` event - */ - function setName(string calldata _name) external; - - /** - * @dev sets the token symbol - * @param _symbol the token symbol to set - * Only the owner of the token smart contract can call this function - * emits a `UpdatedTokenInformation` event - */ - function setSymbol(string calldata _symbol) external; - - /** - * @dev sets the onchain ID of the token - * @param _onchainID the address of the onchain ID to set - * Only the owner of the token smart contract can call this function - * emits a `UpdatedTokenInformation` event - */ - function setOnchainID(address _onchainID) external; - - /** - * @dev Pauses the token contract. When the contract is paused, investors cannot transfer tokens anymore. - * This function can only be called by an agent of the token, provided the agent is not restricted from pausing the token. - * emits a `Paused` event upon successful execution. - * To pause token transfers, the calling agent must have pausing capabilities enabled. - * If the agent is disabled from pausing, the function call will fail. - * The function can be called only when the contract is not already paused. - * error AgentNotAuthorized - Thrown if the agent is disabled from pausing the token, - * indicating they do not have the necessary permissions to execute this function. - */ - function pause() external; - - /** - * @dev Unpauses the token contract, allowing investors to resume token transfers under normal conditions - * This function can only be called by an agent of the token, provided the agent is not restricted from pausing the token. - * emits an `Unpaused` event upon successful execution. - * To unpause token transfers, the calling agent must have pausing capabilities enabled. - * If the agent is disabled from pausing, the function call will fail. - * The function can be called only when the contract is currently paused. - * error AgentNotAuthorized - Thrown if the agent is disabled from pausing the token, - * indicating they do not have the necessary permissions to execute this function. - */ - function unpause() external; - - /** - * @dev Sets an address's frozen status for this token, - * either freezing or unfreezing the address based on the provided boolean value. - * This function can be called by an agent of the token, assuming the agent is not restricted from freezing addresses. - * emits an `AddressFrozen` event upon successful execution. - * @param _userAddress The address for which to update the frozen status. - * @param _freeze The frozen status to be applied: `true` to freeze, `false` to unfreeze. - * @notice To change an address's frozen status, the calling agent must have the capability to freeze addresses enabled. - * If the agent is disabled from freezing addresses, the function call will fail. - * error AgentNotAuthorized - Thrown if the agent is disabled from freezing addresses, - * indicating they do not have the necessary permissions to execute this function. - */ - function setAddressFrozen(address _userAddress, bool _freeze) external; - - /** - * @dev Freezes a specified token amount for a given address, preventing those tokens from being transferred. - * This function can be called by an agent of the token, provided the agent is not restricted from freezing tokens. - * emits a `TokensFrozen` event upon successful execution. - * @param _userAddress The address for which to freeze tokens. - * @param _amount The amount of tokens to be frozen. - * @notice To freeze tokens for an address, the calling agent must have the capability to freeze tokens enabled. - * If the agent is disabled from freezing tokens, the function call will fail. - * error AgentNotAuthorized - Thrown if the agent is disabled from freezing tokens, - * indicating they do not have the necessary permissions to execute this function. - */ - function freezePartialTokens(address _userAddress, uint256 _amount) external; - - /** - * @dev Unfreezes a specified token amount for a given address, allowing those tokens to be transferred again. - * This function can be called by an agent of the token, assuming the agent is not restricted from unfreezing tokens. - * emits a `TokensUnfrozen` event upon successful execution. - * @param _userAddress The address for which to unfreeze tokens. - * @param _amount The amount of tokens to be unfrozen. - * @notice To unfreeze tokens for an address, the calling agent must have the capability to unfreeze tokens enabled. - * If the agent is disabled from unfreezing tokens, the function call will fail. - * error AgentNotAuthorized - Thrown if the agent is disabled from unfreezing tokens, - * indicating they do not have the necessary permissions to execute this function. - */ - function unfreezePartialTokens(address _userAddress, uint256 _amount) external; - - /** - * @dev sets the Identity Registry for the token - * @param _identityRegistry the address of the Identity Registry to set - * Only the owner of the token smart contract can call this function - * emits an `IdentityRegistryAdded` event - */ - function setIdentityRegistry(address _identityRegistry) external; - - /** - * @dev sets the compliance contract of the token - * @param _compliance the address of the compliance contract to set - * Only the owner of the token smart contract can call this function - * calls bindToken on the compliance contract - * emits a `ComplianceAdded` event - */ - function setCompliance(address _compliance) external; - - /** - * @dev Initiates a forced transfer of tokens between two whitelisted wallets. - * If the `from` address does not have sufficient free tokens (unfrozen tokens) - * but possesses a total balance equal to or greater than the specified `amount`, - * the frozen token amount is reduced to ensure enough free tokens for the transfer. - * In such cases, the remaining balance in the `from` account consists entirely of frozen tokens post-transfer. - * It is imperative that the `to` address is a verified and whitelisted address. - * @param _from The address of the sender. - * @param _to The address of the receiver. - * @param _amount The number of tokens to be transferred. - * This function can only be invoked by a wallet designated as an agent of the token, - * provided the agent is not restricted from initiating forced transfers of the token. - * Emits a `TokensUnfrozen` event if `_amount` is higher than the free balance of `_from`. - * Also emits a `Transfer` event. - * To execute this function, the calling agent must not be restricted from initiating forced transfers of the token. - * If the agent is restricted from this capability, the function call will fail. - * The function can only be called when the contract is not already paused. - * error `AgentNotAuthorized` - Thrown if the agent is restricted from initiating forced transfers of the token, - * indicating they do not have the necessary permissions to execute this function. - */ - function forcedTransfer( - address _from, - address _to, - uint256 _amount - ) external returns (bool); - - /** - * @dev Mints tokens to a specified address. - * This enhanced version of the default mint method allows tokens to be minted - * to an address only if it is a verified and whitelisted address according to the security token. - * @param _to Address to mint the tokens to. - * @param _amount Amount of tokens to mint. - * This function can only be called by a wallet designated as an agent of the token, - * provided the agent is not restricted from minting tokens. - * Emits a `Transfer` event upon successful minting. - * To execute this function, the calling agent must not be restricted from minting tokens. - * If the agent is restricted from this capability, the function call will fail. - */ - function mint(address _to, uint256 _amount) external; - - /** - * @dev Burns tokens from a specified address. - * If the account address does not have sufficient free tokens (unfrozen tokens) - * but possesses a total balance equal to or greater than the specified value, - * the frozen token amount is reduced to ensure enough free tokens for the burn. - * In such cases, the remaining balance in the account consists entirely of frozen tokens post-transaction. - * @param _userAddress Address to burn the tokens from. - * @param _amount Amount of tokens to burn. - * This function can only be called by a wallet designated as an agent of the token, - * provided the agent is not restricted from burning tokens. - * Emits a `TokensUnfrozen` event if `_amount` exceeds the free balance of `_userAddress`. - * Also emits a `Transfer` event. - * To execute this function, the calling agent must not be restricted from burning tokens. - * If the agent is restricted from this capability, the function call will fail. - */ - function burn(address _userAddress, uint256 _amount) external; - - /** - * @dev Initiates a recovery process to transfer tokens and associated states - * from a lost wallet to a new wallet for an investor. - * - * This function allows an authorized agent to recover tokens from a lost wallet, - * transferring them to a new wallet while preserving the investor's - * identity and status within the token ecosystem. The function ensures that all relevant data, - * including frozen tokens and address freezing status, is accurately transferred to the new wallet. - * - * @param _lostWallet The wallet that the investor lost, containing the tokens to be recovered. - * @param _newWallet The newly provided wallet to which tokens and associated statuses must be transferred. - * @param _investorOnchainID The ONCHAINID of the investor whose tokens are being recovered. - * - * Requirements: - * - The caller must be an agent authorized to perform recovery operations, with no restrictions on this capability. - * - The `_lostWallet` must have a non-zero token balance; otherwise, the recovery is unnecessary and will revert. - * - Either the `_lostWallet` or the `_newWallet` must be present in the identity registry; - * if neither is present, the function will revert. - * - * Operations: - * - Transfers the entire token balance from `_lostWallet` to `_newWallet`. - * - Transfers any frozen tokens from `_lostWallet` to `_newWallet`, updating the frozen token count accordingly. - * - Transfers the address freeze status from `_lostWallet` to `_newWallet`, - * ensuring the new wallet retains any restrictions if applicable. - * - Updates the identity registry: - * - If `_lostWallet` is listed in the identity registry, it will be removed, - * and `_newWallet` will be registered unless already present. - * - * Emits the following events: - * - `TokensUnfrozen` if there are frozen tokens on `_lostWallet` that are transferred. - * - `TokensFrozen` if frozen tokens are added to `_newWallet`. - * - `AddressFrozen` if the freeze status of either wallet changes. - * - `Transfer` to reflect the movement of tokens from `_lostWallet` to `_newWallet`. - * - `RecoverySuccess` upon successful completion of the recovery process. - * - * Reverts if: - * - The agent calling the function does not have the necessary permissions to perform recovery (`AgentNotAuthorized`). - * - The `_lostWallet` has no tokens to recover (`NoTokenToRecover`). - * - Neither `_lostWallet` nor `_newWallet` is present in the identity registry (`RecoveryNotPossible`). - * - * @return A boolean value indicating whether the recovery process was successful. - */ - function recoveryAddress( - address _lostWallet, - address _newWallet, - address _investorOnchainID - ) external returns (bool); - /** * @dev The owner of this address can allow or disallow spending without allowance. * Any `TransferFrom` from these targets won't need allowance (allow = true) or will need allowance (allow = false). @@ -384,113 +121,6 @@ interface IToken is IERC20 { */ function enableDefaultAllowance() external; - /** - * @dev function allowing to issue transfers in batch - * Require that the msg.sender and `to` addresses are not frozen. - * Require that the total value should not exceed available balance. - * Require that the `to` addresses are all verified addresses, - * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_toList.length` IS TOO HIGH, - * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION - * @param _toList The addresses of the receivers - * @param _amounts The number of tokens to transfer to the corresponding receiver - * emits _toList.length `Transfer` events - */ - function batchTransfer(address[] calldata _toList, uint256[] calldata _amounts) external; - - /** - * @dev Initiates forced transfers in batch. - * Requires that each _amounts[i] does not exceed the available balance of _fromList[i]. - * Requires that the _toList addresses are all verified and whitelisted addresses. - * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF _fromList.length IS TOO HIGH. - * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. - * @param _fromList The addresses of the senders. - * @param _toList The addresses of the receivers. - * @param _amounts The number of tokens to transfer to the corresponding receiver. - * This function can only be called by a wallet designated as an agent of the token, - * provided the agent is not restricted from initiating forced transfers in batch. - * Emits `TokensUnfrozen` events for each `_amounts[i]` that exceeds the free balance of `_fromList[i]`. - * Also emits _fromList.length `Transfer` events upon successful batch transfer. - * To execute this function, the calling agent must not be restricted from initiating forced transfer. - * If the agent is restricted from this capability, the function call will fail. - */ - function batchForcedTransfer( - address[] calldata _fromList, - address[] calldata _toList, - uint256[] calldata _amounts - ) external; - - /** - * @dev Initiates minting of tokens in batch. - * Requires that the `_toList` addresses are all verified and whitelisted addresses. - * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_toList.length` IS TOO HIGH. - * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. - * @param _toList The addresses of the receivers. - * @param _amounts The number of tokens to mint to the corresponding receiver. - * This function can only be called by a wallet designated as an agent of the token, - * provided the agent is not restricted from minting tokens. - * Emits _toList.length `Transfer` events upon successful batch minting. - * To execute this function, the calling agent must not be restricted from minting tokens. - * If the agent is restricted from this capability, the function call will fail. - */ - function batchMint(address[] calldata _toList, uint256[] calldata _amounts) external; - - /** - * @dev Initiates burning of tokens in batch. - * Requires that the `_userAddresses` addresses are all verified and whitelisted addresses. - * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH. - * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. - * @param _userAddresses The addresses of the wallets concerned by the burn. - * @param _amounts The number of tokens to burn from the corresponding wallets. - * This function can only be called by a wallet designated as an agent of the token, - * provided the agent is not restricted from burning tokens. - * Emits _userAddresses.length `Transfer` events upon successful batch burn. - * To execute this function, the calling agent must not be restricted from burning tokens. - * If the agent is restricted from this capability, the function call will fail. - */ - function batchBurn(address[] calldata _userAddresses, uint256[] calldata _amounts) external; - - /** - * @dev Initiates setting of frozen status for addresses in batch. - * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH. - * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. - * @param _userAddresses The addresses for which to update frozen status. - * @param _freeze Frozen status of the corresponding address. - * This function can only be called by a wallet designated as an agent of the token, - * provided the agent is not restricted from setting frozen addresses. - * Emits _userAddresses.length `AddressFrozen` events upon successful batch update of frozen status. - * To execute this function, the calling agent must not be restricted from setting frozen addresses. - * If the agent is restricted from this capability, the function call will fail. - */ - function batchSetAddressFrozen(address[] calldata _userAddresses, bool[] calldata _freeze) external; - - /** - * @dev Initiates partial freezing of tokens in batch. - * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH. - * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. - * @param _userAddresses The addresses on which tokens need to be partially frozen. - * @param _amounts The amount of tokens to freeze on the corresponding address. - * This function can only be called by a wallet designated as an agent of the token, - * provided the agent is not restricted from partially freezing tokens. - * Emits _userAddresses.length `TokensFrozen` events upon successful batch partial freezing. - * To execute this function, the calling agent must not be restricted from partially freezing tokens. - * If the agent is restricted from this capability, the function call will fail. - */ - function batchFreezePartialTokens(address[] calldata _userAddresses, uint256[] calldata _amounts) external; - - /** - * @dev Initiates partial unfreezing of tokens in batch. - * IMPORTANT: THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH. - * USE WITH CARE TO AVOID "OUT OF GAS" TRANSACTIONS AND POTENTIAL LOSS OF TX FEES. - * @param _userAddresses The addresses on which tokens need to be partially unfrozen. - * @param _amounts The amount of tokens to unfreeze on the corresponding address. - * This function can only be called by a wallet designated as an agent of the token, - * provided the agent is not restricted from partially freezing tokens. - * Emits _userAddresses.length `TokensUnfrozen` events upon successful batch partial unfreezing. - * To execute this function, the calling agent must not be restricted from partially freezing tokens. - * If the agent is restricted from this capability, the function call will fail. - */ - function batchUnfreezePartialTokens(address[] calldata _userAddresses, uint256[] calldata _amounts) external; - /** * @dev Set restrictions on agent's roles. * This function can only be called by the contract owner, as enforced by the `onlyOwner` modifier. @@ -502,76 +132,6 @@ interface IToken is IERC20 { */ function setAgentRestrictions(address agent, TokenRoles memory restrictions) external; - /** - * @dev Returns the number of decimals used to get its user representation. - * For example, if `decimals` equals `2`, a balance of `505` tokens should - * be displayed to a user as `5,05` (`505 / 1 ** 2`). - * - * Tokens usually opt for a value of 18, imitating the relationship between - * Ether and Wei. - * - * NOTE: This information is only used for _display_ purposes: it in - * no way affects any of the arithmetic of the contract, including - * balanceOf() and transfer(). - */ - function decimals() external view returns (uint8); - - /** - * @dev Returns the name of the token. - */ - function name() external view returns (string memory); - - /** - * @dev Returns the address of the onchainID of the token. - * the onchainID of the token gives all the information available - * about the token and is managed by the token issuer or his agent. - */ - function onchainID() external view returns (address); - - /** - * @dev Returns the symbol of the token, usually a shorter version of the - * name. - */ - function symbol() external view returns (string memory); - - /** - * @dev Returns the TREX version of the token. - * current version is 3.0.0 - */ - function version() external view returns (string memory); - - /** - * @dev Returns the Identity Registry linked to the token - */ - function identityRegistry() external view returns (IIdentityRegistry); - - /** - * @dev Returns the Compliance contract linked to the token - */ - function compliance() external view returns (IModularCompliance); - - /** - * @dev Returns true if the contract is paused, and false otherwise. - */ - function paused() external view returns (bool); - - /** - * @dev Returns the freezing status of a wallet - * if isFrozen returns `true` the wallet is frozen - * if isFrozen returns `false` the wallet is not frozen - * isFrozen returning `true` doesn't mean that the balance is free, tokens could be blocked by - * a partial freeze or the whole token could be blocked by pause - * @param _userAddress the address of the wallet on which isFrozen is called - */ - function isFrozen(address _userAddress) external view returns (bool); - - /** - * @dev Returns the amount of tokens that are partially frozen on a wallet - * the amount of frozen tokens is always <= to the total balance of the wallet - * @param _userAddress the address of the wallet on which getFrozenTokens is called - */ - function getFrozenTokens(address _userAddress) external view returns (uint256); - /** * @dev Returns A `TokenRoles` struct containing boolean flags for each restricted role. * Each flag set to `true` disables the corresponding capability for the agent. diff --git a/contracts/token/Token.sol b/contracts/token/Token.sol index c2742ba9..7e8fa0ec 100755 --- a/contracts/token/Token.sol +++ b/contracts/token/Token.sol @@ -455,14 +455,14 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage, IERC165 { /** * @dev See {IToken-identityRegistry}. */ - function identityRegistry() external view override returns (IIdentityRegistry) { + function identityRegistry() external view override returns (IERC3643IdentityRegistry) { return _tokenIdentityRegistry; } /** * @dev See {IToken-compliance}. */ - function compliance() external view override returns (IModularCompliance) { + function compliance() external view override returns (IERC3643Compliance) { return _tokenCompliance; } @@ -635,7 +635,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage, IERC165 { * @dev See {IToken-setIdentityRegistry}. */ function setIdentityRegistry(address _identityRegistry) public override onlyOwner { - _tokenIdentityRegistry = IIdentityRegistry(_identityRegistry); + _tokenIdentityRegistry = IERC3643IdentityRegistry(_identityRegistry); emit IdentityRegistryAdded(_identityRegistry); } @@ -646,7 +646,7 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage, IERC165 { if (address(_tokenCompliance) != address(0)) { _tokenCompliance.unbindToken(address(this)); } - _tokenCompliance = IModularCompliance(_compliance); + _tokenCompliance = IERC3643Compliance(_compliance); _tokenCompliance.bindToken(address(this)); emit ComplianceAdded(_compliance); } @@ -670,10 +670,11 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage, IERC165 { */ function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { return - interfaceId == type(IERC20).interfaceId || // 0x36372b07 - interfaceId == type(IToken).interfaceId || // 0x4768ee17 - interfaceId == type(IERC173).interfaceId || // 0x7f5828d0 - interfaceId == type(IERC165).interfaceId; // 0x01ffc9a7 + interfaceId == type(IERC20).interfaceId || + interfaceId == type(IToken).interfaceId || + interfaceId == type(IERC173).interfaceId || + interfaceId == type(IERC165).interfaceId || + interfaceId == type(IERC3643).interfaceId; } /** diff --git a/contracts/token/TokenStorage.sol b/contracts/token/TokenStorage.sol index 1ce25063..19c03573 100644 --- a/contracts/token/TokenStorage.sol +++ b/contracts/token/TokenStorage.sol @@ -62,8 +62,8 @@ */ pragma solidity 0.8.26; -import "../compliance/modular/IModularCompliance.sol"; -import "../registry/interface/IIdentityRegistry.sol"; +import "../ERC-3643/IERC3643Compliance.sol"; +import "../ERC-3643/IERC3643IdentityRegistry.sol"; import "./TokenStructs.sol"; contract TokenStorage { @@ -86,10 +86,10 @@ contract TokenStorage { bool internal _tokenPaused = false; /// @dev Identity Registry contract used by the onchain validator system - IIdentityRegistry internal _tokenIdentityRegistry; + IERC3643IdentityRegistry internal _tokenIdentityRegistry; /// @dev Compliance contract linked to the onchain validator system - IModularCompliance internal _tokenCompliance; + IERC3643Compliance internal _tokenCompliance; mapping(address => TokenRoles) internal _agentsRestrictions; diff --git a/contracts/utils/InterfaceIdCalculator.sol b/contracts/utils/InterfaceIdCalculator.sol index 40be8b12..f9fa649e 100644 --- a/contracts/utils/InterfaceIdCalculator.sol +++ b/contracts/utils/InterfaceIdCalculator.sol @@ -72,6 +72,12 @@ import "../proxy/authority/IIAFactory.sol"; import "../factory/ITREXGateway.sol"; import "../DVA/IDVATransferManager.sol"; import "../compliance/modular/modules/IModule.sol"; +import "../compliance/modular/IModularCompliance.sol"; +import "../registry/interface/IClaimTopicsRegistry.sol"; +import "../registry/interface/IIdentityRegistry.sol"; +import "../registry/interface/IIdentityRegistryStorage.sol"; +import "../registry/interface/ITrustedIssuersRegistry.sol"; + contract InterfaceIdCalculator { /** @@ -82,9 +88,17 @@ contract InterfaceIdCalculator { return type(IERC20).interfaceId; } + /** + * @dev Returns the interface ID for the IERC3643 interface. + * IERC3643 interface ID is 0xb97d944c + */ + function getIERC3643InterfaceId() external pure returns (bytes4) { + return type(IERC3643).interfaceId; + } + /** * @dev Returns the interface ID for the IToken interface. - * IToken interface ID is 0x4768ee17 + * IToken interface ID is 0x5c0cda7e */ function getITokenInterfaceId() external pure returns (bytes4) { return type(IToken).interfaceId; @@ -107,35 +121,43 @@ contract InterfaceIdCalculator { } /** - * @dev Returns the interface ID for the IClaimTopicsRegistry interface. - * IClaimTopicsRegistry interface ID is 0x10928b13 + * @dev Returns the interface ID for the IERC3643ClaimTopicsRegistry interface. + * IERC3643ClaimTopicsRegistry interface ID is 0x10928b13 */ - function getIClaimTopicsRegistryInterfaceId() external pure returns (bytes4) { - return type(IClaimTopicsRegistry).interfaceId; + function getIERC3643ClaimTopicsRegistryInterfaceId() external pure returns (bytes4) { + return type(IERC3643ClaimTopicsRegistry).interfaceId; } /** * @dev Returns the interface ID for the IIdentityRegistry interface. - * IIdentityRegistry interface ID is 0x8ff89f73 + * IIdentityRegistry interface ID is 0xacb7b4db */ function getIIdentityRegistryInterfaceId() external pure returns (bytes4) { return type(IIdentityRegistry).interfaceId; } /** - * @dev Returns the interface ID for the IIdentityRegistryStorage interface. - * IIdentityRegistryStorage interface ID is 0x57defe0d + * @dev Returns the interface ID for the IERC3643IdentityRegistry interface. + * IERC3643IdentityRegistry interface ID is 0x8ff89f73 */ - function getIIdentityRegistryStorageInterfaceId() external pure returns (bytes4) { - return type(IIdentityRegistryStorage).interfaceId; + function getIERC3643IdentityRegistryInterfaceId() external pure returns (bytes4) { + return type(IERC3643IdentityRegistry).interfaceId; } /** - * @dev Returns the interface ID for the ITrustedIssuersRegistry interface. - * ITrustedIssuersRegistry interface ID is 0xb0f773b8 + * @dev Returns the interface ID for the IERC3643IdentityRegistryStorage interface. + * IERC3643IdentityRegistryStorage interface ID is 0x57defe0d */ - function getITrustedIssuersRegistryInterfaceId() external pure returns (bytes4) { - return type(ITrustedIssuersRegistry).interfaceId; + function getIERC3643IdentityRegistryStorageInterfaceId() external pure returns (bytes4) { + return type(IERC3643IdentityRegistryStorage).interfaceId; + } + + /** + * @dev Returns the interface ID for the IERC3643TrustedIssuersRegistry interface. + * IERC3643TrustedIssuersRegistry interface ID is 0xb0f773b8 + */ + function getIERC3643TrustedIssuersRegistryInterfaceId() external pure returns (bytes4) { + return type(IERC3643TrustedIssuersRegistry).interfaceId; } /** @@ -172,12 +194,20 @@ contract InterfaceIdCalculator { /** * @dev Returns the interface ID for the IModularCompliance interface. - * IModularCompliance interface ID is 0xef7cedae + * IModularCompliance interface ID is 0x4d6b83d6 */ function getIModularComplianceInterfaceId() external pure returns (bytes4) { return type(IModularCompliance).interfaceId; } + /** + * @dev Returns the interface ID for the IERC3643Compliance interface. + * IERC3643Compliance interface ID is 0x3144991c + */ + function getIERC3643ComplianceInterfaceId() external pure returns (bytes4) { + return type(IERC3643Compliance).interfaceId; + } + /** * @dev Returns the interface ID for the IModule interface. * IModule interface ID is 0xb795d01e diff --git a/test/compliance.test.ts b/test/compliance.test.ts index 9d7adf96..40f21014 100644 --- a/test/compliance.test.ts +++ b/test/compliance.test.ts @@ -525,6 +525,17 @@ describe('ModularCompliance', () => { expect(await compliance.supportsInterface(iModularComplianceInterfaceId)).to.equal(true); }); + it('should correctly identify the IERC3643Compliance interface ID', async () => { + const { + suite: { compliance }, + } = await loadFixture(deploySuiteWithModularCompliancesFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iComplianceInterfaceId = await interfaceIdCalculator.getIERC3643ComplianceInterfaceId(); + expect(await compliance.supportsInterface(iComplianceInterfaceId)).to.equal(true); + }); + it('should correctly identify the IERC173 interface ID', async () => { const { suite: { compliance }, diff --git a/test/dvd.test.ts b/test/dvd.test.ts index 88935bbf..a27754c5 100644 --- a/test/dvd.test.ts +++ b/test/dvd.test.ts @@ -551,12 +551,10 @@ describe('DVDTransferManager', () => { describe('When token does not have an Identity Registry (probably not a ERC3643 token', () => { it('should return false', async () => { const { - suite: { transferManager, token }, + suite: { transferManager }, } = await loadFixture(deployFullSuiteWithTransferManager); - await token.setIdentityRegistry(ethers.ZeroAddress); - - expect(await transferManager.isTREX(token.target)).to.be.false; + expect(await transferManager.isTREX(transferManager.target)).to.be.false; }); }); }); diff --git a/test/registries/claim-topics-registry.test.ts b/test/registries/claim-topics-registry.test.ts index 6b18d539..e1e279df 100644 --- a/test/registries/claim-topics-registry.test.ts +++ b/test/registries/claim-topics-registry.test.ts @@ -101,14 +101,14 @@ describe('ClaimTopicsRegistry', () => { expect(await claimTopicsRegistry.supportsInterface(unsupportedInterfaceId)).to.equal(false); }); - it('should correctly identify the IClaimTopicsRegistry interface ID', async () => { + it('should correctly identify the IERC3643ClaimTopicsRegistry interface ID', async () => { const { suite: { claimTopicsRegistry }, } = await loadFixture(deployFullSuiteFixture); const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); - const iClaimTopicsRegistryInterfaceId = await interfaceIdCalculator.getIClaimTopicsRegistryInterfaceId(); + const iClaimTopicsRegistryInterfaceId = await interfaceIdCalculator.getIERC3643ClaimTopicsRegistryInterfaceId(); expect(await claimTopicsRegistry.supportsInterface(iClaimTopicsRegistryInterfaceId)).to.equal(true); }); diff --git a/test/registries/identity-registry-storage.test.ts b/test/registries/identity-registry-storage.test.ts index cf85851b..01ab4638 100644 --- a/test/registries/identity-registry-storage.test.ts +++ b/test/registries/identity-registry-storage.test.ts @@ -370,14 +370,14 @@ describe('IdentityRegistryStorage', () => { expect(await identityRegistryStorage.supportsInterface(unsupportedInterfaceId)).to.equal(false); }); - it('should correctly identify the IIdentityRegistryStorage interface ID', async () => { + it('should correctly identify the IERC3643IdentityRegistryStorage interface ID', async () => { const { suite: { identityRegistryStorage }, } = await loadFixture(deployFullSuiteFixture); const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); - const iIdentityRegistryStorageInterfaceId = await interfaceIdCalculator.getIIdentityRegistryStorageInterfaceId(); + const iIdentityRegistryStorageInterfaceId = await interfaceIdCalculator.getIERC3643IdentityRegistryStorageInterfaceId(); expect(await identityRegistryStorage.supportsInterface(iIdentityRegistryStorageInterfaceId)).to.equal(true); }); diff --git a/test/registries/identity-registry.test.ts b/test/registries/identity-registry.test.ts index 4a8ea631..ba0c7023 100644 --- a/test/registries/identity-registry.test.ts +++ b/test/registries/identity-registry.test.ts @@ -417,6 +417,17 @@ describe('IdentityRegistry', () => { expect(await identityRegistry.supportsInterface(iIdentityRegistryInterfaceId)).to.equal(true); }); + it('should correctly identify the IERC3643IdentityRegistry interface ID', async () => { + const { + suite: { identityRegistry }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iIdentityRegistryInterfaceId = await interfaceIdCalculator.getIERC3643IdentityRegistryInterfaceId(); + expect(await identityRegistry.supportsInterface(iIdentityRegistryInterfaceId)).to.equal(true); + }); + it('should correctly identify the IERC173 interface ID', async () => { const { suite: { identityRegistry }, diff --git a/test/registries/trusted-issuers-registry.test.ts b/test/registries/trusted-issuers-registry.test.ts index c3ee8bdc..e7ba0392 100644 --- a/test/registries/trusted-issuers-registry.test.ts +++ b/test/registries/trusted-issuers-registry.test.ts @@ -290,14 +290,14 @@ describe('TrustedIssuersRegistry', () => { expect(await trustedIssuersRegistry.supportsInterface(unsupportedInterfaceId)).to.equal(false); }); - it('should correctly identify the ITrustedIssuersRegistry interface ID', async () => { + it('should correctly identify the IERC3643TrustedIssuersRegistry interface ID', async () => { const { suite: { trustedIssuersRegistry }, } = await loadFixture(deployFullSuiteFixture); const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); - const iTrustedIssuersRegistryInterfaceId = await interfaceIdCalculator.getITrustedIssuersRegistryInterfaceId(); + const iTrustedIssuersRegistryInterfaceId = await interfaceIdCalculator.getIERC3643TrustedIssuersRegistryInterfaceId(); expect(await trustedIssuersRegistry.supportsInterface(iTrustedIssuersRegistryInterfaceId)).to.equal(true); }); diff --git a/test/token/token-information.test.ts b/test/token/token-information.test.ts index 0668b018..0de50cf7 100644 --- a/test/token/token-information.test.ts +++ b/test/token/token-information.test.ts @@ -366,6 +366,17 @@ describe('Token - Information', () => { expect(await token.supportsInterface(iTokenInterfaceId)).to.equal(true); }); + it('should correctly identify the IERC3643 interface ID', async () => { + const { + suite: { token }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const iErc3643InterfaceId = await interfaceIdCalculator.getIERC3643InterfaceId(); + expect(await token.supportsInterface(iErc3643InterfaceId)).to.equal(true); + }); + it('should correctly identify the IERC173 interface ID', async () => { const { suite: { token }, From f0b2d47376e6466ce0a7d299a8ccc581ad18bf66 Mon Sep 17 00:00:00 2001 From: joachimlebrun Date: Mon, 9 Sep 2024 19:09:38 +0700 Subject: [PATCH 36/55] =?UTF-8?q?=F0=9F=93=9D(changelog)=20update=20change?= =?UTF-8?q?log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 272fe03e..9dccd97b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,15 @@ All notable changes to this project will be documented in this file. - Introduced the `addAndSetModule` function in the `ModularCompliance` contract, allowing the contract owner to add a new compliance module and interact with it in a single transaction. - This function supports adding a module and performing up to 5 interactions with the module in one call, streamlining the setup process for compliance modules. +- **Granular Agent Permissioning**: + - Introduced a new system to provide more granular control over agent roles on the token contract. + - **Default Behavior**: By default, agents can perform all actions (mint, burn, freeze tokens, freeze wallets, recover tokens, pause, unpause). + - **Restricting Permissions**: Token owners can now restrict specific roles for agents using the `setAgentRestrictions` function. + - Permissions can be restricted on actions like minting, burning, freezing, recovering, etc. + - Custom restrictions are stored in the `TokenRoles` struct. + - The `AgentRestrictionsSet` event is emitted whenever restrictions are updated for an agent. + - All agent-scoped functions (e.g., mint, burn) now check the agent’s permissions before executing the transaction, ensuring proper enforcement of these restrictions. + ### Updated - **Token Recovery Function**: From 8c5fa14bef581538172ff092f6b6473ab9d1a4cd Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 9 Sep 2024 20:39:38 +0800 Subject: [PATCH 37/55] Solidity 0.8.27 (#224) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨(solidity) v0.8.27 * 📝(changelog) v0.8.27 --- CHANGELOG.md | 14 ++++++++++++++ contracts/DVA/DVATransferManager.sol | 2 +- contracts/DVA/DVATransferManagerProxy.sol | 2 +- contracts/DVA/IDVATransferManager.sol | 2 +- contracts/DVD/DVDTransferManager.sol | 2 +- contracts/ERC-3643/IERC3643.sol | 2 +- contracts/ERC-3643/IERC3643ClaimTopicsRegistry.sol | 2 +- contracts/ERC-3643/IERC3643Compliance.sol | 2 +- contracts/ERC-3643/IERC3643IdentityRegistry.sol | 2 +- .../ERC-3643/IERC3643IdentityRegistryStorage.sol | 2 +- .../ERC-3643/IERC3643TrustedIssuersRegistry.sol | 2 +- contracts/_testContracts/MockContract.sol | 2 +- contracts/_testContracts/TestERC20.sol | 2 +- .../TestUpgradedCountryAllowModule.sol | 2 +- contracts/_testContracts/v_3_5_2/LegacyIA.sol | 2 +- contracts/_testContracts/v_3_5_2/LegacyProxy.sol | 2 +- .../_testContracts/v_3_5_2/LegacyToken_3_5_2.sol | 2 +- contracts/compliance/legacy/BasicCompliance.sol | 2 +- contracts/compliance/legacy/DefaultCompliance.sol | 2 +- contracts/compliance/legacy/ICompliance.sol | 2 +- .../compliance/legacy/features/ApproveTransfer.sol | 2 +- .../legacy/features/CountryRestrictions.sol | 2 +- .../legacy/features/CountryWhitelisting.sol | 2 +- .../compliance/legacy/features/DayMonthLimits.sol | 2 +- .../legacy/features/ExchangeMonthlyLimits.sol | 2 +- .../compliance/legacy/features/MaxBalance.sol | 2 +- .../compliance/legacy/features/SupplyLimit.sol | 2 +- .../compliance/legacy/test/ApproveTransferTest.sol | 2 +- .../legacy/test/CountryRestrictionsTest.sol | 2 +- .../legacy/test/CountryWhitelistingTest.sol | 2 +- .../compliance/legacy/test/DayMonthLimitsTest.sol | 2 +- .../legacy/test/ExchangeMonthlyLimitsTest.sol | 2 +- .../compliance/legacy/test/MaxBalanceTest.sol | 2 +- .../compliance/legacy/test/SupplyLimitTest.sol | 2 +- .../compliance/modular/IModularCompliance.sol | 2 +- contracts/compliance/modular/MCStorage.sol | 2 +- contracts/compliance/modular/ModularCompliance.sol | 2 +- .../compliance/modular/modules/AbstractModule.sol | 2 +- .../modular/modules/AbstractModuleUpgradeable.sol | 2 +- .../modular/modules/ConditionalTransferModule.sol | 2 +- .../modular/modules/CountryAllowModule.sol | 2 +- .../modular/modules/CountryRestrictModule.sol | 2 +- .../modules/ExchangeMonthlyLimitsModule.sol | 2 +- contracts/compliance/modular/modules/IModule.sol | 2 +- .../modular/modules/MaxBalanceModule.sol | 2 +- .../compliance/modular/modules/ModuleProxy.sol | 2 +- .../modular/modules/SupplyLimitModule.sol | 2 +- .../modular/modules/TimeExchangeLimitsModule.sol | 2 +- .../modular/modules/TimeTransfersLimitsModule.sol | 2 +- .../modular/modules/TransferFeesModule.sol | 2 +- .../modular/modules/TransferRestrictModule.sol | 2 +- contracts/errors/CommonErrors.sol | 2 +- contracts/errors/ComplianceErrors.sol | 2 +- contracts/errors/InvalidArgumentErrors.sol | 2 +- contracts/errors/RoleErrors.sol | 2 +- contracts/events/CommonEvents.sol | 2 +- contracts/factory/ITREXFactory.sol | 2 +- contracts/factory/ITREXGateway.sol | 2 +- contracts/factory/TREXFactory.sol | 2 +- contracts/factory/TREXGateway.sol | 2 +- contracts/proxy/AbstractProxy.sol | 2 +- contracts/proxy/ClaimTopicsRegistryProxy.sol | 2 +- contracts/proxy/IdentityRegistryProxy.sol | 2 +- contracts/proxy/IdentityRegistryStorageProxy.sol | 2 +- contracts/proxy/ModularComplianceProxy.sol | 2 +- contracts/proxy/TokenProxy.sol | 2 +- contracts/proxy/TrustedIssuersRegistryProxy.sol | 2 +- contracts/proxy/authority/IAFactory.sol | 2 +- contracts/proxy/authority/IIAFactory.sol | 2 +- .../authority/ITREXImplementationAuthority.sol | 2 +- .../authority/TREXImplementationAuthority.sol | 2 +- contracts/proxy/interface/IProxy.sol | 2 +- .../implementation/ClaimTopicsRegistry.sol | 2 +- .../registry/implementation/IdentityRegistry.sol | 2 +- .../implementation/IdentityRegistryStorage.sol | 2 +- .../implementation/TrustedIssuersRegistry.sol | 2 +- .../registry/interface/IClaimTopicsRegistry.sol | 2 +- contracts/registry/interface/IIdentityRegistry.sol | 2 +- .../interface/IIdentityRegistryStorage.sol | 2 +- .../registry/interface/ITrustedIssuersRegistry.sol | 2 +- contracts/registry/storage/CTRStorage.sol | 2 +- contracts/registry/storage/IRSStorage.sol | 2 +- contracts/registry/storage/IRStorage.sol | 2 +- contracts/registry/storage/TIRStorage.sol | 2 +- contracts/roles/AgentRole.sol | 2 +- contracts/roles/AgentRoleUpgradeable.sol | 2 +- contracts/roles/IERC173.sol | 2 +- contracts/roles/Roles.sol | 2 +- .../roles/permissioning/agent/AgentManager.sol | 2 +- contracts/roles/permissioning/agent/AgentRoles.sol | 2 +- .../permissioning/agent/AgentRolesUpgradeable.sol | 2 +- .../roles/permissioning/owner/OwnerManager.sol | 2 +- contracts/roles/permissioning/owner/OwnerRoles.sol | 2 +- .../permissioning/owner/OwnerRolesUpgradeable.sol | 2 +- contracts/token/IToken.sol | 2 +- contracts/token/Token.sol | 2 +- contracts/token/TokenStorage.sol | 2 +- contracts/token/TokenStructs.sol | 2 +- contracts/utils/InterfaceIdCalculator.sol | 2 +- hardhat.config.ts | 3 +-- 100 files changed, 113 insertions(+), 100 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dccd97b..0227eaef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,20 @@ All notable changes to this project will be documented in this file. - The `AgentRestrictionsSet` event is emitted whenever restrictions are updated for an agent. - All agent-scoped functions (e.g., mint, burn) now check the agent’s permissions before executing the transaction, ensuring proper enforcement of these restrictions. +- **Ethers.js Version Upgrade**: + - The project was upgraded from **Ethers v5** to **Ethers v6**, introducing several changes to the API and syntax. + - **Key Changes**: + - Adjusted syntax for contract deployments, interactions, and function calls to comply with Ethers v6. + - Replaced deprecated features from v5 with the new Ethers v6 equivalents, ensuring compatibility and future-proofing the project. + - Updated test suites and helper functions to use the Ethers v6 `Interface` and `Contract` classes, ensuring smooth testing of the updated code. + - This upgrade ensures better performance, enhanced security, and improved developer experience moving forward. + +- **Solidity Version Upgrade to 0.8.27**: + - Upgraded Solidity version from **0.8.17** to **0.8.27** across all contracts, bringing in multiple new features and improvements: + - **File-Level Event Declaration**: Events are now declared at the file level, simplifying code structure and improving readability. + - **Custom Errors for Require Statements**: All `require` clauses that previously returned a string reason for failure have been updated to use **custom errors**, making debugging easier and more efficient. + - This upgrade provides a cleaner, more efficient error handling process and improves overall code structure without affecting backward compatibility. + ### Updated - **Token Recovery Function**: diff --git a/contracts/DVA/DVATransferManager.sol b/contracts/DVA/DVATransferManager.sol index b3381ed4..b8664a30 100644 --- a/contracts/DVA/DVATransferManager.sol +++ b/contracts/DVA/DVATransferManager.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../roles/AgentRole.sol"; import "../token/IToken.sol"; diff --git a/contracts/DVA/DVATransferManagerProxy.sol b/contracts/DVA/DVATransferManagerProxy.sol index 2a441a9b..1e93ee57 100644 --- a/contracts/DVA/DVATransferManagerProxy.sol +++ b/contracts/DVA/DVATransferManagerProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; diff --git a/contracts/DVA/IDVATransferManager.sol b/contracts/DVA/IDVATransferManager.sol index 9d746bdd..69eab01b 100644 --- a/contracts/DVA/IDVATransferManager.sol +++ b/contracts/DVA/IDVATransferManager.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../roles/AgentRole.sol"; import "../token/IToken.sol"; diff --git a/contracts/DVD/DVDTransferManager.sol b/contracts/DVD/DVDTransferManager.sol index a0ce737e..9c06741c 100644 --- a/contracts/DVD/DVDTransferManager.sol +++ b/contracts/DVD/DVDTransferManager.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../roles/AgentRole.sol"; import "../token/IToken.sol"; diff --git a/contracts/ERC-3643/IERC3643.sol b/contracts/ERC-3643/IERC3643.sol index 8af2604e..d309121e 100644 --- a/contracts/ERC-3643/IERC3643.sol +++ b/contracts/ERC-3643/IERC3643.sol @@ -37,7 +37,7 @@ // :#%%= // -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; diff --git a/contracts/ERC-3643/IERC3643ClaimTopicsRegistry.sol b/contracts/ERC-3643/IERC3643ClaimTopicsRegistry.sol index 256230ca..6644070a 100644 --- a/contracts/ERC-3643/IERC3643ClaimTopicsRegistry.sol +++ b/contracts/ERC-3643/IERC3643ClaimTopicsRegistry.sol @@ -36,7 +36,7 @@ // +@@@@%- // :#%%= // -pragma solidity 0.8.26; +pragma solidity 0.8.27; /// Events diff --git a/contracts/ERC-3643/IERC3643Compliance.sol b/contracts/ERC-3643/IERC3643Compliance.sol index 6f7a3e61..2969dad5 100644 --- a/contracts/ERC-3643/IERC3643Compliance.sol +++ b/contracts/ERC-3643/IERC3643Compliance.sol @@ -36,7 +36,7 @@ // +@@@@%- // :#%%= // -pragma solidity 0.8.26; +pragma solidity 0.8.27; /// Events diff --git a/contracts/ERC-3643/IERC3643IdentityRegistry.sol b/contracts/ERC-3643/IERC3643IdentityRegistry.sol index d64d8a59..52ebc793 100644 --- a/contracts/ERC-3643/IERC3643IdentityRegistry.sol +++ b/contracts/ERC-3643/IERC3643IdentityRegistry.sol @@ -36,7 +36,7 @@ // +@@@@%- // :#%%= // -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; import "./IERC3643IdentityRegistryStorage.sol"; diff --git a/contracts/ERC-3643/IERC3643IdentityRegistryStorage.sol b/contracts/ERC-3643/IERC3643IdentityRegistryStorage.sol index db68bb8e..2583a4be 100644 --- a/contracts/ERC-3643/IERC3643IdentityRegistryStorage.sol +++ b/contracts/ERC-3643/IERC3643IdentityRegistryStorage.sol @@ -36,7 +36,7 @@ // +@@@@%- // :#%%= // -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; /// events diff --git a/contracts/ERC-3643/IERC3643TrustedIssuersRegistry.sol b/contracts/ERC-3643/IERC3643TrustedIssuersRegistry.sol index 06ed14f0..cf1057ff 100644 --- a/contracts/ERC-3643/IERC3643TrustedIssuersRegistry.sol +++ b/contracts/ERC-3643/IERC3643TrustedIssuersRegistry.sol @@ -36,7 +36,7 @@ // +@@@@%- // :#%%= // -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; /// Events diff --git a/contracts/_testContracts/MockContract.sol b/contracts/_testContracts/MockContract.sol index 1881e66f..95f753fc 100644 --- a/contracts/_testContracts/MockContract.sol +++ b/contracts/_testContracts/MockContract.sol @@ -1,4 +1,4 @@ -pragma solidity 0.8.26; +pragma solidity 0.8.27; contract MockContract { address _irRegistry; diff --git a/contracts/_testContracts/TestERC20.sol b/contracts/_testContracts/TestERC20.sol index 90ed59fe..dbe266ef 100644 --- a/contracts/_testContracts/TestERC20.sol +++ b/contracts/_testContracts/TestERC20.sol @@ -58,7 +58,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/contracts/_testContracts/TestUpgradedCountryAllowModule.sol b/contracts/_testContracts/TestUpgradedCountryAllowModule.sol index 76bb6fdb..81ab029e 100644 --- a/contracts/_testContracts/TestUpgradedCountryAllowModule.sol +++ b/contracts/_testContracts/TestUpgradedCountryAllowModule.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../compliance/modular/modules/CountryAllowModule.sol"; diff --git a/contracts/_testContracts/v_3_5_2/LegacyIA.sol b/contracts/_testContracts/v_3_5_2/LegacyIA.sol index c362866a..db920477 100644 --- a/contracts/_testContracts/v_3_5_2/LegacyIA.sol +++ b/contracts/_testContracts/v_3_5_2/LegacyIA.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity 0.8.27; abstract contract ContextLegacy { function _msgSender() internal view virtual returns (address) { diff --git a/contracts/_testContracts/v_3_5_2/LegacyProxy.sol b/contracts/_testContracts/v_3_5_2/LegacyProxy.sol index 5e193918..ba5dcfed 100644 --- a/contracts/_testContracts/v_3_5_2/LegacyProxy.sol +++ b/contracts/_testContracts/v_3_5_2/LegacyProxy.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity 0.8.27; interface IImplementationAuthorityLegacy { function getImplementation() external view returns (address); diff --git a/contracts/_testContracts/v_3_5_2/LegacyToken_3_5_2.sol b/contracts/_testContracts/v_3_5_2/LegacyToken_3_5_2.sol index dbc098fb..fa154e01 100644 --- a/contracts/_testContracts/v_3_5_2/LegacyToken_3_5_2.sol +++ b/contracts/_testContracts/v_3_5_2/LegacyToken_3_5_2.sol @@ -5,7 +5,7 @@ // File: @onchain-id/solidity/contracts/interface/IERC734Legacy.sol // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity 0.8.27; /** * @dev interface of the ERC734 (Key Holder) standard as defined in the EIP. diff --git a/contracts/compliance/legacy/BasicCompliance.sol b/contracts/compliance/legacy/BasicCompliance.sol index 09bcdb07..9b77bdb6 100644 --- a/contracts/compliance/legacy/BasicCompliance.sol +++ b/contracts/compliance/legacy/BasicCompliance.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../../roles/AgentRole.sol"; import "./ICompliance.sol"; diff --git a/contracts/compliance/legacy/DefaultCompliance.sol b/contracts/compliance/legacy/DefaultCompliance.sol index b1ee3d68..c2fc523a 100644 --- a/contracts/compliance/legacy/DefaultCompliance.sol +++ b/contracts/compliance/legacy/DefaultCompliance.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "./BasicCompliance.sol"; diff --git a/contracts/compliance/legacy/ICompliance.sol b/contracts/compliance/legacy/ICompliance.sol index ddd68be4..f9a8070e 100644 --- a/contracts/compliance/legacy/ICompliance.sol +++ b/contracts/compliance/legacy/ICompliance.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; interface ICompliance { /** diff --git a/contracts/compliance/legacy/features/ApproveTransfer.sol b/contracts/compliance/legacy/features/ApproveTransfer.sol index bb1680ca..d5076852 100644 --- a/contracts/compliance/legacy/features/ApproveTransfer.sol +++ b/contracts/compliance/legacy/features/ApproveTransfer.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../BasicCompliance.sol"; diff --git a/contracts/compliance/legacy/features/CountryRestrictions.sol b/contracts/compliance/legacy/features/CountryRestrictions.sol index 36101b66..a2862330 100644 --- a/contracts/compliance/legacy/features/CountryRestrictions.sol +++ b/contracts/compliance/legacy/features/CountryRestrictions.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../BasicCompliance.sol"; diff --git a/contracts/compliance/legacy/features/CountryWhitelisting.sol b/contracts/compliance/legacy/features/CountryWhitelisting.sol index 473952df..4adc4c85 100644 --- a/contracts/compliance/legacy/features/CountryWhitelisting.sol +++ b/contracts/compliance/legacy/features/CountryWhitelisting.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../BasicCompliance.sol"; diff --git a/contracts/compliance/legacy/features/DayMonthLimits.sol b/contracts/compliance/legacy/features/DayMonthLimits.sol index 67f2566d..fd7381e2 100644 --- a/contracts/compliance/legacy/features/DayMonthLimits.sol +++ b/contracts/compliance/legacy/features/DayMonthLimits.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../BasicCompliance.sol"; diff --git a/contracts/compliance/legacy/features/ExchangeMonthlyLimits.sol b/contracts/compliance/legacy/features/ExchangeMonthlyLimits.sol index 77653c12..47201e99 100644 --- a/contracts/compliance/legacy/features/ExchangeMonthlyLimits.sol +++ b/contracts/compliance/legacy/features/ExchangeMonthlyLimits.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../BasicCompliance.sol"; diff --git a/contracts/compliance/legacy/features/MaxBalance.sol b/contracts/compliance/legacy/features/MaxBalance.sol index 40e229a3..93434159 100644 --- a/contracts/compliance/legacy/features/MaxBalance.sol +++ b/contracts/compliance/legacy/features/MaxBalance.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../BasicCompliance.sol"; diff --git a/contracts/compliance/legacy/features/SupplyLimit.sol b/contracts/compliance/legacy/features/SupplyLimit.sol index 8377ebab..26d5a956 100644 --- a/contracts/compliance/legacy/features/SupplyLimit.sol +++ b/contracts/compliance/legacy/features/SupplyLimit.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../BasicCompliance.sol"; diff --git a/contracts/compliance/legacy/test/ApproveTransferTest.sol b/contracts/compliance/legacy/test/ApproveTransferTest.sol index 4b39d26b..0d73c1c4 100644 --- a/contracts/compliance/legacy/test/ApproveTransferTest.sol +++ b/contracts/compliance/legacy/test/ApproveTransferTest.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../features/ApproveTransfer.sol"; diff --git a/contracts/compliance/legacy/test/CountryRestrictionsTest.sol b/contracts/compliance/legacy/test/CountryRestrictionsTest.sol index 1355cc9e..d9b6519f 100644 --- a/contracts/compliance/legacy/test/CountryRestrictionsTest.sol +++ b/contracts/compliance/legacy/test/CountryRestrictionsTest.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../features/CountryRestrictions.sol"; diff --git a/contracts/compliance/legacy/test/CountryWhitelistingTest.sol b/contracts/compliance/legacy/test/CountryWhitelistingTest.sol index 58d5b334..49739725 100644 --- a/contracts/compliance/legacy/test/CountryWhitelistingTest.sol +++ b/contracts/compliance/legacy/test/CountryWhitelistingTest.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../features/CountryWhitelisting.sol"; diff --git a/contracts/compliance/legacy/test/DayMonthLimitsTest.sol b/contracts/compliance/legacy/test/DayMonthLimitsTest.sol index 7a162ae0..500c3060 100644 --- a/contracts/compliance/legacy/test/DayMonthLimitsTest.sol +++ b/contracts/compliance/legacy/test/DayMonthLimitsTest.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../features/DayMonthLimits.sol"; diff --git a/contracts/compliance/legacy/test/ExchangeMonthlyLimitsTest.sol b/contracts/compliance/legacy/test/ExchangeMonthlyLimitsTest.sol index 992a69be..498ec129 100644 --- a/contracts/compliance/legacy/test/ExchangeMonthlyLimitsTest.sol +++ b/contracts/compliance/legacy/test/ExchangeMonthlyLimitsTest.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../features/ExchangeMonthlyLimits.sol"; diff --git a/contracts/compliance/legacy/test/MaxBalanceTest.sol b/contracts/compliance/legacy/test/MaxBalanceTest.sol index e5967fb7..816931f4 100644 --- a/contracts/compliance/legacy/test/MaxBalanceTest.sol +++ b/contracts/compliance/legacy/test/MaxBalanceTest.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../features/MaxBalance.sol"; diff --git a/contracts/compliance/legacy/test/SupplyLimitTest.sol b/contracts/compliance/legacy/test/SupplyLimitTest.sol index 322a3272..94797030 100644 --- a/contracts/compliance/legacy/test/SupplyLimitTest.sol +++ b/contracts/compliance/legacy/test/SupplyLimitTest.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../features/SupplyLimit.sol"; diff --git a/contracts/compliance/modular/IModularCompliance.sol b/contracts/compliance/modular/IModularCompliance.sol index 40a1ed99..63dd38b5 100644 --- a/contracts/compliance/modular/IModularCompliance.sol +++ b/contracts/compliance/modular/IModularCompliance.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../../ERC-3643/IERC3643Compliance.sol"; diff --git a/contracts/compliance/modular/MCStorage.sol b/contracts/compliance/modular/MCStorage.sol index 8337f04b..f50d9e92 100644 --- a/contracts/compliance/modular/MCStorage.sol +++ b/contracts/compliance/modular/MCStorage.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; contract MCStorage { /// token linked to the compliance contract diff --git a/contracts/compliance/modular/ModularCompliance.sol b/contracts/compliance/modular/ModularCompliance.sol index d2ecf752..039a442d 100644 --- a/contracts/compliance/modular/ModularCompliance.sol +++ b/contracts/compliance/modular/ModularCompliance.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/AbstractModule.sol b/contracts/compliance/modular/modules/AbstractModule.sol index 6b66f354..53102e47 100644 --- a/contracts/compliance/modular/modules/AbstractModule.sol +++ b/contracts/compliance/modular/modules/AbstractModule.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "./IModule.sol"; import "../../../errors/InvalidArgumentErrors.sol"; diff --git a/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol index 4a421961..177f49b3 100644 --- a/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol +++ b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; diff --git a/contracts/compliance/modular/modules/ConditionalTransferModule.sol b/contracts/compliance/modular/modules/ConditionalTransferModule.sol index 6cd9caa7..e94f07f3 100644 --- a/contracts/compliance/modular/modules/ConditionalTransferModule.sol +++ b/contracts/compliance/modular/modules/ConditionalTransferModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/CountryAllowModule.sol b/contracts/compliance/modular/modules/CountryAllowModule.sol index 3008fab3..a8ab9710 100644 --- a/contracts/compliance/modular/modules/CountryAllowModule.sol +++ b/contracts/compliance/modular/modules/CountryAllowModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/CountryRestrictModule.sol b/contracts/compliance/modular/modules/CountryRestrictModule.sol index d274b0e3..ca5b7ae0 100644 --- a/contracts/compliance/modular/modules/CountryRestrictModule.sol +++ b/contracts/compliance/modular/modules/CountryRestrictModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol b/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol index a93b8e69..f653831b 100644 --- a/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol +++ b/contracts/compliance/modular/modules/ExchangeMonthlyLimitsModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/IModule.sol b/contracts/compliance/modular/modules/IModule.sol index cbf11425..a0800fd8 100644 --- a/contracts/compliance/modular/modules/IModule.sol +++ b/contracts/compliance/modular/modules/IModule.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; // events diff --git a/contracts/compliance/modular/modules/MaxBalanceModule.sol b/contracts/compliance/modular/modules/MaxBalanceModule.sol index c8bb4bcd..81d64fbf 100644 --- a/contracts/compliance/modular/modules/MaxBalanceModule.sol +++ b/contracts/compliance/modular/modules/MaxBalanceModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../IModularCompliance.sol"; diff --git a/contracts/compliance/modular/modules/ModuleProxy.sol b/contracts/compliance/modular/modules/ModuleProxy.sol index cd8dfe9b..124b2263 100644 --- a/contracts/compliance/modular/modules/ModuleProxy.sol +++ b/contracts/compliance/modular/modules/ModuleProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; diff --git a/contracts/compliance/modular/modules/SupplyLimitModule.sol b/contracts/compliance/modular/modules/SupplyLimitModule.sol index 1a157ab3..7ab2d466 100644 --- a/contracts/compliance/modular/modules/SupplyLimitModule.sol +++ b/contracts/compliance/modular/modules/SupplyLimitModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity ^0.8.26; +pragma solidity 0.8.27; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol b/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol index 712654b6..99febb0a 100644 --- a/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol +++ b/contracts/compliance/modular/modules/TimeExchangeLimitsModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol b/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol index 99a3c6e9..df4ab011 100644 --- a/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol +++ b/contracts/compliance/modular/modules/TimeTransfersLimitsModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/TransferFeesModule.sol b/contracts/compliance/modular/modules/TransferFeesModule.sol index b57cbc83..8802527a 100644 --- a/contracts/compliance/modular/modules/TransferFeesModule.sol +++ b/contracts/compliance/modular/modules/TransferFeesModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; diff --git a/contracts/compliance/modular/modules/TransferRestrictModule.sol b/contracts/compliance/modular/modules/TransferRestrictModule.sol index 8584826a..35fdffcc 100644 --- a/contracts/compliance/modular/modules/TransferRestrictModule.sol +++ b/contracts/compliance/modular/modules/TransferRestrictModule.sol @@ -66,7 +66,7 @@ * Tokeny sàrl for licensing options. */ -pragma solidity ^0.8.26; +pragma solidity 0.8.27; import "./AbstractModuleUpgradeable.sol"; diff --git a/contracts/errors/CommonErrors.sol b/contracts/errors/CommonErrors.sol index b2045473..12e7eac6 100644 --- a/contracts/errors/CommonErrors.sol +++ b/contracts/errors/CommonErrors.sol @@ -62,7 +62,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; /// @dev Thrown when initialization has failed. error InitializationFailed(); diff --git a/contracts/errors/ComplianceErrors.sol b/contracts/errors/ComplianceErrors.sol index 3a227d66..3af7df53 100644 --- a/contracts/errors/ComplianceErrors.sol +++ b/contracts/errors/ComplianceErrors.sol @@ -62,7 +62,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; /// @dev Thrown when address is not a token bound to compliance contract. error AddressNotATokenBoundToComplianceContract(); diff --git a/contracts/errors/InvalidArgumentErrors.sol b/contracts/errors/InvalidArgumentErrors.sol index 33a1afab..6b1e4862 100644 --- a/contracts/errors/InvalidArgumentErrors.sol +++ b/contracts/errors/InvalidArgumentErrors.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; /// @dev Thrown when the address is not an ERC20. diff --git a/contracts/errors/RoleErrors.sol b/contracts/errors/RoleErrors.sol index 40580557..2d1aa1a4 100644 --- a/contracts/errors/RoleErrors.sol +++ b/contracts/errors/RoleErrors.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; /// @dev Thrown when account already has role. error AccountAlreadyHasRole(); diff --git a/contracts/events/CommonEvents.sol b/contracts/events/CommonEvents.sol index 12b3154d..82cd33f9 100644 --- a/contracts/events/CommonEvents.sol +++ b/contracts/events/CommonEvents.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; /// event emitted when the implementation authority of the factory contract is set diff --git a/contracts/factory/ITREXFactory.sol b/contracts/factory/ITREXFactory.sol index 2551ed67..9d6ce4a1 100644 --- a/contracts/factory/ITREXFactory.sol +++ b/contracts/factory/ITREXFactory.sol @@ -59,7 +59,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../events/CommonEvents.sol"; diff --git a/contracts/factory/ITREXGateway.sol b/contracts/factory/ITREXGateway.sol index 3c11002c..a6c25790 100644 --- a/contracts/factory/ITREXGateway.sol +++ b/contracts/factory/ITREXGateway.sol @@ -59,7 +59,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "./ITREXFactory.sol"; diff --git a/contracts/factory/TREXFactory.sol b/contracts/factory/TREXFactory.sol index da195b18..db737ed1 100644 --- a/contracts/factory/TREXFactory.sol +++ b/contracts/factory/TREXFactory.sol @@ -59,7 +59,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../roles/AgentRole.sol"; import "../token/IToken.sol"; diff --git a/contracts/factory/TREXGateway.sol b/contracts/factory/TREXGateway.sol index 58069a31..b8494385 100644 --- a/contracts/factory/TREXGateway.sol +++ b/contracts/factory/TREXGateway.sol @@ -59,7 +59,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "./ITREXGateway.sol"; import "../roles/AgentRole.sol"; diff --git a/contracts/proxy/AbstractProxy.sol b/contracts/proxy/AbstractProxy.sol index cf5a2064..fe039482 100644 --- a/contracts/proxy/AbstractProxy.sol +++ b/contracts/proxy/AbstractProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "./interface/IProxy.sol"; import "./authority/ITREXImplementationAuthority.sol"; diff --git a/contracts/proxy/ClaimTopicsRegistryProxy.sol b/contracts/proxy/ClaimTopicsRegistryProxy.sol index 25b29c52..ecccbf65 100644 --- a/contracts/proxy/ClaimTopicsRegistryProxy.sol +++ b/contracts/proxy/ClaimTopicsRegistryProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "./AbstractProxy.sol"; import "../errors/InvalidArgumentErrors.sol"; diff --git a/contracts/proxy/IdentityRegistryProxy.sol b/contracts/proxy/IdentityRegistryProxy.sol index 301de9ea..ff81a49d 100644 --- a/contracts/proxy/IdentityRegistryProxy.sol +++ b/contracts/proxy/IdentityRegistryProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "./AbstractProxy.sol"; import "../errors/CommonErrors.sol"; diff --git a/contracts/proxy/IdentityRegistryStorageProxy.sol b/contracts/proxy/IdentityRegistryStorageProxy.sol index 17bbc028..fcf29b95 100644 --- a/contracts/proxy/IdentityRegistryStorageProxy.sol +++ b/contracts/proxy/IdentityRegistryStorageProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "./AbstractProxy.sol"; import "../errors/CommonErrors.sol"; diff --git a/contracts/proxy/ModularComplianceProxy.sol b/contracts/proxy/ModularComplianceProxy.sol index 973b72d2..b1ec101b 100644 --- a/contracts/proxy/ModularComplianceProxy.sol +++ b/contracts/proxy/ModularComplianceProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "./AbstractProxy.sol"; import "../errors/CommonErrors.sol"; diff --git a/contracts/proxy/TokenProxy.sol b/contracts/proxy/TokenProxy.sol index 30897cdc..5494d54e 100644 --- a/contracts/proxy/TokenProxy.sol +++ b/contracts/proxy/TokenProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "./AbstractProxy.sol"; import "../errors/InvalidArgumentErrors.sol"; diff --git a/contracts/proxy/TrustedIssuersRegistryProxy.sol b/contracts/proxy/TrustedIssuersRegistryProxy.sol index 634a8888..25b4567f 100644 --- a/contracts/proxy/TrustedIssuersRegistryProxy.sol +++ b/contracts/proxy/TrustedIssuersRegistryProxy.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "./AbstractProxy.sol"; import "../errors/InvalidArgumentErrors.sol"; diff --git a/contracts/proxy/authority/IAFactory.sol b/contracts/proxy/authority/IAFactory.sol index 5123506a..9f6af7bd 100644 --- a/contracts/proxy/authority/IAFactory.sol +++ b/contracts/proxy/authority/IAFactory.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "./TREXImplementationAuthority.sol"; diff --git a/contracts/proxy/authority/IIAFactory.sol b/contracts/proxy/authority/IIAFactory.sol index 4562fcaf..75ca3053 100644 --- a/contracts/proxy/authority/IIAFactory.sol +++ b/contracts/proxy/authority/IIAFactory.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; /// Events diff --git a/contracts/proxy/authority/ITREXImplementationAuthority.sol b/contracts/proxy/authority/ITREXImplementationAuthority.sol index 41268244..d267ce75 100644 --- a/contracts/proxy/authority/ITREXImplementationAuthority.sol +++ b/contracts/proxy/authority/ITREXImplementationAuthority.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; /// events diff --git a/contracts/proxy/authority/TREXImplementationAuthority.sol b/contracts/proxy/authority/TREXImplementationAuthority.sol index 95a8009a..5a5686ce 100644 --- a/contracts/proxy/authority/TREXImplementationAuthority.sol +++ b/contracts/proxy/authority/TREXImplementationAuthority.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@openzeppelin/contracts/access/Ownable.sol"; import "./ITREXImplementationAuthority.sol"; diff --git a/contracts/proxy/interface/IProxy.sol b/contracts/proxy/interface/IProxy.sol index b430ac15..8f764639 100644 --- a/contracts/proxy/interface/IProxy.sol +++ b/contracts/proxy/interface/IProxy.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../../events/CommonEvents.sol"; diff --git a/contracts/registry/implementation/ClaimTopicsRegistry.sol b/contracts/registry/implementation/ClaimTopicsRegistry.sol index a9129cda..33cd62ac 100644 --- a/contracts/registry/implementation/ClaimTopicsRegistry.sol +++ b/contracts/registry/implementation/ClaimTopicsRegistry.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../storage/CTRStorage.sol"; diff --git a/contracts/registry/implementation/IdentityRegistry.sol b/contracts/registry/implementation/IdentityRegistry.sol index 9193ee13..e8a39871 100644 --- a/contracts/registry/implementation/IdentityRegistry.sol +++ b/contracts/registry/implementation/IdentityRegistry.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; diff --git a/contracts/registry/implementation/IdentityRegistryStorage.sol b/contracts/registry/implementation/IdentityRegistryStorage.sol index 2291a1e4..333b9651 100644 --- a/contracts/registry/implementation/IdentityRegistryStorage.sol +++ b/contracts/registry/implementation/IdentityRegistryStorage.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; diff --git a/contracts/registry/implementation/TrustedIssuersRegistry.sol b/contracts/registry/implementation/TrustedIssuersRegistry.sol index acc6d50c..ace11ae4 100644 --- a/contracts/registry/implementation/TrustedIssuersRegistry.sol +++ b/contracts/registry/implementation/TrustedIssuersRegistry.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; diff --git a/contracts/registry/interface/IClaimTopicsRegistry.sol b/contracts/registry/interface/IClaimTopicsRegistry.sol index b83c29bf..e7ae6759 100644 --- a/contracts/registry/interface/IClaimTopicsRegistry.sol +++ b/contracts/registry/interface/IClaimTopicsRegistry.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../../ERC-3643/IERC3643ClaimTopicsRegistry.sol"; diff --git a/contracts/registry/interface/IIdentityRegistry.sol b/contracts/registry/interface/IIdentityRegistry.sol index 26469b19..8f0d214e 100644 --- a/contracts/registry/interface/IIdentityRegistry.sol +++ b/contracts/registry/interface/IIdentityRegistry.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../../ERC-3643/IERC3643IdentityRegistry.sol"; diff --git a/contracts/registry/interface/IIdentityRegistryStorage.sol b/contracts/registry/interface/IIdentityRegistryStorage.sol index 318fdf10..18cce88c 100644 --- a/contracts/registry/interface/IIdentityRegistryStorage.sol +++ b/contracts/registry/interface/IIdentityRegistryStorage.sol @@ -60,7 +60,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../../ERC-3643/IERC3643IdentityRegistryStorage.sol"; diff --git a/contracts/registry/interface/ITrustedIssuersRegistry.sol b/contracts/registry/interface/ITrustedIssuersRegistry.sol index b5cc75a7..f0232889 100644 --- a/contracts/registry/interface/ITrustedIssuersRegistry.sol +++ b/contracts/registry/interface/ITrustedIssuersRegistry.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../../ERC-3643/IERC3643TrustedIssuersRegistry.sol"; // solhint-disable-next-line no-empty-blocks diff --git a/contracts/registry/storage/CTRStorage.sol b/contracts/registry/storage/CTRStorage.sol index a4308c23..5bb952d9 100644 --- a/contracts/registry/storage/CTRStorage.sol +++ b/contracts/registry/storage/CTRStorage.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; contract CTRStorage { /// @dev All required Claim Topics diff --git a/contracts/registry/storage/IRSStorage.sol b/contracts/registry/storage/IRSStorage.sol index 687fada7..fac2210d 100644 --- a/contracts/registry/storage/IRSStorage.sol +++ b/contracts/registry/storage/IRSStorage.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; diff --git a/contracts/registry/storage/IRStorage.sol b/contracts/registry/storage/IRStorage.sol index a0a1d587..956ed581 100644 --- a/contracts/registry/storage/IRStorage.sol +++ b/contracts/registry/storage/IRStorage.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../interface/IClaimTopicsRegistry.sol"; import "../interface/ITrustedIssuersRegistry.sol"; diff --git a/contracts/registry/storage/TIRStorage.sol b/contracts/registry/storage/TIRStorage.sol index 976618e5..717f7032 100644 --- a/contracts/registry/storage/TIRStorage.sol +++ b/contracts/registry/storage/TIRStorage.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; diff --git a/contracts/roles/AgentRole.sol b/contracts/roles/AgentRole.sol index dbd8b80c..e591d940 100644 --- a/contracts/roles/AgentRole.sol +++ b/contracts/roles/AgentRole.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/contracts/roles/AgentRoleUpgradeable.sol b/contracts/roles/AgentRoleUpgradeable.sol index f36588a6..4f82628a 100644 --- a/contracts/roles/AgentRoleUpgradeable.sol +++ b/contracts/roles/AgentRoleUpgradeable.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; diff --git a/contracts/roles/IERC173.sol b/contracts/roles/IERC173.sol index 16c1b33e..5e0670ca 100644 --- a/contracts/roles/IERC173.sol +++ b/contracts/roles/IERC173.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; /// @title ERC-173 Contract Ownership Standard /// Note: the ERC-165 identifier for this interface is 0x7f5828d0 diff --git a/contracts/roles/Roles.sol b/contracts/roles/Roles.sol index 5bfd7fb6..dd49ace2 100644 --- a/contracts/roles/Roles.sol +++ b/contracts/roles/Roles.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../errors/InvalidArgumentErrors.sol"; import "../errors/RoleErrors.sol"; diff --git a/contracts/roles/permissioning/agent/AgentManager.sol b/contracts/roles/permissioning/agent/AgentManager.sol index 2ca84a8e..0a6c6373 100644 --- a/contracts/roles/permissioning/agent/AgentManager.sol +++ b/contracts/roles/permissioning/agent/AgentManager.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; diff --git a/contracts/roles/permissioning/agent/AgentRoles.sol b/contracts/roles/permissioning/agent/AgentRoles.sol index c5709ae9..509e43c9 100644 --- a/contracts/roles/permissioning/agent/AgentRoles.sol +++ b/contracts/roles/permissioning/agent/AgentRoles.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol b/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol index 38e43210..fb5aef48 100644 --- a/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol +++ b/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; diff --git a/contracts/roles/permissioning/owner/OwnerManager.sol b/contracts/roles/permissioning/owner/OwnerManager.sol index 96e0227e..00df7a97 100644 --- a/contracts/roles/permissioning/owner/OwnerManager.sol +++ b/contracts/roles/permissioning/owner/OwnerManager.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../../../token/IToken.sol"; import "../../../registry/interface/IIdentityRegistry.sol"; diff --git a/contracts/roles/permissioning/owner/OwnerRoles.sol b/contracts/roles/permissioning/owner/OwnerRoles.sol index 291dfd6f..65daf1a5 100644 --- a/contracts/roles/permissioning/owner/OwnerRoles.sol +++ b/contracts/roles/permissioning/owner/OwnerRoles.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol b/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol index 8a02d22d..2bbeb52e 100644 --- a/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol +++ b/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; diff --git a/contracts/token/IToken.sol b/contracts/token/IToken.sol index 487f9c07..2fe76fd8 100644 --- a/contracts/token/IToken.sol +++ b/contracts/token/IToken.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "./TokenStructs.sol"; import "../ERC-3643/IERC3643.sol"; diff --git a/contracts/token/Token.sol b/contracts/token/Token.sol index 7e8fa0ec..949f6865 100755 --- a/contracts/token/Token.sol +++ b/contracts/token/Token.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "./IToken.sol"; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; diff --git a/contracts/token/TokenStorage.sol b/contracts/token/TokenStorage.sol index 19c03573..a821ea60 100644 --- a/contracts/token/TokenStorage.sol +++ b/contracts/token/TokenStorage.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "../ERC-3643/IERC3643Compliance.sol"; import "../ERC-3643/IERC3643IdentityRegistry.sol"; import "./TokenStructs.sol"; diff --git a/contracts/token/TokenStructs.sol b/contracts/token/TokenStructs.sol index 126f3cf5..c8d0357a 100644 --- a/contracts/token/TokenStructs.sol +++ b/contracts/token/TokenStructs.sol @@ -62,7 +62,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; struct TokenRoles { bool disableMint; diff --git a/contracts/utils/InterfaceIdCalculator.sol b/contracts/utils/InterfaceIdCalculator.sol index f9fa649e..0f015a1d 100644 --- a/contracts/utils/InterfaceIdCalculator.sol +++ b/contracts/utils/InterfaceIdCalculator.sol @@ -61,7 +61,7 @@ * along with this program. If not, see . */ -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; diff --git a/hardhat.config.ts b/hardhat.config.ts index da2b5bf4..90f04820 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -9,13 +9,12 @@ import 'hardhat-tracer'; const config: HardhatUserConfig = { solidity: { - version: '0.8.26', + version: '0.8.27', settings: { optimizer: { enabled: true, runs: 200, }, - viaIR: true, }, }, gasReporter: { From 6f65f78735ef012cd574c5e2b17137c0239241d2 Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Mon, 7 Oct 2024 11:25:02 +0200 Subject: [PATCH 38/55] Ownership2steps (#226) Change OwnableUpgradeable to Ownable2StepUpgradeable https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.6/contracts/access/Ownable2StepUpgradeable.sol --- CHANGELOG.md | 11 +++ contracts/DVA/DVATransferManager.sol | 4 +- .../compliance/modular/ModularCompliance.sol | 4 +- .../modules/AbstractModuleUpgradeable.sol | 4 +- .../implementation/ClaimTopicsRegistry.sol | 4 +- .../implementation/TrustedIssuersRegistry.sol | 4 +- contracts/roles/AgentRoleUpgradeable.sol | 5 +- .../agent/AgentRolesUpgradeable.sol | 5 +- .../owner/OwnerRolesUpgradeable.sol | 5 +- .../utils/OwnableOnceNext2StepUpgradeable.sol | 94 +++++++++++++++++++ .../module-conditional-transfer.test.ts | 12 ++- test/compliances/module-country-allow.test.ts | 10 +- .../module-country-restrict.test.ts | 12 ++- .../module-exchange-monthly-limits.test.ts | 10 +- test/compliances/module-max-balance.test.ts | 10 +- test/compliances/module-supply-limit.test.ts | 10 +- .../module-time-exchange-limits.test.ts | 10 +- .../module-time-transfer-limits.test.ts | 10 +- test/compliances/module-transfer-fees.test.ts | 10 +- .../module-transfer-restrict.test.ts | 10 +- test/factory.test.ts | 10 +- 21 files changed, 210 insertions(+), 44 deletions(-) create mode 100644 contracts/utils/OwnableOnceNext2StepUpgradeable.sol diff --git a/CHANGELOG.md b/CHANGELOG.md index 0227eaef..141088ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,17 @@ All notable changes to this project will be documented in this file. - The function now accurately updates the identity registry, preventing errors related to attempting to add or remove identities that are already present or absent. - Improved overall logic to ensure smooth and error-free recovery operations, with events (`RecoverySuccess`, `TokensFrozen`, `TokensUnfrozen`, etc.) emitted to provide detailed feedback. +- **Ownership Transfer**: + - Implemented a two-step ownership transfer process across all relevant contracts in the suite, using OpenZeppelin's implementation `Ownable2StepUpgradeable`. + - This change enhances security by requiring the new owner to accept ownership explicitly, preventing accidental transfers to incorrect or inaccessible addresses. + - Added new functions: + - `transferOwnership(address newOwner)`: Initiates the ownership transfer process. + - `acceptOwnership()`: Allows the pending owner to accept and finalize the ownership transfer. + - Introduced a `_pendingOwner` state variable to track the address of the pending new owner. + - Updated relevant events to reflect the two-step process: + - `OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner)` + - `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)` + - This change affects all contracts that previously used a single-step ownership transfer, ensuring consistent and secure ownership management across the entire suite. ## [4.1.5] diff --git a/contracts/DVA/DVATransferManager.sol b/contracts/DVA/DVATransferManager.sol index b8664a30..0a317d62 100644 --- a/contracts/DVA/DVATransferManager.sol +++ b/contracts/DVA/DVATransferManager.sol @@ -72,12 +72,12 @@ import "../roles/AgentRole.sol"; import "../token/IToken.sol"; import "./IDVATransferManager.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import "../utils/OwnableOnceNext2StepUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import "../roles/IERC173.sol"; -contract DVATransferManager is IDVATransferManager, Initializable, OwnableUpgradeable, UUPSUpgradeable, IERC165 { +contract DVATransferManager is IDVATransferManager, Initializable, OwnableOnceNext2StepUpgradeable, UUPSUpgradeable, IERC165 { // Mapping for token approval criteria mapping(address => ApprovalCriteria) private _approvalCriteria; diff --git a/contracts/compliance/modular/ModularCompliance.sol b/contracts/compliance/modular/ModularCompliance.sol index 039a442d..e1d9f5dc 100644 --- a/contracts/compliance/modular/ModularCompliance.sol +++ b/contracts/compliance/modular/ModularCompliance.sol @@ -62,7 +62,7 @@ pragma solidity 0.8.27; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import "../../utils/OwnableOnceNext2StepUpgradeable.sol"; import "../../token/IToken.sol"; import "./IModularCompliance.sol"; import "./MCStorage.sol"; @@ -92,7 +92,7 @@ error OnlyOwnerOrTokenCanCall(); error TokenNotBound(); -contract ModularCompliance is IModularCompliance, OwnableUpgradeable, MCStorage, IERC165 { +contract ModularCompliance is IModularCompliance, OwnableOnceNext2StepUpgradeable, MCStorage, IERC165 { /// modifiers diff --git a/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol index 177f49b3..5e71cbde 100644 --- a/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol +++ b/contracts/compliance/modular/modules/AbstractModuleUpgradeable.sol @@ -63,7 +63,7 @@ pragma solidity 0.8.27; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import "../../../utils/OwnableOnceNext2StepUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "./IModule.sol"; import "../../../errors/InvalidArgumentErrors.sol"; @@ -72,7 +72,7 @@ import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import "../../../roles/IERC173.sol"; -abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUpgradeable, UUPSUpgradeable, IERC165 { +abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableOnceNext2StepUpgradeable, UUPSUpgradeable, IERC165 { struct AbstractModuleStorage { /// compliance contract binding status mapping(address => bool) complianceBound; diff --git a/contracts/registry/implementation/ClaimTopicsRegistry.sol b/contracts/registry/implementation/ClaimTopicsRegistry.sol index 33cd62ac..b2099942 100644 --- a/contracts/registry/implementation/ClaimTopicsRegistry.sol +++ b/contracts/registry/implementation/ClaimTopicsRegistry.sol @@ -62,7 +62,7 @@ pragma solidity 0.8.27; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import "../../utils/OwnableOnceNext2StepUpgradeable.sol"; import "../storage/CTRStorage.sol"; import "../interface/IClaimTopicsRegistry.sol"; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; @@ -78,7 +78,7 @@ error MaxTopicsReached(uint256 _max); error ClaimTopicAlreadyExists(); -contract ClaimTopicsRegistry is IClaimTopicsRegistry, OwnableUpgradeable, CTRStorage, IERC165 { +contract ClaimTopicsRegistry is IClaimTopicsRegistry, OwnableOnceNext2StepUpgradeable, CTRStorage, IERC165 { function init() external initializer { __Ownable_init(); diff --git a/contracts/registry/implementation/TrustedIssuersRegistry.sol b/contracts/registry/implementation/TrustedIssuersRegistry.sol index ace11ae4..59f70f3d 100644 --- a/contracts/registry/implementation/TrustedIssuersRegistry.sol +++ b/contracts/registry/implementation/TrustedIssuersRegistry.sol @@ -64,7 +64,7 @@ pragma solidity 0.8.27; import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import "../../utils/OwnableOnceNext2StepUpgradeable.sol"; import "../interface/ITrustedIssuersRegistry.sol"; import "../storage/TIRStorage.sol"; import "../../errors/InvalidArgumentErrors.sol"; @@ -97,7 +97,7 @@ error TrustedIssuerAlreadyExists(); error TrustedIssuerDoesNotExist(); -contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableUpgradeable, TIRStorage, IERC165 { +contract TrustedIssuersRegistry is ITrustedIssuersRegistry, OwnableOnceNext2StepUpgradeable, TIRStorage, IERC165 { /// Functions diff --git a/contracts/roles/AgentRoleUpgradeable.sol b/contracts/roles/AgentRoleUpgradeable.sol index 4f82628a..a963fdb1 100644 --- a/contracts/roles/AgentRoleUpgradeable.sol +++ b/contracts/roles/AgentRoleUpgradeable.sol @@ -63,8 +63,7 @@ pragma solidity 0.8.27; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - +import "../utils/OwnableOnceNext2StepUpgradeable.sol"; import "./Roles.sol"; import "../errors/InvalidArgumentErrors.sol"; import "../errors/RoleErrors.sol"; @@ -80,7 +79,7 @@ event AgentAdded(address indexed _agent); event AgentRemoved(address indexed _agent); -contract AgentRoleUpgradeable is OwnableUpgradeable { +contract AgentRoleUpgradeable is OwnableOnceNext2StepUpgradeable { using Roles for Roles.Role; Roles.Role private _agents; diff --git a/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol b/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol index fb5aef48..b63f8f39 100644 --- a/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol +++ b/contracts/roles/permissioning/agent/AgentRolesUpgradeable.sol @@ -63,8 +63,7 @@ pragma solidity 0.8.27; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - +import "../../../utils/OwnableOnceNext2StepUpgradeable.sol"; import "../../Roles.sol"; import "../../../errors/RoleErrors.sol"; @@ -81,7 +80,7 @@ event RoleAdded(address indexed _agent, string _role); event RoleRemoved(address indexed _agent, string _role); -contract AgentRolesUpgradeable is OwnableUpgradeable { +contract AgentRolesUpgradeable is OwnableOnceNext2StepUpgradeable { using Roles for Roles.Role; /// variables diff --git a/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol b/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol index 2bbeb52e..688f5fb9 100644 --- a/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol +++ b/contracts/roles/permissioning/owner/OwnerRolesUpgradeable.sol @@ -63,8 +63,7 @@ pragma solidity 0.8.27; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - +import "../../../utils/OwnableOnceNext2StepUpgradeable.sol"; import "../../Roles.sol"; import "../../../errors/RoleErrors.sol"; @@ -81,7 +80,7 @@ event RoleAdded(address indexed _owner, string _role); event RoleRemoved(address indexed _owner, string _role); -contract OwnerRolesUpgradeable is OwnableUpgradeable { +contract OwnerRolesUpgradeable is OwnableOnceNext2StepUpgradeable { using Roles for Roles.Role; /// variables diff --git a/contracts/utils/OwnableOnceNext2StepUpgradeable.sol b/contracts/utils/OwnableOnceNext2StepUpgradeable.sol new file mode 100644 index 00000000..aa177ad9 --- /dev/null +++ b/contracts/utils/OwnableOnceNext2StepUpgradeable.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-3.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// + +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2023, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +pragma solidity 0.8.27; + +import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; + +contract OwnableOnceNext2StepUpgradeable is Ownable2StepUpgradeable { + + struct Ownable2StepsStorage { + bool firstCall; + } + + bytes32 private constant _STORAGE_SLOT = keccak256("ownableOnceNext2StepUpgradeable.storage.firstCall"); + + function transferOwnership(address newOwner) public override onlyOwner { + Ownable2StepsStorage storage s = _getStorage(); + if (s.firstCall) { + s.firstCall = false; + super._transferOwnership(newOwner); + } + else { + super.transferOwnership(newOwner); + } + } + + function _getStorage() internal pure returns (Ownable2StepsStorage storage s) { + bytes32 position = _STORAGE_SLOT; + assembly { + s.slot := position + } + } + +} \ No newline at end of file diff --git a/test/compliances/module-conditional-transfer.test.ts b/test/compliances/module-conditional-transfer.test.ts index 7e93192e..ad08bdd3 100644 --- a/test/compliances/module-conditional-transfer.test.ts +++ b/test/compliances/module-conditional-transfer.test.ts @@ -83,8 +83,16 @@ describe('ConditionalTransferModule', () => { const context = await loadFixture(deployComplianceWithConditionalTransferModule); // when - await context.suite.conditionalTransferModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); - + const tx1 = await context.suite.conditionalTransferModule + .connect(context.accounts.deployer) + .transferOwnership(context.accounts.bobWallet.address); + expect(tx1) + .to.emit(context.suite.conditionalTransferModule, 'OwnershipTransferStarted') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); + const tx2 = await context.suite.conditionalTransferModule.connect(context.accounts.bobWallet).acceptOwnership(); + expect(tx2) + .to.emit(context.suite.conditionalTransferModule, 'OwnershipTransferred') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); // then const owner = await context.suite.conditionalTransferModule.owner(); expect(owner).to.eq(context.accounts.bobWallet.address); diff --git a/test/compliances/module-country-allow.test.ts b/test/compliances/module-country-allow.test.ts index 583e9019..be8d23ee 100644 --- a/test/compliances/module-country-allow.test.ts +++ b/test/compliances/module-country-allow.test.ts @@ -78,8 +78,14 @@ describe('CountryAllowModule', () => { const context = await loadFixture(deployComplianceWithCountryAllowModule); // when - await context.suite.countryAllowModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); - + const tx1 = await context.suite.countryAllowModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + expect(tx1) + .to.emit(context.suite.countryAllowModule, 'OwnershipTransferStarted') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); + const tx2 = await context.suite.countryAllowModule.connect(context.accounts.bobWallet).acceptOwnership(); + expect(tx2) + .to.emit(context.suite.countryAllowModule, 'OwnershipTransferred') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); // then const owner = await context.suite.countryAllowModule.owner(); expect(owner).to.eq(context.accounts.bobWallet.address); diff --git a/test/compliances/module-country-restrict.test.ts b/test/compliances/module-country-restrict.test.ts index a5665d6e..84db6842 100644 --- a/test/compliances/module-country-restrict.test.ts +++ b/test/compliances/module-country-restrict.test.ts @@ -77,8 +77,16 @@ describe('CountryRestrictModule', () => { const context = await loadFixture(deployComplianceWithCountryRestrictModule); // when - await context.suite.countryRestrictModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); - + const tx1 = await context.suite.countryRestrictModule + .connect(context.accounts.deployer) + .transferOwnership(context.accounts.bobWallet.address); + expect(tx1) + .to.emit(context.suite.countryRestrictModule, 'OwnershipTransferStarted') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); + const tx2 = await context.suite.countryRestrictModule.connect(context.accounts.bobWallet).acceptOwnership(); + expect(tx2) + .to.emit(context.suite.countryRestrictModule, 'OwnershipTransferred') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); // then const owner = await context.suite.countryRestrictModule.owner(); expect(owner).to.eq(context.accounts.bobWallet.address); diff --git a/test/compliances/module-exchange-monthly-limits.test.ts b/test/compliances/module-exchange-monthly-limits.test.ts index aa45a942..6d20b7c5 100644 --- a/test/compliances/module-exchange-monthly-limits.test.ts +++ b/test/compliances/module-exchange-monthly-limits.test.ts @@ -107,8 +107,14 @@ describe('Compliance Module: ExchangeMonthlyLimits', () => { const context = await loadFixture(deployExchangeMonthlyLimitsFixture); // when - await context.contracts.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); - + const tx1 = await context.contracts.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + expect(tx1) + .to.emit(context.contracts.complianceModule, 'OwnershipTransferStarted') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); + const tx2 = await context.contracts.complianceModule.connect(context.accounts.bobWallet).acceptOwnership(); + expect(tx2) + .to.emit(context.contracts.complianceModule, 'OwnershipTransferred') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); // then const owner = await context.contracts.complianceModule.owner(); expect(owner).to.eq(context.accounts.bobWallet.address); diff --git a/test/compliances/module-max-balance.test.ts b/test/compliances/module-max-balance.test.ts index eb8bb1ed..7e05b525 100644 --- a/test/compliances/module-max-balance.test.ts +++ b/test/compliances/module-max-balance.test.ts @@ -146,8 +146,14 @@ describe('Compliance Module: MaxBalance', () => { const context = await loadFixture(deployMaxBalanceFullSuite); // when - await context.suite.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); - + const tx1 = await context.suite.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + expect(tx1) + .to.emit(context.suite.complianceModule, 'OwnershipTransferStarted') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); + const tx2 = await context.suite.complianceModule.connect(context.accounts.bobWallet).acceptOwnership(); + expect(tx2) + .to.emit(context.suite.complianceModule, 'OwnershipTransferred') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); // then const owner = await context.suite.complianceModule.owner(); expect(owner).to.eq(context.accounts.bobWallet.address); diff --git a/test/compliances/module-supply-limit.test.ts b/test/compliances/module-supply-limit.test.ts index da88229f..09e13b47 100644 --- a/test/compliances/module-supply-limit.test.ts +++ b/test/compliances/module-supply-limit.test.ts @@ -106,8 +106,14 @@ describe('Compliance Module: SupplyLimit', () => { const context = await loadFixture(deploySupplyLimitFixture); // when - await context.suite.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); - + const tx1 = await context.suite.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + expect(tx1) + .to.emit(context.suite.complianceModule, 'OwnershipTransferStarted') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); + const tx2 = await context.suite.complianceModule.connect(context.accounts.bobWallet).acceptOwnership(); + expect(tx2) + .to.emit(context.suite.complianceModule, 'OwnershipTransferred') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); // then const owner = await context.suite.complianceModule.owner(); expect(owner).to.eq(context.accounts.bobWallet.address); diff --git a/test/compliances/module-time-exchange-limits.test.ts b/test/compliances/module-time-exchange-limits.test.ts index ee27e1a6..b35b6322 100644 --- a/test/compliances/module-time-exchange-limits.test.ts +++ b/test/compliances/module-time-exchange-limits.test.ts @@ -93,8 +93,14 @@ describe('Compliance Module: TimeExchangeLimits', () => { const context = await loadFixture(deployTimeExchangeLimitsFixture); // when - await context.contracts.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); - + const tx1 = await context.contracts.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + expect(tx1) + .to.emit(context.contracts.complianceModule, 'OwnershipTransferStarted') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); + const tx2 = await context.contracts.complianceModule.connect(context.accounts.bobWallet).acceptOwnership(); + expect(tx2) + .to.emit(context.contracts.complianceModule, 'OwnershipTransferred') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); // then const owner = await context.contracts.complianceModule.owner(); expect(owner).to.eq(context.accounts.bobWallet.address); diff --git a/test/compliances/module-time-transfer-limits.test.ts b/test/compliances/module-time-transfer-limits.test.ts index f627d5e7..125541bd 100644 --- a/test/compliances/module-time-transfer-limits.test.ts +++ b/test/compliances/module-time-transfer-limits.test.ts @@ -93,8 +93,14 @@ describe('Compliance Module: TimeTransferLimits', () => { const context = await loadFixture(deployTimeTransferLimitsFixture); // when - await context.contracts.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); - + const tx1 = await context.contracts.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + expect(tx1) + .to.emit(context.contracts.complianceModule, 'OwnershipTransferStarted') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); + const tx2 = await context.contracts.complianceModule.connect(context.accounts.bobWallet).acceptOwnership(); + expect(tx2) + .to.emit(context.contracts.complianceModule, 'OwnershipTransferred') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); // then const owner = await context.contracts.complianceModule.owner(); expect(owner).to.eq(context.accounts.bobWallet.address); diff --git a/test/compliances/module-transfer-fees.test.ts b/test/compliances/module-transfer-fees.test.ts index d15087cd..8c157949 100644 --- a/test/compliances/module-transfer-fees.test.ts +++ b/test/compliances/module-transfer-fees.test.ts @@ -58,8 +58,14 @@ describe('Compliance Module: TransferFees', () => { const context = await loadFixture(deployTransferFeesFullSuite); // when - await context.suite.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); - + const tx1 = await context.suite.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + expect(tx1) + .to.emit(context.suite.complianceModule, 'OwnershipTransferStarted') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); + const tx2 = await context.suite.complianceModule.connect(context.accounts.bobWallet).acceptOwnership(); + expect(tx2) + .to.emit(context.suite.complianceModule, 'OwnershipTransferred') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); // then const owner = await context.suite.complianceModule.owner(); expect(owner).to.eq(context.accounts.bobWallet.address); diff --git a/test/compliances/module-transfer-restrict.test.ts b/test/compliances/module-transfer-restrict.test.ts index 4a36e1b5..f0bae22d 100644 --- a/test/compliances/module-transfer-restrict.test.ts +++ b/test/compliances/module-transfer-restrict.test.ts @@ -91,8 +91,14 @@ describe('Compliance Module: TransferRestrict', () => { const context = await loadFixture(deployTransferRestrictFullSuite); // when - await context.suite.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); - + const tx1 = await context.suite.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + expect(tx1) + .to.emit(context.suite.complianceModule, 'OwnershipTransferStarted') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); + const tx2 = await context.suite.complianceModule.connect(context.accounts.bobWallet).acceptOwnership(); + expect(tx2) + .to.emit(context.suite.complianceModule, 'OwnershipTransferred') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); // then const owner = await context.suite.complianceModule.owner(); expect(owner).to.eq(context.accounts.bobWallet.address); diff --git a/test/factory.test.ts b/test/factory.test.ts index a465c1cb..4cd3065b 100644 --- a/test/factory.test.ts +++ b/test/factory.test.ts @@ -471,14 +471,14 @@ describe('TREXFactory', () => { ); const tokenAddress = await getTREXSuiteDeployedTokenAddress(deployTx); - - const tx = await trexFactory.connect(deployer).recoverContractOwnership(tokenAddress, aliceWallet.address); - const token = await ethers.getContractAt('Token', tokenAddress); - await expect(tx).to.emit(token, 'OwnershipTransferred').withArgs(trexFactory.target, aliceWallet.address); + const tx = await trexFactory.connect(deployer).recoverContractOwnership(tokenAddress, aliceWallet.address); + expect(tx).to.emit(token, 'OwnershipTransferStarted').withArgs(trexFactory.target, aliceWallet.address); + const tx2 = await token.connect(aliceWallet).acceptOwnership(); + expect(tx2).to.emit(token, 'OwnershipTransferStarted').withArgs(trexFactory.target, aliceWallet.address); - await expect(token.owner()).to.eventually.eq(aliceWallet.address); + expect(await token.owner()).to.eq(aliceWallet.address); }); }); }); From 68269bda17d6b47eb0602d91a61826e939fe0d2c Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Tue, 15 Oct 2024 10:10:17 +0200 Subject: [PATCH 39/55] =?UTF-8?q?=F0=9F=94=A7()=20BT-7=20Update=20solidity?= =?UTF-8?q?=20and=20ethers=20versions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TokenListingRestrictionsModule.sol | 103 ++++--- .../module-token-listing-restrictions.test.ts | 258 +++++++++--------- 2 files changed, 193 insertions(+), 168 deletions(-) diff --git a/contracts/compliance/modular/modules/TokenListingRestrictionsModule.sol b/contracts/compliance/modular/modules/TokenListingRestrictionsModule.sol index b2255aea..86561cb5 100644 --- a/contracts/compliance/modular/modules/TokenListingRestrictionsModule.sol +++ b/contracts/compliance/modular/modules/TokenListingRestrictionsModule.sol @@ -60,68 +60,81 @@ * along with this program. If not, see . */ -pragma solidity 0.8.17; +pragma solidity 0.8.27; import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; import "./AbstractModuleUpgradeable.sol"; -contract TokenListingRestrictionsModule is AbstractModuleUpgradeable { - enum ListingType { - NOT_CONFIGURED, // default value (token is not configured yet) - WHITELISTING, - BLACKLISTING - } +/// Types - enum InvestorAddressType { - WALLET, - ONCHAINID - } +enum ListingType { + NOT_CONFIGURED, // default value (token is not configured yet) + WHITELISTING, + BLACKLISTING +} - /// Mapping between token and listing type - mapping(address => ListingType) private _tokenListingType; +enum InvestorAddressType { + WALLET, + ONCHAINID +} - /// Mapping between tokenAddress and investor (wallet or OID address) - /// and listing status (whitelisted or blacklisted depending on the listing type of the token) - mapping(address => mapping(address => bool)) private _tokenInvestorListingStatus; - /// events - /** - * this event is emitted whenever a token is configured with a non-zero listing type - * the event is emitted by 'configureToken'. - * _tokenAddress is the address of the configured token - * _listingType is the configured listing type for the token (1: WHITELISTING, 2: BLACKLISTING) - */ - event TokenListingConfigured(address _tokenAddress, ListingType _listingType); +/// events - /** - * this event is emitted whenever a token is listed (whitelisted or blacklisted) for an investor - * the event is emitted by 'listToken'. - * _tokenAddress is the address of the listed token - * _investorAddress is the investor address (a wallet or an ONCHAINID address) - */ - event TokenListed(address _tokenAddress, address _investorAddress); +/// @dev This event is emitted whenever a token is configured with a non-zero listing type +/// @param _tokenAddress the address of the configured token +/// @param _listingType the configured listing type for the token (1: WHITELISTING, 2: BLACKLISTING) +event TokenListingConfigured(address _tokenAddress, ListingType _listingType); - /** - * this event is emitted whenever a token is unlisted for an investor - * the event is emitted by 'unlistToken'. - * _tokenAddress is the address of the unlisted token - * _investorAddress is the investor address (a wallet or an ONCHAINID address) - */ - event TokenUnlisted(address _tokenAddress, address _investorAddress); +/// @dev This event is emitted whenever a token is listed (whitelisted or blacklisted) for an investor +/// @param _tokenAddress the address of the listed token +/// @param _investorAddress the investor address (a wallet or an ONCHAINID address) +event TokenListed(address _tokenAddress, address _investorAddress); + +/// @dev This event is emitted whenever a token is unlisted for an investor +/// @param _tokenAddress the address of the unlisted token +/// @param _investorAddress the investor address (a wallet or an ONCHAINID address) +event TokenUnlisted(address _tokenAddress, address _investorAddress); + +/// Errors + +/// @dev Thrown when the token is already configured +/// @param _tokenAddress the address of the token +error TokenAlreadyConfigured(address _tokenAddress); + +/// @dev Thrown when the token is not configured +/// @param _tokenAddress the address of the token +error TokenIsNotConfigured(address _tokenAddress); - /// Custom Errors - error TokenAlreadyConfigured(address _tokenAddress); +/// @dev Thrown when the token is already listed for the investor +/// @param _tokenAddress the address of the token +/// @param _investorAddress the investor address (a wallet or an ONCHAINID address) +error TokenAlreadyListed(address _tokenAddress, address _investorAddress); - error TokenIsNotConfigured(address _tokenAddress); +/// @dev Thrown when the token is not listed for the investor +/// @param _tokenAddress the address of the token +/// @param _investorAddress the investor address (a wallet or an ONCHAINID address) +error TokenIsNotListed(address _tokenAddress, address _investorAddress); - error TokenAlreadyListed(address _tokenAddress, address _investorAddress); +/// @dev Thrown when the identity is not found +/// @param _tokenAddress the address of the token +/// @param _userAddress the user address (a wallet or an ONCHAINID address) +error IdentityNotFound(address _tokenAddress, address _userAddress); - error TokenIsNotListed(address _tokenAddress, address _investorAddress); +/// @dev Thrown when the listing type is invalid for configuration +/// @param _listingType the listing type +error InvalidListingTypeForConfiguration(ListingType _listingType); - error IdentityNotFound(address _tokenAddress, address _userAddress); - error InvalidListingTypeForConfiguration(ListingType _listingType); +contract TokenListingRestrictionsModule is AbstractModuleUpgradeable { + + /// Mapping between token and listing type + mapping(address token => ListingType) private _tokenListingType; + + /// Mapping between tokenAddress and investor (wallet or OID address) + /// and listing status (whitelisted or blacklisted depending on the listing type of the token) + mapping(address token => mapping(address investor => bool)) private _tokenInvestorListingStatus; /// functions /** diff --git a/test/compliances/module-token-listing-restrictions.test.ts b/test/compliances/module-token-listing-restrictions.test.ts index 5ba6049a..ad615a68 100644 --- a/test/compliances/module-token-listing-restrictions.test.ts +++ b/test/compliances/module-token-listing-restrictions.test.ts @@ -7,11 +7,11 @@ import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; async function deployTokenListingRestrictionsFullSuite() { const context = await loadFixture(deploySuiteWithModularCompliancesFixture); const module = await ethers.deployContract('TokenListingRestrictionsModule'); - const proxy = await ethers.deployContract('ModuleProxy', [module.address, module.interface.encodeFunctionData('initialize')]); - const complianceModule = await ethers.getContractAt('TokenListingRestrictionsModule', proxy.address); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('TokenListingRestrictionsModule', proxy.target); - await context.suite.compliance.bindToken(context.suite.token.address); - await context.suite.compliance.addModule(complianceModule.address); + await context.suite.compliance.bindToken(context.suite.token.target); + await context.suite.compliance.addModule(complianceModule.target); return { ...context, @@ -26,8 +26,8 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should deploy the TokenListingRestrictions contract and bind it to the compliance', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); - expect(context.suite.complianceModule.address).not.to.be.undefined; - expect(await context.suite.compliance.isModuleBound(context.suite.complianceModule.address)).to.be.true; + expect(context.suite.complianceModule.target).not.to.be.undefined; + expect(await context.suite.compliance.isModuleBound(context.suite.complianceModule.target)).to.be.true; }); describe('.name', () => { @@ -49,7 +49,7 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should return true', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); const complianceModule = await ethers.deployContract('TokenListingRestrictionsModule'); - expect(await complianceModule.canComplianceBind(context.suite.compliance.address)).to.be.true; + expect(await complianceModule.canComplianceBind(context.suite.compliance.target)).to.be.true; }); }); @@ -91,7 +91,14 @@ describe('Compliance Module: TokenListingRestrictions', () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); // when - await context.suite.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + const tx1 = await context.suite.complianceModule.connect(context.accounts.deployer).transferOwnership(context.accounts.bobWallet.address); + expect(tx1) + .to.emit(context.suite.complianceModule, 'OwnershipTransferStarted') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); + const tx2 = await context.suite.complianceModule.connect(context.accounts.bobWallet).acceptOwnership(); + expect(tx2) + .to.emit(context.suite.complianceModule, 'OwnershipTransferred') + .withArgs(context.accounts.deployer.address, context.accounts.bobWallet.address); // then const owner = await context.suite.complianceModule.owner(); @@ -104,7 +111,7 @@ describe('Compliance Module: TokenListingRestrictions', () => { describe('when calling directly', () => { it('should revert', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); - await expect(context.suite.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.constants.AddressZero)).to.revertedWith( + await expect(context.suite.complianceModule.connect(context.accounts.aliceWallet).upgradeTo(ethers.ZeroAddress)).to.revertedWith( 'Ownable: caller is not the owner', ); }); @@ -117,11 +124,11 @@ describe('Compliance Module: TokenListingRestrictions', () => { const newImplementation = await ethers.deployContract('TokenListingRestrictionsModule'); // when - await context.suite.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.address); + await context.suite.complianceModule.connect(context.accounts.deployer).upgradeTo(newImplementation.target); // then - const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.complianceModule.address); - expect(implementationAddress).to.eq(newImplementation.address); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(context.suite.complianceModule.target); + expect(implementationAddress).to.eq(newImplementation.target); }); }); }); @@ -130,7 +137,10 @@ describe('Compliance Module: TokenListingRestrictions', () => { describe('when calling directly', () => { it('should revert', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); - await expect(context.suite.complianceModule.configureToken(1)).to.revertedWith('only bound compliance can call'); + await expect(context.suite.complianceModule.configureToken(1)).to.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', + ); }); }); @@ -140,8 +150,8 @@ describe('Compliance Module: TokenListingRestrictions', () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [0]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [0]), + context.suite.complianceModule.target, ), ).to.be.revertedWithCustomError(context.suite.complianceModule, `InvalidListingTypeForConfiguration`); }); @@ -151,14 +161,14 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should revert', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [2]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [2]), + context.suite.complianceModule.target, ), ).to.be.revertedWithCustomError(context.suite.complianceModule, `TokenAlreadyConfigured`); }); @@ -169,11 +179,11 @@ describe('Compliance Module: TokenListingRestrictions', () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); const tx = await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); - await expect(tx).to.emit(context.suite.complianceModule, 'TokenListingConfigured').withArgs(context.suite.token.address, 1); + await expect(tx).to.emit(context.suite.complianceModule, 'TokenListingConfigured').withArgs(context.suite.token.target, 1); }); }); }); @@ -184,7 +194,7 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should revert', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await expect( - context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1), + context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.target, 1), ).to.be.revertedWithCustomError(context.suite.complianceModule, `TokenIsNotConfigured`); }); }); @@ -194,14 +204,14 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should revert', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); - await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1); + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.target, 1); await expect( - context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1), + context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.target, 1), ).to.be.revertedWithCustomError(context.suite.complianceModule, `TokenAlreadyListed`); }); }); @@ -211,15 +221,15 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should list the token', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); - const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 0); + const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.target, 0); await expect(tx) .to.emit(context.suite.complianceModule, 'TokenListed') - .withArgs(context.suite.token.address, context.accounts.aliceWallet.address); + .withArgs(context.suite.token.target, context.accounts.aliceWallet.address); }); }); @@ -228,12 +238,12 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should revert', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); await expect( - context.suite.complianceModule.connect(context.accounts.anotherWallet).listToken(context.suite.token.address, 1), + context.suite.complianceModule.connect(context.accounts.anotherWallet).listToken(context.suite.token.target, 1), ).to.be.revertedWithCustomError(context.suite.complianceModule, `IdentityNotFound`); }); }); @@ -242,15 +252,15 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should list the token', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); - const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1); + const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.target, 1); await expect(tx) .to.emit(context.suite.complianceModule, 'TokenListed') - .withArgs(context.suite.token.address, context.identities.aliceIdentity.address); + .withArgs(context.suite.token.target, context.identities.aliceIdentity.target); }); }); }); @@ -263,7 +273,7 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should revert', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await expect( - context.suite.complianceModule.connect(context.accounts.aliceWallet).batchListTokens([context.suite.token.address], 1), + context.suite.complianceModule.connect(context.accounts.aliceWallet).batchListTokens([context.suite.token.target], 1), ).to.be.revertedWithCustomError(context.suite.complianceModule, `TokenIsNotConfigured`); }); }); @@ -273,14 +283,14 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should revert', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); - await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1); + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.target, 1); await expect( - context.suite.complianceModule.connect(context.accounts.aliceWallet).batchListTokens([context.suite.token.address], 1), + context.suite.complianceModule.connect(context.accounts.aliceWallet).batchListTokens([context.suite.token.target], 1), ).to.be.revertedWithCustomError(context.suite.complianceModule, `TokenAlreadyListed`); }); }); @@ -290,15 +300,15 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should list tokens', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); - const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).batchListTokens([context.suite.token.address], 0); + const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).batchListTokens([context.suite.token.target], 0); await expect(tx) .to.emit(context.suite.complianceModule, 'TokenListed') - .withArgs(context.suite.token.address, context.accounts.aliceWallet.address); + .withArgs(context.suite.token.target, context.accounts.aliceWallet.address); }); }); @@ -306,15 +316,15 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should list tokens', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); - const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).batchListTokens([context.suite.token.address], 1); + const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).batchListTokens([context.suite.token.target], 1); await expect(tx) .to.emit(context.suite.complianceModule, 'TokenListed') - .withArgs(context.suite.token.address, context.identities.aliceIdentity.address); + .withArgs(context.suite.token.target, context.identities.aliceIdentity.target); }); }); }); @@ -326,12 +336,12 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should revert', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); await expect( - context.suite.complianceModule.connect(context.accounts.aliceWallet).unlistToken(context.suite.token.address, 1), + context.suite.complianceModule.connect(context.accounts.aliceWallet).unlistToken(context.suite.token.target, 1), ).to.be.revertedWithCustomError(context.suite.complianceModule, `TokenIsNotListed`); }); }); @@ -341,17 +351,17 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should unlist the token', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); - await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 0); + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.target, 0); - const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).unlistToken(context.suite.token.address, 0); + const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).unlistToken(context.suite.token.target, 0); await expect(tx) .to.emit(context.suite.complianceModule, 'TokenUnlisted') - .withArgs(context.suite.token.address, context.accounts.aliceWallet.address); + .withArgs(context.suite.token.target, context.accounts.aliceWallet.address); }); }); @@ -359,17 +369,17 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should unlist the token', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); - await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1); + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.target, 1); - const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).unlistToken(context.suite.token.address, 1); + const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).unlistToken(context.suite.token.target, 1); await expect(tx) .to.emit(context.suite.complianceModule, 'TokenUnlisted') - .withArgs(context.suite.token.address, context.identities.aliceIdentity.address); + .withArgs(context.suite.token.target, context.identities.aliceIdentity.target); }); }); }); @@ -380,12 +390,12 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should revert', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); await expect( - context.suite.complianceModule.connect(context.accounts.aliceWallet).batchUnlistTokens([context.suite.token.address], 1), + context.suite.complianceModule.connect(context.accounts.aliceWallet).batchUnlistTokens([context.suite.token.target], 1), ).to.be.revertedWithCustomError(context.suite.complianceModule, `TokenIsNotListed`); }); }); @@ -395,17 +405,17 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should unlist tokens', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); - await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 0); + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.target, 0); - const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).batchUnlistTokens([context.suite.token.address], 0); + const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).batchUnlistTokens([context.suite.token.target], 0); await expect(tx) .to.emit(context.suite.complianceModule, 'TokenUnlisted') - .withArgs(context.suite.token.address, context.accounts.aliceWallet.address); + .withArgs(context.suite.token.target, context.accounts.aliceWallet.address); }); }); @@ -413,17 +423,17 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should unlist tokens', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); - await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1); + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.target, 1); - const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).batchUnlistTokens([context.suite.token.address], 1); + const tx = await context.suite.complianceModule.connect(context.accounts.aliceWallet).batchUnlistTokens([context.suite.token.target], 1); await expect(tx) .to.emit(context.suite.complianceModule, 'TokenUnlisted') - .withArgs(context.suite.token.address, context.identities.aliceIdentity.address); + .withArgs(context.suite.token.target, context.identities.aliceIdentity.target); }); }); }); @@ -433,7 +443,7 @@ describe('Compliance Module: TokenListingRestrictions', () => { describe('when token is not configured', () => { it('should return NOT_CONFIGURED(0)', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); - const result = await context.suite.complianceModule.getTokenListingType(context.suite.token.address); + const result = await context.suite.complianceModule.getTokenListingType(context.suite.token.target); expect(result).to.be.eq(0); }); }); @@ -443,11 +453,11 @@ describe('Compliance Module: TokenListingRestrictions', () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); - const result = await context.suite.complianceModule.getTokenListingType(context.suite.token.address); + const result = await context.suite.complianceModule.getTokenListingType(context.suite.token.target); expect(result).to.be.eq(1); }); }); @@ -458,7 +468,7 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should return false', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); const result = await context.suite.complianceModule.getInvestorListingStatus( - context.suite.token.address, + context.suite.token.target, context.accounts.aliceWallet.address, ); expect(result).to.be.false; @@ -470,14 +480,14 @@ describe('Compliance Module: TokenListingRestrictions', () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); - await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 0); + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.target, 0); const result = await context.suite.complianceModule.getInvestorListingStatus( - context.suite.token.address, + context.suite.token.target, context.accounts.aliceWallet.address, ); expect(result).to.be.true; @@ -492,11 +502,11 @@ describe('Compliance Module: TokenListingRestrictions', () => { const from = context.accounts.aliceWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); - const result = await context.suite.complianceModule.moduleCheck(from, ethers.constants.AddressZero, 10, context.suite.compliance.address); + const result = await context.suite.complianceModule.moduleCheck(from, ethers.ZeroAddress, 10, context.suite.compliance.target); expect(result).to.be.true; }); }); @@ -506,7 +516,7 @@ describe('Compliance Module: TokenListingRestrictions', () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); const from = context.accounts.aliceWallet.address; const to = context.accounts.bobWallet.address; - const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.target); expect(result).to.be.true; }); }); @@ -519,11 +529,11 @@ describe('Compliance Module: TokenListingRestrictions', () => { const from = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); - const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.target); expect(result).to.be.false; }); }); @@ -535,13 +545,13 @@ describe('Compliance Module: TokenListingRestrictions', () => { const from = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); - await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 0); + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.target, 0); - const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.target); expect(result).to.be.true; }); }); @@ -553,13 +563,13 @@ describe('Compliance Module: TokenListingRestrictions', () => { const from = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [1]), + context.suite.complianceModule.target, ); - await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1); + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.target, 1); - const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.target); expect(result).to.be.true; }); }); @@ -573,11 +583,11 @@ describe('Compliance Module: TokenListingRestrictions', () => { const from = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [2]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [2]), + context.suite.complianceModule.target, ); - const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.target); expect(result).to.be.true; }); }); @@ -589,13 +599,13 @@ describe('Compliance Module: TokenListingRestrictions', () => { const from = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [2]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [2]), + context.suite.complianceModule.target, ); - await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 0); + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.target, 0); - const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.target); expect(result).to.be.false; }); }); @@ -607,13 +617,13 @@ describe('Compliance Module: TokenListingRestrictions', () => { const from = context.accounts.bobWallet.address; await context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [2]), - context.suite.complianceModule.address, + new ethers.Interface(['function configureToken(uint8 _listingType)']).encodeFunctionData('configureToken', [2]), + context.suite.complianceModule.target, ); - await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.address, 1); + await context.suite.complianceModule.connect(context.accounts.aliceWallet).listToken(context.suite.token.target, 1); - const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.address); + const result = await context.suite.complianceModule.moduleCheck(from, to, 10, context.suite.compliance.target); expect(result).to.be.false; }); }); @@ -625,8 +635,9 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should revert', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); - await expect(context.suite.complianceModule.moduleMintAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWith( - 'only bound compliance can call', + await expect(context.suite.complianceModule.moduleMintAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -637,11 +648,11 @@ describe('Compliance Module: TokenListingRestrictions', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ + new ethers.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [ context.accounts.anotherWallet.address, 10, ]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ), ).to.eventually.be.fulfilled; }); @@ -653,8 +664,9 @@ describe('Compliance Module: TokenListingRestrictions', () => { it('should revert', async () => { const context = await loadFixture(deployTokenListingRestrictionsFullSuite); - await expect(context.suite.complianceModule.moduleBurnAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWith( - 'only bound compliance can call', + await expect(context.suite.complianceModule.moduleBurnAction(context.accounts.anotherWallet.address, 10)).to.be.revertedWithCustomError( + context.suite.complianceModule, + 'OnlyBoundComplianceCanCall', ); }); }); @@ -665,11 +677,11 @@ describe('Compliance Module: TokenListingRestrictions', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ + new ethers.Interface(['function moduleBurnAction(address, uint256)']).encodeFunctionData('moduleBurnAction', [ context.accounts.anotherWallet.address, 10, ]), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ), ).to.eventually.be.fulfilled; }); @@ -683,7 +695,7 @@ describe('Compliance Module: TokenListingRestrictions', () => { await expect( context.suite.complianceModule.moduleTransferAction(context.accounts.aliceWallet.address, context.accounts.anotherWallet.address, 10), - ).to.be.revertedWith('only bound compliance can call'); + ).to.be.revertedWithCustomError(context.suite.complianceModule, 'OnlyBoundComplianceCanCall'); }); }); @@ -693,11 +705,11 @@ describe('Compliance Module: TokenListingRestrictions', () => { await expect( context.suite.compliance.callModuleFunction( - new ethers.utils.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( + new ethers.Interface(['function moduleTransferAction(address _from, address _to, uint256 _value)']).encodeFunctionData( 'moduleTransferAction', [context.accounts.aliceWallet.address, context.accounts.anotherWallet.address, 80], ), - context.suite.complianceModule.address, + context.suite.complianceModule.target, ), ).to.eventually.be.fulfilled; }); From fb7f47c4affaf61d3ad032bde4021958e47dcb98 Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Tue, 15 Oct 2024 10:20:47 +0200 Subject: [PATCH 40/55] =?UTF-8?q?=F0=9F=94=80()=20BT-7=20Fix=20changelog?= =?UTF-8?q?=20merge=20issue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 99 +--------------------------------------------------- 1 file changed, 1 insertion(+), 98 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a58de89..b754593c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -90,103 +90,6 @@ All notable changes to this project will be documented in this file. - The DvA manager contract freezes the tokens to be transferred instead of being a vault (so it must be a token agent) - Only the token owner (rather than agents) can call setApprovalCriteria, as it is part of the main token settings. -## [4.2.0] - -### Added - -- Introduced **Token Listing Restrictions Module**: Investors can determine which tokens they can receive by whitelisting or blacklisting them - Token issuers can choose the listing type they prefer for their tokens: - WHITELISTING: investors must whitelist/allow the token address in order to receive it. - BLACKLISTING: investors can receive the token by default. If they do not want to receive it, they need to blacklist/disallow it. - -- **Default Allowance Mechanism**: - - Introduced a new feature allowing the contract owner to set certain addresses as trusted external smart contracts, enabling them to use `transferFrom` without requiring an explicit allowance from users. By default, users are opted in, allowing these contracts to have an "infinite allowance". Users can opt-out if they prefer to control allowances manually. - - Added custom errors and events to provide better feedback and traceability: - - Custom errors: `DefaultAllowanceAlreadyEnabled`, `DefaultAllowanceAlreadyDisabled`, `DefaultAllowanceAlreadySet`. - - Events: `DefaultAllowance`, `DefaultAllowanceDisabled`, `DefaultAllowanceEnabled`. - - Enhanced the `allowance` function to return `type(uint256).max` for addresses with default allowance enabled, unless the user has opted out. - -- **Eligibility Checks Toggle**: - - Added the ability for the token owner to enable or disable eligibility checks on the `IdentityRegistry` contract. - - **`disableEligibilityChecks`**: Allows the token owner to disable eligibility checks, making all addresses automatically verified by the `isVerified` function. - - **`enableEligibilityChecks`**: Allows the token owner to re-enable eligibility checks, restoring the full verification process. - - Introduced custom errors and events: - - Custom errors: `EligibilityChecksDisabledAlready`, `EligibilityChecksEnabledAlready`. - - Events: `EligibilityChecksDisabled`, `EligibilityChecksEnabled`. - - This feature provides flexibility for issuers to launch tokens with or without eligibility checks, based on their needs. - -- **ERC-165 Interface Implementation**: - - Implemented ERC-165 support across all major contracts in the suite, allowing them to explicitly declare the interfaces they support. This enhancement improves interoperability and makes it easier for external contracts and tools to interact with T-REX contracts. - - Each contract now implements the `supportsInterface` function to identify the supported interfaces, ensuring compliance with ERC-165 standards. - - In addition to implementing ERC-165, the ERC-3643 interfaces were organized into a new directory, with each interface inheriting from the original ERC-3643 standard interface. This setup allows for future expansion and maintains uniformity across the suite: - - `IERC3643`, `IERC3643IdentityRegistry`, `IERC3643Compliance`, `IERC3643ClaimTopicsRegistry`, `IERC3643TrustedIssuersRegistry`, `IERC3643IdentityRegistryStorage` - - For contracts that extend the ERC-3643 standard with new functions, `supportsInterface` now checks for both the new interface ID and the original ERC-3643 interface ID. - - For interfaces that did not change, `supportsInterface` checks for the ERC-3643 interface ID directly, omitting the empty version-specific interface to avoid redundancy. - -- **Add and Set Module in a Single Transaction**: - - Introduced the `addAndSetModule` function in the `ModularCompliance` contract, allowing the contract owner to add a new compliance module and interact with it in a single transaction. - - This function supports adding a module and performing up to 5 interactions with the module in one call, streamlining the setup process for compliance modules. - -- **Granular Agent Permissioning**: - - Introduced a new system to provide more granular control over agent roles on the token contract. - - **Default Behavior**: By default, agents can perform all actions (mint, burn, freeze tokens, freeze wallets, recover tokens, pause, unpause). - - **Restricting Permissions**: Token owners can now restrict specific roles for agents using the `setAgentRestrictions` function. - - Permissions can be restricted on actions like minting, burning, freezing, recovering, etc. - - Custom restrictions are stored in the `TokenRoles` struct. - - The `AgentRestrictionsSet` event is emitted whenever restrictions are updated for an agent. - - All agent-scoped functions (e.g., mint, burn) now check the agent’s permissions before executing the transaction, ensuring proper enforcement of these restrictions. - -- **Ethers.js Version Upgrade**: - - The project was upgraded from **Ethers v5** to **Ethers v6**, introducing several changes to the API and syntax. - - **Key Changes**: - - Adjusted syntax for contract deployments, interactions, and function calls to comply with Ethers v6. - - Replaced deprecated features from v5 with the new Ethers v6 equivalents, ensuring compatibility and future-proofing the project. - - Updated test suites and helper functions to use the Ethers v6 `Interface` and `Contract` classes, ensuring smooth testing of the updated code. - - This upgrade ensures better performance, enhanced security, and improved developer experience moving forward. - -- **Solidity Version Upgrade to 0.8.27**: - - Upgraded Solidity version from **0.8.17** to **0.8.27** across all contracts, bringing in multiple new features and improvements: - - **File-Level Event Declaration**: Events are now declared at the file level, simplifying code structure and improving readability. - - **Custom Errors for Require Statements**: All `require` clauses that previously returned a string reason for failure have been updated to use **custom errors**, making debugging easier and more efficient. - - This upgrade provides a cleaner, more efficient error handling process and improves overall code structure without affecting backward compatibility. - -### Updated - -- **Token Recovery Function**: - - The `recoveryAddress` function was significantly improved to handle more complex scenarios and prevent potential bugs: - - Removed the requirement for the `newWallet` to be a key on the `onchainID`, simplifying the process and reducing potential errors. - - Enhanced compatibility with shared identity registry storage, ensuring the function works correctly even when multiple tokens share the same identity registry storage. - - Added logic to handle recovery to an existing wallet that is already linked to the investor's identity, addressing scenarios where the `newWallet` is an existing wallet. - - The function now accurately updates the identity registry, preventing errors related to attempting to add or remove identities that are already present or absent. - - Improved overall logic to ensure smooth and error-free recovery operations, with events (`RecoverySuccess`, `TokensFrozen`, `TokensUnfrozen`, etc.) emitted to provide detailed feedback. - -- **Ownership Transfer**: - - Implemented a two-step ownership transfer process across all relevant contracts in the suite, using OpenZeppelin's implementation `Ownable2StepUpgradeable`. - - This change enhances security by requiring the new owner to accept ownership explicitly, preventing accidental transfers to incorrect or inaccessible addresses. - - Added new functions: - - `transferOwnership(address newOwner)`: Initiates the ownership transfer process. - - `acceptOwnership()`: Allows the pending owner to accept and finalize the ownership transfer. - - Introduced a `_pendingOwner` state variable to track the address of the pending new owner. - - Updated relevant events to reflect the two-step process: - - `OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner)` - - `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)` - - This change affects all contracts that previously used a single-step ownership transfer, ensuring consistent and secure ownership management across the entire suite. - -## [4.1.5] - -### Update -- DvA Transfer Manager contract proxified -- The DvA manager contract freezes the tokens to be transferred instead of being a vault (so it must be a token agent) -- Only the token owner (rather than agents) can call setApprovalCriteria, as it is part of the main token settings. - -## [4.1.5] - -### Added -- Introduced **Token Listing Restrictions Module**: Investors can determine which tokens they can receive by whitelisting or blacklisting them - Token issuers can choose the listing type they prefer for their tokens: - WHITELISTING: investors must whitelist/allow the token address in order to receive it. - BLACKLISTING: investors can receive the token by default. If they do not want to receive it, they need to blacklist/disallow it. - ## [4.1.4] ### Added @@ -396,4 +299,4 @@ Version 4.0.0 of TREX has been successfully audited by Hacken [more details here - changed required key for roles on AgentManager contract (MANAGEMENT key -> EXECUTION key) - changed required key for roles on OwnerManager contract (MANAGEMENT key -> EXECUTION key) - import interfaces from openzeppelin instead of local copy -- contract name : **Storage** -> **TokenStorage** +- contract name : **Storage** -> **TokenStorage** \ No newline at end of file From 222e30857048e6dd84531c2f8c82a2f7f2778d1a Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Wed, 16 Oct 2024 12:31:37 +0200 Subject: [PATCH 41/55] =?UTF-8?q?=E2=99=BB()=20Deduplication=20of=20batche?= =?UTF-8?q?s=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TokenListingRestrictionsModule.sol | 112 +++++++----------- 1 file changed, 43 insertions(+), 69 deletions(-) diff --git a/contracts/compliance/modular/modules/TokenListingRestrictionsModule.sol b/contracts/compliance/modular/modules/TokenListingRestrictionsModule.sol index 86561cb5..f3f6b85a 100644 --- a/contracts/compliance/modular/modules/TokenListingRestrictionsModule.sol +++ b/contracts/compliance/modular/modules/TokenListingRestrictionsModule.sol @@ -168,30 +168,6 @@ contract TokenListingRestrictionsModule is AbstractModuleUpgradeable { emit TokenListingConfigured(tokenAddress, _listingType); } - /** - * @dev Lists a token for the investor (caller) - * If the token listing type is WHITELISTING, it will be whitelisted/allowed for the investor. - * If the token listing type is BLACKLISTING, it will be blaclisted/disallowed for the investor. - * @param _tokenAddress is the address of the token to be listed - * @param _addressType can be WALLET(0) or ONCHAINID(1) - * If it is WALLET, the token will be listed only for the caller wallet address - * If it is ONCHAINID, the token will be listed for the ONCHAINID (it will be applied to all wallet addresses of the OID) - * It will revert if the listing type of the token is not configured - */ - function listToken(address _tokenAddress, InvestorAddressType _addressType) external { - if (_tokenListingType[_tokenAddress] == ListingType.NOT_CONFIGURED) { - revert TokenIsNotConfigured(_tokenAddress); - } - - address investorAddress = _getInvestorAddressByAddressType(_tokenAddress, msg.sender, _addressType); - if (_tokenInvestorListingStatus[_tokenAddress][investorAddress]) { - revert TokenAlreadyListed(_tokenAddress, investorAddress); - } - - _tokenInvestorListingStatus[_tokenAddress][investorAddress] = true; - emit TokenListed(_tokenAddress, investorAddress); - } - /** * @dev Lists multiple tokens for the investor (caller) * If the token listing type is WHITELISTING, it will be whitelisted/allowed for the investor. @@ -203,43 +179,11 @@ contract TokenListingRestrictionsModule is AbstractModuleUpgradeable { * It will revert if the listing type of the token is not configured */ function batchListTokens(address[] calldata _tokenAddresses, InvestorAddressType _addressType) external { - address investorAddress = msg.sender; for (uint256 i = 0; i < _tokenAddresses.length; i++) { - address tokenAddress = _tokenAddresses[i]; - if (_tokenListingType[tokenAddress] == ListingType.NOT_CONFIGURED) { - revert TokenIsNotConfigured(tokenAddress); - } - - if (_addressType != InvestorAddressType.WALLET) { - investorAddress = _getInvestorAddressByAddressType(tokenAddress, msg.sender, _addressType); - } - - if (_tokenInvestorListingStatus[tokenAddress][investorAddress]) { - revert TokenAlreadyListed(tokenAddress, investorAddress); - } - - _tokenInvestorListingStatus[tokenAddress][investorAddress] = true; - emit TokenListed(tokenAddress, investorAddress); + listToken(_tokenAddresses[i], _addressType); } } - /** - * @dev Unlists a token for the investor (caller) - * @param _tokenAddress is the address of the token to be unlisted - * @param _addressType can be WALLET(0) or ONCHAINID(1) - * If it is WALLET, the token will be unlisted only for the caller wallet address - * If it is ONCHAINID, the token will be unlisted for the ONCHAINID - */ - function unlistToken(address _tokenAddress, InvestorAddressType _addressType) external { - address investorAddress = _getInvestorAddressByAddressType(_tokenAddress, msg.sender, _addressType); - if (!_tokenInvestorListingStatus[_tokenAddress][investorAddress]) { - revert TokenIsNotListed(_tokenAddress, investorAddress); - } - - _tokenInvestorListingStatus[_tokenAddress][investorAddress] = false; - emit TokenUnlisted(_tokenAddress, investorAddress); - } - /** * @dev Unlists multiple tokens for the investor (caller) * @param _tokenAddresses is the array of addresses of tokens to be unlisted @@ -248,19 +192,8 @@ contract TokenListingRestrictionsModule is AbstractModuleUpgradeable { * If it is ONCHAINID, the token will be unlisted for the ONCHAINID */ function batchUnlistTokens(address[] calldata _tokenAddresses, InvestorAddressType _addressType) external { - address investorAddress = msg.sender; for (uint256 i = 0; i < _tokenAddresses.length; i++) { - address tokenAddress = _tokenAddresses[i]; - if (_addressType != InvestorAddressType.WALLET) { - investorAddress = _getInvestorAddressByAddressType(tokenAddress, msg.sender, _addressType); - } - - if (!_tokenInvestorListingStatus[tokenAddress][investorAddress]) { - revert TokenIsNotListed(tokenAddress, investorAddress); - } - - _tokenInvestorListingStatus[tokenAddress][investorAddress] = false; - emit TokenUnlisted(tokenAddress, investorAddress); + unlistToken(_tokenAddresses[i], _addressType); } } @@ -360,6 +293,47 @@ contract TokenListingRestrictionsModule is AbstractModuleUpgradeable { return true; } + /** + * @dev Lists a token for the investor (caller) + * If the token listing type is WHITELISTING, it will be whitelisted/allowed for the investor. + * If the token listing type is BLACKLISTING, it will be blaclisted/disallowed for the investor. + * @param _tokenAddress is the address of the token to be listed + * @param _addressType can be WALLET(0) or ONCHAINID(1) + * If it is WALLET, the token will be listed only for the caller wallet address + * If it is ONCHAINID, the token will be listed for the ONCHAINID (it will be applied to all wallet addresses of the OID) + * It will revert if the listing type of the token is not configured + */ + function listToken(address _tokenAddress, InvestorAddressType _addressType) public { + if (_tokenListingType[_tokenAddress] == ListingType.NOT_CONFIGURED) { + revert TokenIsNotConfigured(_tokenAddress); + } + + address investorAddress = _getInvestorAddressByAddressType(_tokenAddress, msg.sender, _addressType); + if (_tokenInvestorListingStatus[_tokenAddress][investorAddress]) { + revert TokenAlreadyListed(_tokenAddress, investorAddress); + } + + _tokenInvestorListingStatus[_tokenAddress][investorAddress] = true; + emit TokenListed(_tokenAddress, investorAddress); + } + + /** + * @dev Unlists a token for the investor (caller) + * @param _tokenAddress is the address of the token to be unlisted + * @param _addressType can be WALLET(0) or ONCHAINID(1) + * If it is WALLET, the token will be unlisted only for the caller wallet address + * If it is ONCHAINID, the token will be unlisted for the ONCHAINID + */ + function unlistToken(address _tokenAddress, InvestorAddressType _addressType) public { + address investorAddress = _getInvestorAddressByAddressType(_tokenAddress, msg.sender, _addressType); + if (!_tokenInvestorListingStatus[_tokenAddress][investorAddress]) { + revert TokenIsNotListed(_tokenAddress, investorAddress); + } + + _tokenInvestorListingStatus[_tokenAddress][investorAddress] = false; + emit TokenUnlisted(_tokenAddress, investorAddress); + } + /** * @dev See {IModule-name}. */ From badb68e5123376af26cb04f6cfd16273fd5e7edb Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Fri, 18 Oct 2024 10:47:57 +0200 Subject: [PATCH 42/55] =?UTF-8?q?=E2=9C=A8()=20Eligibility=20and=20complia?= =?UTF-8?q?nce=20checker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/_testContracts/MockContract.sol | 9 + contracts/utilities/IUtilityChecker.sol | 129 +++++ contracts/utilities/UtilityChecker.sol | 185 +++++++ contracts/utilities/UtilityCheckerProxy.sol | 72 +++ hardhat.config.ts | 2 +- package-lock.json | 567 +++++++++++++------- package.json | 3 - test/utilities/compliance-check.test.ts | 93 ++++ test/utilities/eligibility-check.test.ts | 114 ++++ test/utilities/freeze-check.test.ts | 72 +++ test/utilities/transfer-check.test.ts | 160 ++++++ test/utilities/upgrade.test.ts | 35 ++ 12 files changed, 1243 insertions(+), 198 deletions(-) create mode 100644 contracts/utilities/IUtilityChecker.sol create mode 100644 contracts/utilities/UtilityChecker.sol create mode 100644 contracts/utilities/UtilityCheckerProxy.sol create mode 100644 test/utilities/compliance-check.test.ts create mode 100644 test/utilities/eligibility-check.test.ts create mode 100644 test/utilities/freeze-check.test.ts create mode 100644 test/utilities/transfer-check.test.ts create mode 100644 test/utilities/upgrade.test.ts diff --git a/contracts/_testContracts/MockContract.sol b/contracts/_testContracts/MockContract.sol index 95f753fc..6e0568f9 100644 --- a/contracts/_testContracts/MockContract.sol +++ b/contracts/_testContracts/MockContract.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.27; contract MockContract { address _irRegistry; uint16 _investorCountry; + address _compliance; function identityRegistry() public view returns (address identityRegistry) { if (_irRegistry != address(0)) { @@ -19,4 +20,12 @@ contract MockContract { function setInvestorCountry(uint16 country) public { _investorCountry = country; } + + function setCompliance(address compliance) public { + _compliance = compliance; + } + + function compliance() public view returns (address) { + return _compliance; + } } diff --git a/contracts/utilities/IUtilityChecker.sol b/contracts/utilities/IUtilityChecker.sol new file mode 100644 index 00000000..19d1522e --- /dev/null +++ b/contracts/utilities/IUtilityChecker.sol @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-3.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// + +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2023, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +pragma solidity 0.8.27; + +import { IClaimIssuer } from "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; + + +interface IUtilityChecker { + + struct ComplianceCheckDetails { + string moduleName; + bool pass; + } + + struct EligibilityCheckDetails { + IClaimIssuer issuer; + uint256 topic; + bool pass; + } + + /// @dev This function verifies if the transfer is restricted due to frozen addresses or tokens. + /// @param _token The address of the token contract. + /// @param _from The address of the sender. + /// @param _to The address of the recipient. + /// @param _amount The amount of tokens to be transferred. + /// @return _frozen bool Returns true if the transfer is affected by freeze conditions, false otherwise. + /// @return _availableBalance uint256 Available unfreezed balance. + function testFreeze(address _token, address _from, address _to, uint256 _amount) + external view returns (bool _frozen, uint256 _availableBalance); + + /// @dev This function performs a comprehensive check on whether a transfer would succeed: + /// - check if token is paused, + /// - check freeze conditions, + /// - check eligibilty, + /// - check compliance. + /// @param _token The address of the token contract. + /// @param _from The address of the sender. + /// @param _to The address of the recipient. + /// @param _amount The amount of tokens to be transferred. + /// @return _freezeStatus bool + /// Returns true if the transfer would be successful according to pause/freeze conditions, false otherwise. + /// @return _eligibilityStatus bool + /// Returns true if the transfer would be successful according to eligibilty conditions, false otherwise. + /// @return _complianceStatus bool + /// Returns true if the transfer would be successful according to compliance conditions, false otherwise. + function testTransfer(address _token, address _from, address _to, uint256 _amount) + external view returns (bool _freezeStatus, bool _eligibilityStatus, bool _complianceStatus); + + /// @dev Check trade validity and return the status of each module for this transfer. + /// @param _token The address of the token contract. + /// @param _from Address of the sender. + /// @param _to Address of the receiver. + /// @param _value Amount of tokens to transfer. + /// @return _details Array of struct with module name and result of the `moduleCheck` call. + function testTransferDetails(address _token, address _from, address _to, uint256 _value) + external view returns (ComplianceCheckDetails [] memory _details); + + + /// @dev This functions checks whether an identity contract corresponding to the provided user address has the required + /// claims or not based on the data fetched from trusted issuers registry and from the claim topics registry. It + /// returns the details of each (issuer, topic). + /// @param _token Address of the token contract. + /// @param _userAddress Address of the user to be verified. + /// @return _details Array of struct with issuer, topic, and the verified status. + function testVerifiedDetails(address _token, address _userAddress) + external view returns (EligibilityCheckDetails [] memory _details); + +} \ No newline at end of file diff --git a/contracts/utilities/UtilityChecker.sol b/contracts/utilities/UtilityChecker.sol new file mode 100644 index 00000000..0a4a1331 --- /dev/null +++ b/contracts/utilities/UtilityChecker.sol @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-3.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// + +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2023, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +pragma solidity 0.8.27; + +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; + +import { IClaimIssuer, IIdentity } from "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; +import { IERC3643IdentityRegistry } from "../ERC-3643/IERC3643IdentityRegistry.sol"; +import { IERC3643TrustedIssuersRegistry } from "../ERC-3643/IERC3643TrustedIssuersRegistry.sol"; +import { IModularCompliance } from "../compliance/modular/IModularCompliance.sol"; +import { IModule } from "../compliance/modular/modules/IModule.sol"; +import { IToken } from "../token/IToken.sol"; +import { IUtilityChecker } from "./IUtilityChecker.sol"; + + +contract UtilityChecker is IUtilityChecker, OwnableUpgradeable, UUPSUpgradeable { + + function initialize() external initializer { + __Ownable_init(); + } + + /// @inheritdoc IUtilityChecker + /// @dev This function is not gas optimized and should be called only OFF chain. + function testTransfer(address _token, address _from, address _to, uint256 _amount) + external view override returns (bool _freezeStatus, bool _eligibilityStatus, bool _complianceStatus) { + IToken token = IToken(_token); + + _freezeStatus = !token.paused(); + + (bool frozen, ) = testFreeze(_token, _from, _to, _amount); + _freezeStatus = _freezeStatus && !frozen; + + IERC3643IdentityRegistry ir = token.identityRegistry(); + _eligibilityStatus = ir.isVerified(_to); + + ComplianceCheckDetails [] memory details = testTransferDetails(_token, _from, _to, _amount); + for (uint256 i; i < details.length; i++) { + if (!details[i].pass) { + _complianceStatus = false; + break; + } + } + _complianceStatus = true; + } + + /// @inheritdoc IUtilityChecker + function testVerifiedDetails(address _token, address _userAddress) + public view override returns (EligibilityCheckDetails [] memory _details) { + + IERC3643IdentityRegistry identityRegistry = IToken(_token).identityRegistry(); + IERC3643TrustedIssuersRegistry tokenIssuersRegistry = identityRegistry.issuersRegistry(); + IIdentity identity = identityRegistry.identity(_userAddress); + + uint256 foundClaimTopic; + uint256 scheme; + address issuer; + bytes memory sig; + bytes memory data; + uint256 topic; + uint256[] memory requiredClaimTopics = identityRegistry.topicsRegistry().getClaimTopics(); + uint256 topicsCount = requiredClaimTopics.length; + _details = new EligibilityCheckDetails[](topicsCount); + for (uint256 claimTopic; claimTopic < topicsCount; claimTopic++) { + topic = requiredClaimTopics[claimTopic]; + IClaimIssuer[] memory trustedIssuers = + tokenIssuersRegistry.getTrustedIssuersForClaimTopic(topic); + + for (uint256 i; i < trustedIssuers.length; i++) { + bytes32 claimId = keccak256(abi.encode(trustedIssuers[i], topic)); + (foundClaimTopic, scheme, issuer, sig, data, ) = identity.getClaim(claimId); + if (foundClaimTopic == topic) { + bool pass; + try IClaimIssuer(issuer).isClaimValid(identity, topic, sig, data) returns(bool validity) { + pass = validity; + } + catch { + pass = false; + } + + _details[claimTopic] = EligibilityCheckDetails({ + issuer: trustedIssuers[i], + topic: topic, + pass: pass + }); + } + } + } + } + + /// @inheritdoc IUtilityChecker + function testFreeze(address _token, address _from, address _to, uint256 _amount) + public view override returns (bool _frozen, uint256 _availableBalance) { + IToken token = IToken(_token); + + if (token.isFrozen(_from) || token.isFrozen(_to)) { + _availableBalance = 0; + _frozen = true; + } else { + _availableBalance = token.balanceOf(_from) - token.getFrozenTokens(_from); + _frozen = _amount > _availableBalance; + } + } + + /// @inheritdoc IUtilityChecker + function testTransferDetails(address _token, address _from, address _to, uint256 _value) + public view override returns (ComplianceCheckDetails [] memory _details) { + IModularCompliance compliance = IModularCompliance(address(IToken(_token).compliance())); + address[] memory modules = compliance.getModules(); + uint256 length = modules.length; + _details = new ComplianceCheckDetails[](length); + for (uint256 i; i < length; i++) { + IModule module = IModule(modules[i]); + _details[i] = ComplianceCheckDetails({ + moduleName: module.name(), + pass: module.moduleCheck(_from, _to, _value, address(compliance)) + }); + } + } + + // solhint-disable-next-line no-empty-blocks + function _authorizeUpgrade(address /*newImplementation*/) internal view override onlyOwner { } + +} \ No newline at end of file diff --git a/contracts/utilities/UtilityCheckerProxy.sol b/contracts/utilities/UtilityCheckerProxy.sol new file mode 100644 index 00000000..b5695d74 --- /dev/null +++ b/contracts/utilities/UtilityCheckerProxy.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-3.0 +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2023, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +pragma solidity 0.8.27; + +import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + +contract UtilityCheckerProxy is ERC1967Proxy { + + // solhint-disable-next-line no-empty-blocks + constructor(address implementation, bytes memory _data) ERC1967Proxy(implementation, _data) { } + +} \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index 90f04820..09fc0657 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -5,7 +5,6 @@ import '@openzeppelin/hardhat-upgrades'; import 'solidity-coverage'; import '@nomiclabs/hardhat-solhint'; import '@primitivefi/hardhat-dodoc'; -import 'hardhat-tracer'; const config: HardhatUserConfig = { solidity: { @@ -15,6 +14,7 @@ const config: HardhatUserConfig = { enabled: true, runs: 200, }, + viaIR: true, }, }, gasReporter: { diff --git a/package-lock.json b/package-lock.json index 33d74852..c2b417d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,9 +8,6 @@ "name": "@tokenysolutions/t-rex", "version": "4.2.0-beta1", "license": "SEE LICENSE IN LICENSE.md", - "dependencies": { - "hardhat-tracer": "^3.0.3" - }, "devDependencies": { "@commitlint/cli": "^19.3.0", "@nomicfoundation/hardhat-toolbox": "^5.0.0", @@ -431,7 +428,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "devOptional": true, + "dev": true, "peer": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" @@ -640,6 +637,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", + "dev": true, "funding": [ { "type": "individual", @@ -666,6 +664,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", + "dev": true, "funding": [ { "type": "individual", @@ -690,6 +689,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", + "dev": true, "funding": [ { "type": "individual", @@ -712,6 +712,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", + "dev": true, "funding": [ { "type": "individual", @@ -734,6 +735,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", + "dev": true, "funding": [ { "type": "individual", @@ -752,6 +754,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", + "dev": true, "funding": [ { "type": "individual", @@ -771,6 +774,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", + "dev": true, "funding": [ { "type": "individual", @@ -791,6 +795,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", + "dev": true, "funding": [ { "type": "individual", @@ -809,6 +814,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", + "dev": true, "funding": [ { "type": "individual", @@ -827,6 +833,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", + "dev": true, "funding": [ { "type": "individual", @@ -854,6 +861,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", + "dev": true, "funding": [ { "type": "individual", @@ -880,6 +888,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", + "dev": true, "funding": [ { "type": "individual", @@ -909,6 +918,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", + "dev": true, "funding": [ { "type": "individual", @@ -938,12 +948,14 @@ "node_modules/@ethersproject/json-wallets/node_modules/aes-js": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==" + "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", + "dev": true }, "node_modules/@ethersproject/keccak256": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", + "dev": true, "funding": [ { "type": "individual", @@ -963,6 +975,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", + "dev": true, "funding": [ { "type": "individual", @@ -978,6 +991,7 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", + "dev": true, "funding": [ { "type": "individual", @@ -996,6 +1010,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", + "dev": true, "funding": [ { "type": "individual", @@ -1015,6 +1030,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", + "dev": true, "funding": [ { "type": "individual", @@ -1033,6 +1049,7 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", + "dev": true, "funding": [ { "type": "individual", @@ -1070,6 +1087,7 @@ "version": "7.4.6", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "dev": true, "engines": { "node": ">=8.3.0" }, @@ -1090,6 +1108,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", + "dev": true, "funding": [ { "type": "individual", @@ -1109,6 +1128,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", + "dev": true, "funding": [ { "type": "individual", @@ -1128,6 +1148,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", + "dev": true, "funding": [ { "type": "individual", @@ -1148,6 +1169,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", + "dev": true, "funding": [ { "type": "individual", @@ -1171,6 +1193,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", + "dev": true, "funding": [ { "type": "individual", @@ -1194,6 +1217,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", + "dev": true, "funding": [ { "type": "individual", @@ -1214,6 +1238,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", + "dev": true, "funding": [ { "type": "individual", @@ -1240,6 +1265,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", + "dev": true, "funding": [ { "type": "individual", @@ -1260,6 +1286,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", + "dev": true, "funding": [ { "type": "individual", @@ -1292,6 +1319,7 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", + "dev": true, "funding": [ { "type": "individual", @@ -1314,6 +1342,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", + "dev": true, "funding": [ { "type": "individual", @@ -1336,6 +1365,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, "engines": { "node": ">=14" } @@ -1483,7 +1513,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "devOptional": true, + "dev": true, "peer": true, "engines": { "node": ">=6.0.0" @@ -1493,14 +1523,14 @@ "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "devOptional": true, + "dev": true, "peer": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "devOptional": true, + "dev": true, "peer": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", @@ -1511,6 +1541,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz", "integrity": "sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==", + "dev": true, "dependencies": { "ethereumjs-abi": "^0.6.8", "ethereumjs-util": "^6.2.1", @@ -1526,6 +1557,7 @@ "version": "4.11.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -1533,12 +1565,14 @@ "node_modules/@metamask/eth-sig-util/node_modules/bn.js": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true }, "node_modules/@metamask/eth-sig-util/node_modules/ethereum-cryptography": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -1561,6 +1595,7 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, "dependencies": { "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", @@ -1601,6 +1636,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", + "dev": true, "funding": [ { "type": "individual", @@ -1612,6 +1648,7 @@ "version": "1.7.1", "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", + "dev": true, "funding": [ { "type": "individual", @@ -1658,6 +1695,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.5.2.tgz", "integrity": "sha512-hW/iLvUQZNTVjFyX/I40rtKvvDOqUEyIi96T28YaLfmPL+3LW2lxmYLUXEJ6MI14HzqxDqrLyhf6IbjAa2r3Dw==", + "dev": true, "dependencies": { "@nomicfoundation/edr-darwin-arm64": "0.5.2", "@nomicfoundation/edr-darwin-x64": "0.5.2", @@ -1675,6 +1713,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.5.2.tgz", "integrity": "sha512-Gm4wOPKhbDjGTIRyFA2QUAPfCXA1AHxYOKt3yLSGJkQkdy9a5WW+qtqKeEKHc/+4wpJSLtsGQfpzyIzggFfo/A==", + "dev": true, "engines": { "node": ">= 18" } @@ -1683,6 +1722,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.5.2.tgz", "integrity": "sha512-ClyABq2dFCsrYEED3/UIO0c7p4H1/4vvlswFlqUyBpOkJccr75qIYvahOSJRM62WgUFRhbSS0OJXFRwc/PwmVg==", + "dev": true, "engines": { "node": ">= 18" } @@ -1691,6 +1731,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.5.2.tgz", "integrity": "sha512-HWMTVk1iOabfvU2RvrKLDgtFjJZTC42CpHiw2h6rfpsgRqMahvIlx2jdjWYzFNy1jZKPTN1AStQ/91MRrg5KnA==", + "dev": true, "engines": { "node": ">= 18" } @@ -1699,6 +1740,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.5.2.tgz", "integrity": "sha512-CwsQ10xFx/QAD5y3/g5alm9+jFVuhc7uYMhrZAu9UVF+KtVjeCvafj0PaVsZ8qyijjqVuVsJ8hD1x5ob7SMcGg==", + "dev": true, "engines": { "node": ">= 18" } @@ -1707,6 +1749,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.5.2.tgz", "integrity": "sha512-CWVCEdhWJ3fmUpzWHCRnC0/VLBDbqtqTGTR6yyY1Ep3S3BOrHEAvt7h5gx85r2vLcztisu2vlDq51auie4IU1A==", + "dev": true, "engines": { "node": ">= 18" } @@ -1715,6 +1758,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.5.2.tgz", "integrity": "sha512-+aJDfwhkddy2pP5u1ISg3IZVAm0dO836tRlDTFWtvvSMQ5hRGqPcWwlsbobhDQsIxhPJyT7phL0orCg5W3WMeA==", + "dev": true, "engines": { "node": ">= 18" } @@ -1723,6 +1767,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.5.2.tgz", "integrity": "sha512-CcvvuA3sAv7liFNPsIR/68YlH6rrybKzYttLlMr80d4GKJjwJ5OKb3YgE6FdZZnOfP19HEHhsLcE0DPLtY3r0w==", + "dev": true, "engines": { "node": ">= 18" } @@ -1731,6 +1776,7 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz", "integrity": "sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==", + "dev": true, "dependencies": { "@nomicfoundation/ethereumjs-util": "9.0.4" } @@ -1739,6 +1785,7 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz", "integrity": "sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==", + "dev": true, "bin": { "rlp": "bin/rlp.cjs" }, @@ -1750,6 +1797,7 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz", "integrity": "sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==", + "dev": true, "dependencies": { "@nomicfoundation/ethereumjs-common": "4.0.4", "@nomicfoundation/ethereumjs-rlp": "5.0.4", @@ -1772,6 +1820,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -1794,6 +1843,7 @@ "version": "9.0.4", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz", "integrity": "sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==", + "dev": true, "dependencies": { "@nomicfoundation/ethereumjs-rlp": "5.0.4", "ethereum-cryptography": "0.1.3" @@ -1814,6 +1864,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -2192,6 +2243,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz", "integrity": "sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg==", + "dev": true, "engines": { "node": ">= 12" }, @@ -2215,6 +2267,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -2230,6 +2283,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -2245,6 +2299,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "freebsd" @@ -2260,6 +2315,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -2275,6 +2331,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -2290,6 +2347,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -2305,6 +2363,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -2320,6 +2379,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -2335,6 +2395,7 @@ "cpu": [ "ia32" ], + "dev": true, "optional": true, "os": [ "win32" @@ -2350,6 +2411,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -2988,6 +3050,7 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==", + "dev": true, "funding": { "url": "https://paulmillr.com/funding/" } @@ -2996,6 +3059,7 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", + "dev": true, "funding": [ { "type": "individual", @@ -3012,6 +3076,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", + "dev": true, "funding": [ { "type": "individual", @@ -3027,6 +3092,7 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==", + "dev": true, "dependencies": { "@sentry/hub": "5.30.0", "@sentry/minimal": "5.30.0", @@ -3042,6 +3108,7 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==", + "dev": true, "dependencies": { "@sentry/types": "5.30.0", "@sentry/utils": "5.30.0", @@ -3055,6 +3122,7 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==", + "dev": true, "dependencies": { "@sentry/hub": "5.30.0", "@sentry/types": "5.30.0", @@ -3068,6 +3136,7 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz", "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==", + "dev": true, "dependencies": { "@sentry/core": "5.30.0", "@sentry/hub": "5.30.0", @@ -3087,6 +3156,7 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==", + "dev": true, "dependencies": { "@sentry/hub": "5.30.0", "@sentry/minimal": "5.30.0", @@ -3102,6 +3172,7 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==", + "dev": true, "engines": { "node": ">=6" } @@ -3110,6 +3181,7 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", + "dev": true, "dependencies": { "@sentry/types": "5.30.0", "tslib": "^1.9.3" @@ -3173,28 +3245,28 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "devOptional": true, + "dev": true, "peer": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "devOptional": true, + "dev": true, "peer": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "devOptional": true, + "dev": true, "peer": true }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "devOptional": true, + "dev": true, "peer": true }, "node_modules/@typechain/ethers-v6": { @@ -3249,6 +3321,7 @@ "version": "5.1.5", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -3323,7 +3396,8 @@ "node_modules/@types/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==" + "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", + "dev": true }, "node_modules/@types/minimatch": { "version": "5.1.2", @@ -3343,6 +3417,7 @@ "version": "20.12.12", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", + "dev": true, "dependencies": { "undici-types": "~5.26.4" } @@ -3351,6 +3426,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -3372,6 +3448,7 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -3587,7 +3664,7 @@ "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "devOptional": true, + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -3608,7 +3685,7 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", - "devOptional": true, + "dev": true, "peer": true, "engines": { "node": ">=0.4.0" @@ -3618,6 +3695,7 @@ "version": "0.4.16", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "dev": true, "engines": { "node": ">=0.3.0" } @@ -3633,6 +3711,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, "dependencies": { "debug": "4" }, @@ -3644,6 +3723,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -3696,6 +3776,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, "dependencies": { "string-width": "^4.1.0" } @@ -3704,6 +3785,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -3712,6 +3794,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3725,6 +3808,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, "engines": { "node": ">=6" } @@ -3733,6 +3817,7 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, "dependencies": { "type-fest": "^0.21.3" }, @@ -3747,6 +3832,7 @@ "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, "engines": { "node": ">=10" }, @@ -3758,6 +3844,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "engines": { "node": ">=8" } @@ -3793,6 +3880,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -3805,13 +3893,14 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "devOptional": true, + "dev": true, "peer": true }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/array-back": { "version": "3.1.0", @@ -3992,6 +4081,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, "peer": true, "engines": { "node": "*" @@ -4073,12 +4163,14 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "node_modules/base-x": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "dev": true, "dependencies": { "safe-buffer": "^5.0.1" } @@ -4106,12 +4198,14 @@ "node_modules/bech32": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "dev": true }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, "engines": { "node": ">=8" }, @@ -4122,17 +4216,20 @@ "node_modules/blakejs": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", - "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==" + "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", + "dev": true }, "node_modules/bn.js": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "dev": true }, "node_modules/boxen": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, "dependencies": { "ansi-align": "^3.0.0", "camelcase": "^6.2.0", @@ -4154,6 +4251,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -4168,6 +4266,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4183,6 +4282,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -4193,12 +4293,14 @@ "node_modules/boxen/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/boxen/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -4207,6 +4309,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -4220,6 +4323,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -4231,6 +4335,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -4239,6 +4344,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, "dependencies": { "fill-range": "^7.1.1" }, @@ -4249,17 +4355,20 @@ "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true }, "node_modules/browserify-aes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, "dependencies": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", @@ -4273,6 +4382,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "dev": true, "dependencies": { "base-x": "^3.0.2" } @@ -4281,6 +4391,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dev": true, "dependencies": { "bs58": "^4.0.0", "create-hash": "^1.1.0", @@ -4301,17 +4412,20 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true }, "node_modules/buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -4387,6 +4501,7 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, "engines": { "node": ">=10" }, @@ -4417,6 +4532,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "dev": true, "peer": true, "dependencies": { "assertion-error": "^1.1.0", @@ -4469,6 +4585,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, "peer": true, "dependencies": { "get-func-name": "^2.0.2" @@ -4481,6 +4598,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -4504,6 +4622,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -4514,12 +4633,14 @@ "node_modules/ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true }, "node_modules/cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -4529,6 +4650,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, "engines": { "node": ">=6" } @@ -4537,6 +4659,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, "engines": { "node": ">=6" }, @@ -4682,6 +4805,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -4689,7 +4813,8 @@ "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, "node_modules/colorette": { "version": "2.0.20", @@ -4722,6 +4847,7 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "dev": true, "license": "MIT" }, "node_modules/command-line-args": { @@ -4865,7 +4991,8 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "node_modules/concat-stream": { "version": "1.6.2", @@ -4968,6 +5095,7 @@ "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -5025,6 +5153,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, "dependencies": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -5037,6 +5166,7 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, "dependencies": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", @@ -5050,7 +5180,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "devOptional": true, + "dev": true, "peer": true }, "node_modules/cross-spawn": { @@ -5150,6 +5280,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -5166,6 +5297,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, "engines": { "node": ">=10" }, @@ -5204,6 +5336,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, "peer": true, "dependencies": { "type-detect": "^4.0.0" @@ -5283,6 +5416,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -5291,6 +5425,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, "engines": { "node": ">=0.3.1" } @@ -5354,6 +5489,7 @@ "version": "6.5.4", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -5367,12 +5503,14 @@ "node_modules/elliptic/node_modules/bn.js": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/enhanced-resolve": { "version": "5.16.1", @@ -5391,6 +5529,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -5403,6 +5542,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, "engines": { "node": ">=6" } @@ -5553,6 +5693,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, "engines": { "node": ">=6" } @@ -5561,6 +5702,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "engines": { "node": ">=10" }, @@ -6351,6 +6493,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", + "dev": true, "dependencies": { "@noble/hashes": "1.2.0", "@noble/secp256k1": "1.7.1", @@ -6362,6 +6505,7 @@ "version": "0.6.8", "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", + "dev": true, "dependencies": { "bn.js": "^4.11.8", "ethereumjs-util": "^6.0.0" @@ -6371,6 +6515,7 @@ "version": "4.11.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -6378,12 +6523,14 @@ "node_modules/ethereumjs-abi/node_modules/bn.js": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true }, "node_modules/ethereumjs-abi/node_modules/ethereum-cryptography": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -6406,6 +6553,7 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, "dependencies": { "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", @@ -6537,6 +6685,7 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "dev": true, "dependencies": { "is-hex-prefixed": "1.0.0", "strip-hex-prefix": "1.0.0" @@ -6556,6 +6705,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, "dependencies": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" @@ -6667,6 +6817,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -6708,6 +6859,7 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, "bin": { "flat": "cli.js" } @@ -6736,6 +6888,7 @@ "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "dev": true, "funding": [ { "type": "individual", @@ -6802,7 +6955,8 @@ "node_modules/fp-ts": { "version": "1.19.3", "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", - "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==" + "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==", + "dev": true }, "node_modules/fs-extra": { "version": "11.2.0", @@ -6827,12 +6981,14 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -6882,6 +7038,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -6902,6 +7059,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, "peer": true, "engines": { "node": "*" @@ -7268,7 +7426,8 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "node_modules/graphemer": { "version": "1.4.0", @@ -7312,6 +7471,7 @@ "version": "2.22.8", "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.8.tgz", "integrity": "sha512-hPh2feBGRswkXkoXUFW6NbxgiYtEzp/3uvVFjYROy6fA9LH8BobUyxStlyhSKj4+v1Y23ZoUBOVWL84IcLACrA==", + "dev": true, "dependencies": { "@ethersproject/abi": "^5.1.2", "@metamask/eth-sig-util": "^4.0.0", @@ -7388,135 +7548,11 @@ "hardhat": "^2.0.2" } }, - "node_modules/hardhat-tracer": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/hardhat-tracer/-/hardhat-tracer-3.0.3.tgz", - "integrity": "sha512-Uto+JQGayzZRnwdUyM1Un0zmFth+j3jkijHxls75BCTEBHXvAilUO20UloT+b2DYWVCcKn5GRuRpxjSQEV4QYg==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "debug": "^4.3.4", - "ethers": "^5.6.1", - "semver": "^7.6.2" - }, - "peerDependencies": { - "chai": "4.x", - "hardhat": ">=2.22.5 <3.x" - } - }, - "node_modules/hardhat-tracer/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/hardhat-tracer/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/hardhat-tracer/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/hardhat-tracer/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/hardhat-tracer/node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" - } - }, - "node_modules/hardhat-tracer/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/hardhat/node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -7528,6 +7564,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7537,6 +7574,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -7550,6 +7588,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, "engines": { "node": ">=0.8.0" } @@ -7558,6 +7597,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, "dependencies": { "locate-path": "^2.0.0" }, @@ -7569,6 +7609,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -7583,6 +7624,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -7602,6 +7644,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, "engines": { "node": ">=4" } @@ -7610,6 +7653,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -7618,6 +7662,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -7630,6 +7675,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -7641,6 +7687,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, "dependencies": { "p-try": "^1.0.0" }, @@ -7652,6 +7699,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, "dependencies": { "p-limit": "^1.1.0" }, @@ -7663,6 +7711,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, "engines": { "node": ">=4" } @@ -7671,6 +7720,7 @@ "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, "dependencies": { "path-parse": "^1.0.6" }, @@ -7682,6 +7732,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } @@ -7690,6 +7741,7 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -7701,6 +7753,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, "engines": { "node": ">= 4.0.0" } @@ -7709,6 +7762,7 @@ "version": "7.5.9", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "dev": true, "engines": { "node": ">=8.3.0" }, @@ -7738,6 +7792,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -7797,6 +7852,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, "dependencies": { "inherits": "^2.0.4", "readable-stream": "^3.6.0", @@ -7810,6 +7866,7 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" @@ -7831,6 +7888,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, "bin": { "he": "bin/he" } @@ -7846,6 +7904,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -7877,6 +7936,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -7920,6 +7980,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -7956,6 +8017,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -8006,7 +8068,8 @@ "node_modules/immutable": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz", - "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==" + "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==", + "dev": true }, "node_modules/import-fresh": { "version": "3.3.0", @@ -8056,6 +8119,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, "engines": { "node": ">=8" } @@ -8065,6 +8129,7 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -8073,7 +8138,8 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "node_modules/ini": { "version": "4.1.1", @@ -8112,6 +8178,7 @@ "version": "1.10.4", "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz", "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==", + "dev": true, "dependencies": { "fp-ts": "^1.0.0" } @@ -8154,6 +8221,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -8235,6 +8303,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -8255,6 +8324,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -8266,6 +8336,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", "integrity": "sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==", + "dev": true, "engines": { "node": ">=6.5.0", "npm": ">=3" @@ -8287,6 +8358,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, "engines": { "node": ">=0.12.0" } @@ -8328,6 +8400,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, "engines": { "node": ">=8" } @@ -8436,6 +8509,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, "engines": { "node": ">=10" }, @@ -8513,7 +8587,8 @@ "node_modules/js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "dev": true }, "node_modules/js-tokens": { "version": "4.0.0", @@ -8525,6 +8600,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -8626,6 +8702,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", + "dev": true, "hasInstallScript": true, "dependencies": { "node-addon-api": "^2.0.0", @@ -8840,7 +8917,8 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true }, "node_modules/lodash.camelcase": { "version": "4.3.0", @@ -8920,6 +8998,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -8935,6 +9014,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -8949,6 +9029,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -8964,6 +9045,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -8974,12 +9056,14 @@ "node_modules/log-symbols/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/log-symbols/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -9120,6 +9204,7 @@ "version": "2.3.7", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, "peer": true, "dependencies": { "get-func-name": "^2.0.1" @@ -9140,7 +9225,8 @@ "node_modules/lru_map": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==" + "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", + "dev": true }, "node_modules/lru-cache": { "version": "10.2.2", @@ -9155,7 +9241,7 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "devOptional": true, + "dev": true, "peer": true }, "node_modules/markdown-table": { @@ -9168,6 +9254,7 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1", @@ -9178,6 +9265,7 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, "engines": { "node": ">= 0.10.0" } @@ -9277,12 +9365,14 @@ "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true }, "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true }, "node_modules/minimatch": { "version": "9.0.4", @@ -9334,6 +9424,7 @@ "version": "0.38.5", "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", "integrity": "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==", + "dev": true, "dependencies": { "obliterator": "^2.0.0" } @@ -9342,6 +9433,7 @@ "version": "10.4.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", + "dev": true, "dependencies": { "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", @@ -9376,6 +9468,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, "engines": { "node": ">=6" } @@ -9384,6 +9477,7 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, "funding": [ { "type": "individual", @@ -9410,6 +9504,7 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -9420,6 +9515,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -9436,6 +9532,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -9454,6 +9551,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -9465,6 +9563,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -9473,6 +9572,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -9487,6 +9587,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -9497,12 +9598,14 @@ "node_modules/mocha/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true }, "node_modules/mocha/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -9517,6 +9620,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -9531,6 +9635,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "engines": { "node": ">=8" } @@ -9539,6 +9644,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -9552,6 +9658,7 @@ "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -9569,6 +9676,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, "engines": { "node": ">=10" }, @@ -9579,7 +9687,8 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/natural-compare": { "version": "1.4.0", @@ -9627,7 +9736,8 @@ "node_modules/node-addon-api": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "dev": true }, "node_modules/node-emoji": { "version": "1.11.0", @@ -9663,6 +9773,7 @@ "version": "4.8.1", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", + "dev": true, "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", @@ -9695,6 +9806,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -9871,12 +9983,14 @@ "node_modules/obliterator": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", - "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==" + "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==", + "dev": true }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "dependencies": { "wrappy": "1" } @@ -9924,6 +10038,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -9972,6 +10087,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, "dependencies": { "aggregate-error": "^3.0.0" }, @@ -9986,6 +10102,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true, "engines": { "node": ">=4" } @@ -10057,6 +10174,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -10073,7 +10191,8 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, "node_modules/path-scurry": { "version": "1.11.1", @@ -10104,6 +10223,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, "peer": true, "engines": { "node": "*" @@ -10113,6 +10233,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, "dependencies": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", @@ -10134,6 +10255,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "engines": { "node": ">=8.6" }, @@ -10367,6 +10489,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -10375,6 +10498,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -10419,6 +10543,7 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -10432,6 +10557,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -10590,6 +10716,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -10793,6 +10920,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -10802,6 +10930,7 @@ "version": "2.2.7", "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz", "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==", + "dev": true, "dependencies": { "bn.js": "^5.2.0" }, @@ -10860,6 +10989,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, "funding": [ { "type": "github", @@ -10904,7 +11034,8 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "node_modules/sc-istanbul": { "version": "0.4.6", @@ -11058,12 +11189,14 @@ "node_modules/scrypt-js": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", + "dev": true }, "node_modules/secp256k1": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", + "dev": true, "hasInstallScript": true, "dependencies": { "elliptic": "^6.5.4", @@ -11078,6 +11211,7 @@ "version": "7.6.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -11089,6 +11223,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, "dependencies": { "randombytes": "^2.1.0" } @@ -11128,17 +11263,20 @@ "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true }, "node_modules/sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -11311,6 +11449,7 @@ "version": "0.8.26", "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.26.tgz", "integrity": "sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==", + "dev": true, "license": "MIT", "dependencies": { "command-exists": "^1.2.8", @@ -11332,6 +11471,7 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, "license": "MIT", "engines": { "node": ">= 12" @@ -11341,6 +11481,7 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver" @@ -11800,6 +11941,7 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -11809,6 +11951,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -11845,6 +11988,7 @@ "version": "0.1.10", "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", + "dev": true, "dependencies": { "type-fest": "^0.7.1" }, @@ -11856,6 +12000,7 @@ "version": "0.7.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "dev": true, "engines": { "node": ">=8" } @@ -11864,6 +12009,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -11872,6 +12018,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -12012,6 +12159,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -12057,6 +12205,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", "integrity": "sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==", + "dev": true, "dependencies": { "is-hex-prefixed": "1.0.0" }, @@ -12069,6 +12218,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, "engines": { "node": ">=8" }, @@ -12080,6 +12230,7 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -12361,6 +12512,7 @@ "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, "license": "MIT", "dependencies": { "os-tmpdir": "~1.0.2" @@ -12373,6 +12525,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -12384,6 +12537,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, "engines": { "node": ">=0.6" } @@ -12502,7 +12656,7 @@ "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "devOptional": true, + "dev": true, "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", @@ -12546,7 +12700,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "devOptional": true, + "dev": true, "peer": true, "engines": { "node": ">=0.3.1" @@ -12567,22 +12721,26 @@ "node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, "node_modules/tsort": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", - "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==" + "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==", + "dev": true }, "node_modules/tweetnacl": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "dev": true }, "node_modules/tweetnacl-util": { "version": "0.15.1", "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", - "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==" + "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", + "dev": true }, "node_modules/type-check": { "version": "0.4.0", @@ -12600,6 +12758,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, "peer": true, "engines": { "node": ">=4" @@ -12609,6 +12768,7 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, "engines": { "node": ">=10" }, @@ -12834,7 +12994,7 @@ "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "devOptional": true, + "dev": true, "peer": true, "bin": { "tsc": "bin/tsc", @@ -12887,6 +13047,7 @@ "version": "5.28.4", "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dev": true, "dependencies": { "@fastify/busboy": "^2.0.0" }, @@ -12897,7 +13058,8 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true }, "node_modules/unfetch": { "version": "4.2.0", @@ -12930,6 +13092,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -12953,12 +13116,14 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, "bin": { "uuid": "dist/bin/uuid" } @@ -12967,7 +13132,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "devOptional": true, + "dev": true, "peer": true }, "node_modules/web3-utils": { @@ -13128,6 +13293,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, "dependencies": { "string-width": "^4.0.0" }, @@ -13139,6 +13305,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -13147,6 +13314,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -13199,12 +13367,14 @@ "node_modules/workerpool": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==" + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -13295,6 +13465,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -13309,6 +13480,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -13319,12 +13491,14 @@ "node_modules/wrap-ansi/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -13333,6 +13507,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -13345,7 +13520,8 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "node_modules/ws": { "version": "8.5.0", @@ -13373,6 +13549,7 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, "engines": { "node": ">=10" } @@ -13411,6 +13588,7 @@ "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, "engines": { "node": ">=10" } @@ -13419,6 +13597,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -13465,7 +13644,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "devOptional": true, + "dev": true, "peer": true, "engines": { "node": ">=6" diff --git a/package.json b/package.json index 1d1e6491..7ae6caf0 100644 --- a/package.json +++ b/package.json @@ -85,8 +85,5 @@ "*.js": [ "eslint" ] - }, - "dependencies": { - "hardhat-tracer": "^3.0.3" } } diff --git a/test/utilities/compliance-check.test.ts b/test/utilities/compliance-check.test.ts new file mode 100644 index 00000000..144f81f8 --- /dev/null +++ b/test/utilities/compliance-check.test.ts @@ -0,0 +1,93 @@ +import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { expect } from 'chai'; +import { ethers } from 'hardhat'; + +import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture'; + +async function deployComplianceWithCountryAllowModule() { + const context = await loadFixture(deployComplianceFixture); + const { compliance } = context.suite; + + const module = await ethers.deployContract('CountryAllowModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const countryAllowModule = await ethers.getContractAt('CountryAllowModule', proxy.target); + await compliance.addModule(countryAllowModule.target); + + const contract = await ethers.deployContract('MockContract'); + await compliance.bindToken(contract.target); + await contract.setCompliance(compliance.target); + + return { ...context, suite: { ...context.suite, countryAllowModule, mock: contract } }; +} + +describe('UtilityChecker.testTransferDetails', () => { + it('should return no pass for single module', async () => { + const context = await loadFixture(deployComplianceWithCountryAllowModule); + + const utilityChecker = await ethers.deployContract('UtilityChecker'); + const results = await utilityChecker.testTransferDetails( + context.suite.mock.target, + context.accounts.aliceWallet, + context.accounts.bobWallet, + 100, + ); + expect(results.length).to.equal(1); + expect(results[0][0]).to.equal('CountryAllowModule'); + expect(results[0][1]).to.equal(false); + }); + + it('should return no pass for multiple modules', async () => { + const context = await loadFixture(deployComplianceWithCountryAllowModule); + + const transferRestrictModule = await ethers.deployContract('TransferRestrictModule'); + await ethers.deployContract('ModuleProxy', [transferRestrictModule.target, transferRestrictModule.interface.encodeFunctionData('initialize')]); + await context.suite.compliance.addModule(transferRestrictModule.target); + + const utilityChecker = await ethers.deployContract('UtilityChecker'); + const results = await utilityChecker.testTransferDetails( + context.suite.mock.target, + context.accounts.aliceWallet, + context.accounts.bobWallet, + 100, + ); + expect(results.length).to.equal(2); + expect(results[0][0]).to.equal('CountryAllowModule'); + expect(results[0][1]).to.equal(false); + expect(results[1][0]).to.equal('TransferRestrictModule'); + expect(results[1][1]).to.equal(false); + }); + + it('should return pass for multiple modules', async () => { + const context = await loadFixture(deployComplianceWithCountryAllowModule); + + const transferRestrictModule = await ethers.deployContract('TransferRestrictModule'); + await ethers.deployContract('ModuleProxy', [transferRestrictModule.target, transferRestrictModule.interface.encodeFunctionData('initialize')]); + await context.suite.compliance.addModule(transferRestrictModule.target); + + await context.suite.compliance + .connect(context.accounts.deployer) + .callModuleFunction( + new ethers.Interface(['function addAllowedCountry(uint16 country)']).encodeFunctionData('addAllowedCountry', [42]), + context.suite.countryAllowModule.target, + ); + await context.suite.mock.setInvestorCountry(42); + + await context.suite.compliance.callModuleFunction( + new ethers.Interface(['function allowUser(address _userAddress)']).encodeFunctionData('allowUser', [context.accounts.aliceWallet.address]), + transferRestrictModule.target, + ); + + const utilityChecker = await ethers.deployContract('UtilityChecker'); + const results = await utilityChecker.testTransferDetails( + context.suite.mock.target, + context.accounts.aliceWallet, + context.accounts.bobWallet, + 100, + ); + expect(results.length).to.equal(2); + expect(results[0][0]).to.equal('CountryAllowModule'); + expect(results[0][1]).to.equal(true); + expect(results[1][0]).to.equal('TransferRestrictModule'); + expect(results[1][1]).to.equal(true); + }); +}); diff --git a/test/utilities/eligibility-check.test.ts b/test/utilities/eligibility-check.test.ts new file mode 100644 index 00000000..f4c803c8 --- /dev/null +++ b/test/utilities/eligibility-check.test.ts @@ -0,0 +1,114 @@ +import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { expect } from 'chai'; +import { ethers } from 'hardhat'; + +import { deployClaimIssuer, deployFullSuiteFixture } from '../fixtures/deploy-full-suite.fixture'; + +async function addClaim(claimIssuerContract, claimIssuerSigningKey, claimTopic, wallet, identity) { + const claim = { + data: ethers.hexlify(ethers.toUtf8Bytes('Some claim public data 2.')), + issuer: claimIssuerContract.target, + topic: claimTopic, + scheme: 1, + identity: identity.target, + signature: '', + }; + claim.signature = await claimIssuerSigningKey.signMessage( + ethers.getBytes( + ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [claim.identity, claim.topic, claim.data])), + ), + ); + + await identity.connect(wallet).addClaim(claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, ''); +} + +describe('UtilityChecker.testVerifiedDetails', () => { + it('should return false when the identity is registered with topics', async () => { + const { + suite: { identityRegistry, token }, + accounts: { tokenAgent, charlieWallet }, + identities: { charlieIdentity }, + } = await loadFixture(deployFullSuiteFixture); + + await identityRegistry.connect(tokenAgent).registerIdentity(charlieWallet.address, charlieIdentity.target, 0); + + const eligibilityChecker = await ethers.deployContract('UtilityChecker'); + const results = await eligibilityChecker.testVerifiedDetails(token.target, charlieWallet.address); + expect(results.length).to.be.equal(1); + const result = results[0]; + expect(result[0]).to.be.equal(ethers.ZeroAddress); + expect(result[1]).to.be.equal(0); + expect(result[2]).to.be.equal(false); + }); + + it('should return empty result when the identity is registered without topics', async () => { + const { + suite: { identityRegistry, claimTopicsRegistry, token }, + accounts: { tokenAgent, charlieWallet }, + identities: { charlieIdentity }, + } = await loadFixture(deployFullSuiteFixture); + + await identityRegistry.connect(tokenAgent).registerIdentity(charlieWallet.address, charlieIdentity.target, 0); + const topics = await claimTopicsRegistry.getClaimTopics(); + await Promise.all(topics.map((topic) => claimTopicsRegistry.removeClaimTopic(topic))); + + const eligibilityChecker = await ethers.deployContract('UtilityChecker'); + const results = await eligibilityChecker.testVerifiedDetails(token.target, charlieWallet.address); + expect(results.length).to.be.equal(0); + }); + + it('should return true after fixture', async () => { + const { + suite: { token, claimTopicsRegistry, trustedIssuersRegistry }, + accounts: { aliceWallet }, + } = await loadFixture(deployFullSuiteFixture); + + const eligibilityChecker = await ethers.deployContract('UtilityChecker'); + const results = await eligibilityChecker.testVerifiedDetails(token.target, aliceWallet.address); + expect(results.length).to.be.equal(1); + + const topics = await claimTopicsRegistry.getClaimTopics(); + topics.forEach(async (topic, i) => { + const result = results[i]; + expect(result[0]).to.be.equal(await trustedIssuersRegistry.getTrustedIssuersForClaimTopic(topic)); + expect(result[1]).to.be.equal(topic); + expect(result[2]).to.be.equal(true); + }); + }); + + it('should return true for multiple issuers and topics', async () => { + const { + suite: { token, claimTopicsRegistry, trustedIssuersRegistry }, + accounts: { deployer, aliceWallet }, + identities: { aliceIdentity }, + } = await loadFixture(deployFullSuiteFixture); + + const [, , , , , , , , , , claimIssuer] = await ethers.getSigners(); + const claimIssuerSigningKey = ethers.Wallet.createRandom(); + + const claimIssuerContract = await deployClaimIssuer(claimIssuer.address, claimIssuer); + await claimIssuerContract + .connect(claimIssuer) + .addKey(ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address'], [claimIssuerSigningKey.address])), 3, 1); + + const claimTopics = [ethers.keccak256(ethers.toUtf8Bytes('CLAIM_TOPIC_2')), ethers.keccak256(ethers.toUtf8Bytes('CLAIM_TOPIC_3'))]; + await claimTopicsRegistry.connect(deployer).addClaimTopic(claimTopics[0]); + await claimTopicsRegistry.connect(deployer).addClaimTopic(claimTopics[1]); + await trustedIssuersRegistry.connect(deployer).addTrustedIssuer(claimIssuerContract.target, claimTopics); + + await addClaim(claimIssuerContract, claimIssuerSigningKey, claimTopics[0], aliceWallet, aliceIdentity); + await addClaim(claimIssuerContract, claimIssuerSigningKey, claimTopics[1], aliceWallet, aliceIdentity); + + const eligibilityChecker = await ethers.deployContract('UtilityChecker'); + const results = await eligibilityChecker.testVerifiedDetails(token.target, aliceWallet.address); + + expect(results.length).to.be.equal(3); + const topics = await claimTopicsRegistry.getClaimTopics(); + topics.forEach(async (topic, i) => { + const result = results[i]; + expect(result[0]).to.be.equal(await trustedIssuersRegistry.getTrustedIssuersForClaimTopic(topic)); + expect(result[1]).to.be.equal(topic); + expect(result[2]).to.be.equal(true); + }); + }); +}); diff --git a/test/utilities/freeze-check.test.ts b/test/utilities/freeze-check.test.ts new file mode 100644 index 00000000..cfffeb8c --- /dev/null +++ b/test/utilities/freeze-check.test.ts @@ -0,0 +1,72 @@ +import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { expect } from 'chai'; +import { ethers } from 'hardhat'; + +import { deployFullSuiteFixture } from '../fixtures/deploy-full-suite.fixture'; + +describe('UtilityChecker.testFreeze', () => { + describe('When sender is frozen', () => { + it('should return true', async () => { + const { + suite: { token }, + accounts: { tokenAgent, aliceWallet, bobWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await token.connect(tokenAgent).setAddressFrozen(aliceWallet.address, true); + + const utilityChecker = await ethers.deployContract('UtilityChecker'); + const [success, balance] = await utilityChecker.testFreeze(token.target, aliceWallet.address, bobWallet.address, 100); + expect(success).to.be.equal(true); + expect(balance).to.be.equal(0); + }); + }); + + describe('When recipient is frozen', () => { + it('should return true', async () => { + const { + suite: { token }, + accounts: { tokenAgent, aliceWallet, bobWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await token.connect(tokenAgent).setAddressFrozen(bobWallet.address, true); + + const utilityChecker = await ethers.deployContract('UtilityChecker'); + const [success, balance] = await utilityChecker.testFreeze(token.target, aliceWallet.address, bobWallet.address, 100); + expect(success).to.be.equal(true); + expect(balance).to.be.equal(0); + }); + }); + + describe('When unfrozen balance is unsufficient', () => { + it('should return true', async () => { + const { + suite: { token }, + accounts: { tokenAgent, aliceWallet, bobWallet }, + } = await loadFixture(deployFullSuiteFixture); + + const initialBalance = await token.balanceOf(aliceWallet.address); + await token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, initialBalance - 10n); + + const utilityChecker = await ethers.deployContract('UtilityChecker'); + const [success, balance] = await utilityChecker.testFreeze(token.target, aliceWallet.address, bobWallet.address, 100); + expect(success).to.be.equal(true); + expect(balance).to.be.equal(10); + }); + }); + + describe('When nominal case', () => { + it('should return false', async () => { + const { + suite: { token }, + accounts: { aliceWallet, bobWallet }, + } = await loadFixture(deployFullSuiteFixture); + + const initialBalance = await token.balanceOf(aliceWallet.address); + + const utilityChecker = await ethers.deployContract('UtilityChecker'); + const [success, balance] = await utilityChecker.testFreeze(token.target, aliceWallet.address, bobWallet.address, 100); + expect(success).to.be.equal(false); + expect(balance).to.be.equal(initialBalance); + }); + }); +}); diff --git a/test/utilities/transfer-check.test.ts b/test/utilities/transfer-check.test.ts new file mode 100644 index 00000000..bac2b655 --- /dev/null +++ b/test/utilities/transfer-check.test.ts @@ -0,0 +1,160 @@ +import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { expect } from 'chai'; +import { ethers } from 'hardhat'; + +import { HardhatEthersSigner } from '@nomicfoundation/hardhat-ethers/signers'; +import { deployFullSuiteFixture } from '../fixtures/deploy-full-suite.fixture'; + +import { Token } from '../../typechain-types'; + +async function deployComplianceAndCountryAllowModule(token: Token, deployer: HardhatEthersSigner) { + const compliance = await ethers.deployContract('ModularCompliance'); + await compliance.init(); + await token.connect(deployer).setCompliance(compliance.target); + + const module = await ethers.deployContract('CountryAllowModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const countryAllowModule = await ethers.getContractAt('CountryAllowModule', proxy.target); + + await compliance.addModule(countryAllowModule.target); + await compliance.bindToken(token.target); + + await compliance + .connect(deployer) + .callModuleFunction( + new ethers.Interface(['function addAllowedCountry(uint16 country)']).encodeFunctionData('addAllowedCountry', [42]), + countryAllowModule.target, + ); +} + +describe('UtilityChecker.testTransfer', () => { + describe('When sender is frozen', () => { + it('should return false', async () => { + const { + suite: { token }, + accounts: { tokenAgent, aliceWallet, bobWallet, deployer }, + } = await loadFixture(deployFullSuiteFixture); + await deployComplianceAndCountryAllowModule(token, deployer); + + const utilityChecker = await ethers.deployContract('UtilityChecker'); + + await token.connect(tokenAgent).setAddressFrozen(aliceWallet.address, true); + const result = await utilityChecker.testTransfer(token.target, aliceWallet.address, bobWallet.address, 100); + expect(result[0]).to.be.equal(false); + expect(result[1]).to.be.equal(true); + expect(result[2]).to.be.equal(true); + }); + }); + + describe('When recipient is frozen', () => { + it('should return false', async () => { + const { + suite: { token }, + accounts: { tokenAgent, aliceWallet, bobWallet, deployer }, + } = await loadFixture(deployFullSuiteFixture); + await deployComplianceAndCountryAllowModule(token, deployer); + + const utilityChecker = await ethers.deployContract('UtilityChecker'); + + await token.connect(tokenAgent).setAddressFrozen(bobWallet.address, true); + const result = await utilityChecker.testTransfer(token.target, aliceWallet.address, bobWallet.address, 100); + expect(result[0]).to.be.equal(false); + expect(result[1]).to.be.equal(true); + expect(result[2]).to.be.equal(true); + }); + }); + + describe('When unfrozen balance is unsufficient', () => { + it('should return false', async () => { + const { + suite: { token }, + accounts: { tokenAgent, aliceWallet, bobWallet, deployer }, + } = await loadFixture(deployFullSuiteFixture); + await deployComplianceAndCountryAllowModule(token, deployer); + + const utilityChecker = await ethers.deployContract('UtilityChecker'); + + const initialBalance = await token.balanceOf(aliceWallet.address); + await token.connect(tokenAgent).freezePartialTokens(aliceWallet.address, initialBalance - 10n); + const result = await utilityChecker.testTransfer(token.target, aliceWallet.address, bobWallet.address, 100); + expect(result[0]).to.be.equal(false); + expect(result[1]).to.be.equal(true); + expect(result[2]).to.be.equal(true); + }); + }); + + describe('When nominal case', () => { + it('should return true', async () => { + const { + suite: { token, identityRegistry }, + accounts: { deployer, tokenAgent, aliceWallet, bobWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await deployComplianceAndCountryAllowModule(token, deployer); + await identityRegistry.connect(tokenAgent).updateCountry(bobWallet.address, 42); + + const utilityChecker = await ethers.deployContract('UtilityChecker'); + + const result = await utilityChecker.testTransfer(token.target, aliceWallet.address, bobWallet.address, 100); + expect(result[0]).to.be.equal(true); + expect(result[1]).to.be.equal(true); + expect(result[2]).to.be.equal(true); + }); + }); + + describe('When no identity is registered', () => { + it('should return false', async () => { + const { + suite: { token, identityRegistry }, + accounts: { deployer, tokenAgent, aliceWallet, bobWallet }, + } = await loadFixture(deployFullSuiteFixture); + await deployComplianceAndCountryAllowModule(token, deployer); + await identityRegistry.connect(tokenAgent).deleteIdentity(bobWallet.address); + + const utilityChecker = await ethers.deployContract('UtilityChecker'); + + const result = await utilityChecker.testTransfer(token.target, aliceWallet.address, bobWallet.address, 100); + expect(result[0]).to.be.equal(true); + expect(result[1]).to.be.equal(false); + expect(result[2]).to.be.equal(true); + }); + }); + + describe('When the identity is registered with topics', () => { + it('should return false', async () => { + const { + suite: { identityRegistry, token }, + accounts: { deployer, tokenAgent, aliceWallet, charlieWallet }, + identities: { charlieIdentity }, + } = await loadFixture(deployFullSuiteFixture); + + await identityRegistry.connect(tokenAgent).registerIdentity(charlieWallet.address, charlieIdentity.target, 0); + + await deployComplianceAndCountryAllowModule(token, deployer); + const utilityChecker = await ethers.deployContract('UtilityChecker'); + + const result = await utilityChecker.testTransfer(token.target, aliceWallet.address, charlieWallet.address, 100); + expect(result[0]).to.be.equal(true); + expect(result[1]).to.be.equal(false); + expect(result[2]).to.be.equal(true); + }); + }); + + describe('After fixture', () => { + it('should return true ', async () => { + const { + suite: { token, identityRegistry }, + accounts: { deployer, tokenAgent, aliceWallet, bobWallet }, + } = await loadFixture(deployFullSuiteFixture); + + await deployComplianceAndCountryAllowModule(token, deployer); + await identityRegistry.connect(tokenAgent).updateCountry(bobWallet.address, 42); + + const utilityChecker = await ethers.deployContract('UtilityChecker'); + const result = await utilityChecker.testTransfer(token.target, aliceWallet.address, bobWallet.address, 100); + expect(result[0]).to.be.equal(true); + expect(result[1]).to.be.equal(true); + expect(result[2]).to.be.equal(true); + }); + }); +}); diff --git a/test/utilities/upgrade.test.ts b/test/utilities/upgrade.test.ts new file mode 100644 index 00000000..8822d9d5 --- /dev/null +++ b/test/utilities/upgrade.test.ts @@ -0,0 +1,35 @@ +import { expect } from 'chai'; +import { ethers, upgrades } from 'hardhat'; + +describe('UtilityChecker.upgrateTo', () => { + describe('when calling directly', () => { + it('should revert', async () => { + const [, , , , , aliceWallet] = await ethers.getSigners(); + + const implementation = await ethers.deployContract('UtilityChecker'); + const proxy = await ethers.deployContract('UtilityCheckerProxy', [implementation.target, '0x8129fc1c']); + const utilityChecker = await ethers.getContractAt('UtilityChecker', proxy.target); + + const newImplementation = await ethers.deployContract('UtilityChecker'); + + await expect(utilityChecker.connect(aliceWallet).upgradeTo(newImplementation.target)).to.revertedWith('Ownable: caller is not the owner'); + }); + }); + + describe('when calling with owner account', () => { + it('should upgrade proxy', async () => { + const [deployer] = await ethers.getSigners(); + + const implementation = await ethers.deployContract('UtilityChecker'); + const proxy = await ethers.deployContract('UtilityCheckerProxy', [implementation.target, '0x8129fc1c']); + const utilityChecker = await ethers.getContractAt('UtilityChecker', proxy.target); + + const newImplementation = await ethers.deployContract('UtilityChecker'); + + await utilityChecker.connect(deployer).upgradeTo(newImplementation.target); + + const implementationAddress = await upgrades.erc1967.getImplementationAddress(utilityChecker.target as string); + expect(implementationAddress).to.eq(newImplementation.target); + }); + }); +}); From 36d1555a893dde382aebe81e0e1269cfa7bba95f Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Fri, 18 Oct 2024 11:09:46 +0200 Subject: [PATCH 43/55] =?UTF-8?q?=F0=9F=93=9D()=20Update=20changelog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 141088ef..9fb7906f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,13 @@ All notable changes to this project will be documented in this file. - **Custom Errors for Require Statements**: All `require` clauses that previously returned a string reason for failure have been updated to use **custom errors**, making debugging easier and more efficient. - This upgrade provides a cleaner, more efficient error handling process and improves overall code structure without affecting backward compatibility. +- **Utility checker**: + - Add a new utility contract to check for freeze status, eligibility and compliance of an address for a token: + - Test if the transfer of tokens will fail + - Test the eligibility of an address for a token + - Test the compliance of an address for a token + - Test the freeze status of an address for a token + ### Updated - **Token Recovery Function**: From c9c77108e83fa42c4f8ca3c7e134c962f6a04a09 Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Wed, 20 Nov 2024 09:51:37 +0100 Subject: [PATCH 44/55] =?UTF-8?q?=E2=9C=A8()=20Investor=20country=20cap=20?= =?UTF-8?q?module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 + .../modules/InvestorCountryCapModule.sol | 299 ++++++++++++++++++ index.d.ts | 1 + index.js | 2 + 4 files changed, 305 insertions(+) create mode 100644 contracts/compliance/modular/modules/InvestorCountryCapModule.sol diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b92485b..e089cbc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ All notable changes to this project will be documented in this file. WHITELISTING: investors must whitelist/allow the token address in order to receive it. BLACKLISTING: investors can receive the token by default. If they do not want to receive it, they need to blacklist/disallow it. +- Introduced **Investor Country Cap Module**: to limit the number of identities per country. + - The module allows the token owner to set a maximum number of identities per country. + - **Default Allowance Mechanism**: - Introduced a new feature allowing the contract owner to set certain addresses as trusted external smart contracts, enabling them to use `transferFrom` without requiring an explicit allowance from users. By default, users are opted in, allowing these contracts to have an "infinite allowance". Users can opt-out if they prefer to control allowances manually. - Added custom errors and events to provide better feedback and traceability: diff --git a/contracts/compliance/modular/modules/InvestorCountryCapModule.sol b/contracts/compliance/modular/modules/InvestorCountryCapModule.sol new file mode 100644 index 00000000..83febf72 --- /dev/null +++ b/contracts/compliance/modular/modules/InvestorCountryCapModule.sol @@ -0,0 +1,299 @@ +// SPDX-License-Identifier: GPL-3.0 +// This contract is also licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2024, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This specific smart contract is also licensed under the Creative Commons + * Attribution-NonCommercial 4.0 International License (CC-BY-NC-4.0), + * which prohibits commercial use. For commercial inquiries, please contact + * Tokeny sàrl for licensing options. + */ + +pragma solidity 0.8.27; + +import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import "./AbstractModuleUpgradeable.sol"; +import "../IModularCompliance.sol"; +import "../../../token/IToken.sol"; +import "../../../roles/AgentRole.sol"; + +event CountryCapSet(uint16 indexed country, uint256 cap); +event BypassedIdentityAdded(address indexed identity); +event BypassedIdentityRemoved(address indexed identity); + +error IdentityNotBypassed(address identity); +error CapLowerThanCurrent(uint16 country, uint256 cap, uint256 currentCap); +error WalletCountLimitReached(address identity, uint256 maxWallets); + +uint256 constant MAX_WALLET_PER_IDENTITY = 20; + + +contract InvestorCountryCapModule is AbstractModuleUpgradeable { + using EnumerableSet for EnumerableSet.AddressSet; + using EnumerableSet for EnumerableSet.UintSet; + + struct CountryParams { + bool capped; + uint256 cap; + uint256 count; + mapping(address identity => bool counted) identities; + } + + EnumerableSet.UintSet private _countries; + mapping(uint16 country => CountryParams params) private _countryParams; + mapping(address identity => bool bypassed) private _bypassedIdentities; + + mapping(address identity => EnumerableSet.AddressSet wallets) private _identityToWallets; + + /// @dev initializes the contract and sets the initial state. + /// @notice This function should only be called once during the contract deployment. + function initialize() external initializer { + __AbstractModule_init(); + + // TODO + } + + /// @dev Set the cap for a country + /// @param _country Country code + /// @param _cap New cap + function setCountryCap(uint16 _country, uint256 _cap) external onlyComplianceCall { + CountryParams storage params = _countryParams[_country]; + + // Can't set cap lower than current cap + if (_cap < params.cap) { + revert CapLowerThanCurrent(_country, _cap, params.cap); + } + + params.capped = true; + params.cap = _cap; + + _countries.add(_country); + + emit CountryCapSet(_country, _cap); + } + + /// @dev Add an identity to the list of bypassed identities + /// @param _identity Address of the identity + function addBypassedIdentity(address _identity) external onlyComplianceCall { + _bypassedIdentities[_identity] = true; + + emit BypassedIdentityAdded(_identity); + } + + /// @dev Remove an identity from the list of bypassed identities + /// @param _identity Address of the identity + function removeBypassedIdentity(address _identity) external onlyComplianceCall { + require(_bypassedIdentities[_identity], IdentityNotBypassed(_identity)); + _bypassedIdentities[_identity] = false; + + emit BypassedIdentityRemoved(_identity); + } + + /// @inheritdoc IModule + function moduleBurnAction(address _from, uint256 /*_value*/) external onlyComplianceCall { + address _idFrom = _getIdentity(msg.sender, _from); + + uint16 country = _getCountry(msg.sender, _from); + _removeWalletIfNoBalance(_idFrom, country); + } + + /// @inheritdoc IModule + function moduleMintAction(address _to, uint256 /*_value*/) external onlyComplianceCall { + address _idTo = _getIdentity(msg.sender, _to); + + if (_bypassedIdentities[_idTo]) { + return; + } + + uint16 country = _getCountry(msg.sender, _to); + _registerWallet(_to, _idTo, country); + } + + /// @inheritdoc IModule + function moduleTransferAction(address _from, address _to, uint256 /*_value*/) external onlyComplianceCall { + address _idTo = _getIdentity(msg.sender, _to); + + if (_bypassedIdentities[_idTo]) { + return; + } + + uint16 country = _getCountry(msg.sender, _to); + if (!_countryParams[country].capped) { + return; + } + + _registerWallet(_to, _idTo, country); + _removeWalletIfNoBalance(_getIdentity(msg.sender, _from), country); + } + + /// @inheritdoc IModule + function moduleCheck(address _from, address _to, uint256 /*_value*/, address _compliance) external view returns (bool) { + address _idFrom = _getIdentity(_compliance, _from); + address _idTo = _getIdentity(_compliance, _to); + + // Bypassed identity are always allowed + if (_bypassedIdentities[_idFrom]) { + return true; + } + + uint16 country = _getCountry(_compliance, _to); + CountryParams storage params = _countryParams[country]; + + // If country is not capped, allow transfer + if (!params.capped) { + return true; + } + + // If identity is already counted, allow transfer + if (params.identities[_idTo]) { + return true; + } + + // Check if adding new identity would exceed cap or max wallets per identity + return params.count + 1 <= params.cap && _identityToWallets[_idTo].length() + 1 < MAX_WALLET_PER_IDENTITY; + } + + /// @inheritdoc IModule + function canComplianceBind(address /*_compliance*/) external view override returns (bool) { + return true; + } + + /// @inheritdoc IModule + function isPlugAndPlay() public pure override returns (bool) { + return false; + } + + /// @inheritdoc IModule + function name() public pure override returns (string memory) { + return "InvestorCountryCapModule"; + } + + /// @dev Register a wallet for an identity, and check for country change + /// @param _wallet Address of the wallet + /// @param _identity Address of the identity + /// @param _country Country code + function _registerWallet(address _wallet, address _identity, uint16 _country) internal { + IToken token = IToken(IModularCompliance(msg.sender).getTokenBound()); + CountryParams storage params = _countryParams[_country]; + + // Register wallet for this country if not already registered + if (!params.identities[_identity]) { + if (token.balanceOf(_wallet) > 0) { + // Wallet has a balance, either: + // - User have several countries (Identity already registered) + // - User country has changed + if (_identityToWallets[_identity].length() == 0) { + uint256 countryCount = _countries.length(); + for (uint16 i; i < countryCount; i++) { + uint16 otherCountry = uint16(_countries.at(i)); + if (otherCountry != _country && _countryParams[otherCountry].identities[_identity]) { + // Unlink previous country + _countryParams[otherCountry].identities[_identity] = false; + _countryParams[otherCountry].count--; + } + } + } + } + + params.count++; + params.identities[_identity] = true; + } + + _identityToWallets[_identity].add(_wallet); + } + + /// @dev Remove a wallet from an identity if no balance + /// @param _identity Address of the identity + /// @param _country Country code + function _removeWalletIfNoBalance(address _identity, uint16 _country) internal { + if (_bypassedIdentities[_identity]) { + return; + } + + IToken token = IToken(IModularCompliance(msg.sender).getTokenBound()); + uint256 walletCount = _identityToWallets[_identity].length(); + uint256 balance; + for (uint256 i; i < walletCount; i++) { + balance += token.balanceOf(_identityToWallets[_identity].at(i)); + } + + // If balance is 0, the identity has no more wallets and should be uncounted + if (balance == 0) { + _countryParams[_country].count--; + _countryParams[_country].identities[_identity] = false; + } + } + + /// @dev Returns the country code of the wallet owner + /// @param _compliance Address of the compliance + /// @param _userAddress Address of the wallet + function _getCountry(address _compliance, address _userAddress) internal view returns (uint16) { + return IToken(IModularCompliance(_compliance).getTokenBound()).identityRegistry().investorCountry(_userAddress); + } + + /// @dev Returns the ONCHAINID (Identity) of the _userAddress + /// @param _compliance Address of the compliance + /// @param _userAddress Address of the wallet + function _getIdentity(address _compliance, address _userAddress) internal view returns (address) { + return address(IToken(IModularCompliance(_compliance).getTokenBound()).identityRegistry().identity + (_userAddress)); + } + +} diff --git a/index.d.ts b/index.d.ts index ee7dea56..178fad0e 100644 --- a/index.d.ts +++ b/index.d.ts @@ -72,6 +72,7 @@ export namespace contracts { export const TransferFeesModule: ContractJSON; export const TransferRestrictModule: ContractJSON; export const TokenListingRestrictionsModule: ContractJSON; + export const InvestorCountryCapModule: ContractJSON; } export namespace interfaces { diff --git a/index.js b/index.js index 5dc0f284..c34e4ac0 100644 --- a/index.js +++ b/index.js @@ -74,6 +74,7 @@ const SupplyLimitModule = require('./artifacts/contracts/compliance/modular/modu const TransferFeesModule = require('./artifacts/contracts/compliance/modular/modules/TransferFeesModule.sol/TransferFeesModule.json'); const TransferRestrictModule = require('./artifacts/contracts/compliance/modular/modules/TransferRestrictModule.sol/TransferRestrictModule.json'); const TokenListingRestrictionsModule = require('./artifacts/contracts/compliance/modular/modules/TokenListingRestrictionsModule.sol/TokenListingRestrictionsModule.json'); +const InvestorCountryCapModule = require('./artifacts/contracts/compliance/modular/modules/InvestorCountryCapModule.sol/InvestorCountryCapModule.json'); module.exports = { contracts: { @@ -139,6 +140,7 @@ module.exports = { TransferFeesModule, TransferRestrictModule, TokenListingRestrictionsModule, + InvestorCountryCapModule, }, interfaces: { IToken, From 8139b0c28a719855a79e51d42b2173999c641f7c Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Wed, 20 Nov 2024 09:55:16 +0100 Subject: [PATCH 45/55] =?UTF-8?q?=E2=99=BB()=20Initialize=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/InvestorCountryCapModule.sol | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/contracts/compliance/modular/modules/InvestorCountryCapModule.sol b/contracts/compliance/modular/modules/InvestorCountryCapModule.sol index 83febf72..91ca9b2e 100644 --- a/contracts/compliance/modular/modules/InvestorCountryCapModule.sol +++ b/contracts/compliance/modular/modules/InvestorCountryCapModule.sol @@ -103,11 +103,24 @@ contract InvestorCountryCapModule is AbstractModuleUpgradeable { mapping(address identity => EnumerableSet.AddressSet wallets) private _identityToWallets; /// @dev initializes the contract and sets the initial state. + /// @param _compliance Address of the compliance. + /// @param _holders Addresses of the holders already holding tokens. /// @notice This function should only be called once during the contract deployment. - function initialize() external initializer { + function initialize(address _compliance, address[] memory _holders) external initializer { __AbstractModule_init(); - // TODO + uint256 holdersCount = _holders.length; + for (uint256 i; i < holdersCount; i++) { + address holder = _holders[i]; + address idTo = _getIdentity(_compliance, holder); + + if (_bypassedIdentities[idTo]) { + return; + } + + uint16 country = _getCountry(_compliance, holder); + _registerWallet(holder, idTo, country); + } } /// @dev Set the cap for a country From 09776e96ff5178c2501a4549732472e2f28f47fb Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Fri, 22 Nov 2024 09:07:59 +0100 Subject: [PATCH 46/55] =?UTF-8?q?=E2=99=BB()=20Update=20after=20review?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/InvestorCountryCapModule.sol | 80 +++++++++++-------- 1 file changed, 47 insertions(+), 33 deletions(-) diff --git a/contracts/compliance/modular/modules/InvestorCountryCapModule.sol b/contracts/compliance/modular/modules/InvestorCountryCapModule.sol index 91ca9b2e..a88fac0e 100644 --- a/contracts/compliance/modular/modules/InvestorCountryCapModule.sol +++ b/contracts/compliance/modular/modules/InvestorCountryCapModule.sol @@ -96,19 +96,30 @@ contract InvestorCountryCapModule is AbstractModuleUpgradeable { mapping(address identity => bool counted) identities; } - EnumerableSet.UintSet private _countries; - mapping(uint16 country => CountryParams params) private _countryParams; - mapping(address identity => bool bypassed) private _bypassedIdentities; + EnumerableSet.UintSet internal _countries; + mapping(address identity => bool bypassed) internal _bypassedIdentities; - mapping(address identity => EnumerableSet.AddressSet wallets) private _identityToWallets; + mapping(address compliance => mapping(uint16 country => CountryParams params)) internal _countryParams; + mapping(address compliance => mapping(address identity => EnumerableSet.AddressSet wallets)) internal _identityToWallets; + + /// @notice Used only during batchInitialize / canComplianceBind + mapping(address token => uint256 supply) public calculatedSupply; + /// @dev initializes the contract and sets the initial state. - /// @param _compliance Address of the compliance. - /// @param _holders Addresses of the holders already holding tokens. - /// @notice This function should only be called once during the contract deployment. - function initialize(address _compliance, address[] memory _holders) external initializer { + /// @notice This function should only be called once during the contract deployment, and after (optionally) batchInitialize. + function initialize() external initializer { __AbstractModule_init(); + } + /// @dev Initialize the module for a compliance and a list of holders + /// @param _compliance Address of the compliance. + /// @param _holders Addresses of the holders already holding tokens (addresses should be unique - no control is done on that). + /// @notice This function should only be called before initialize. + function batchInitialize(address _compliance, address[] memory _holders) external onlyOwner { + // TODO calculate gas cost and revert if _holders.length is too high + + IToken token = IToken(IModularCompliance(_compliance).getTokenBound()); uint256 holdersCount = _holders.length; for (uint256 i; i < holdersCount; i++) { address holder = _holders[i]; @@ -118,8 +129,9 @@ contract InvestorCountryCapModule is AbstractModuleUpgradeable { return; } - uint16 country = _getCountry(_compliance, holder); - _registerWallet(holder, idTo, country); + _registerWallet(_compliance, holder, idTo, _getCountry(_compliance, holder)); + + calculatedSupply[address(token)] += token.balanceOf(holder); } } @@ -127,7 +139,7 @@ contract InvestorCountryCapModule is AbstractModuleUpgradeable { /// @param _country Country code /// @param _cap New cap function setCountryCap(uint16 _country, uint256 _cap) external onlyComplianceCall { - CountryParams storage params = _countryParams[_country]; + CountryParams storage params = _countryParams[msg.sender][_country]; // Can't set cap lower than current cap if (_cap < params.cap) { @@ -176,7 +188,7 @@ contract InvestorCountryCapModule is AbstractModuleUpgradeable { } uint16 country = _getCountry(msg.sender, _to); - _registerWallet(_to, _idTo, country); + _registerWallet(msg.sender, _to, _idTo, country); } /// @inheritdoc IModule @@ -188,26 +200,25 @@ contract InvestorCountryCapModule is AbstractModuleUpgradeable { } uint16 country = _getCountry(msg.sender, _to); - if (!_countryParams[country].capped) { + if (!_countryParams[msg.sender][country].capped) { return; } - _registerWallet(_to, _idTo, country); + _registerWallet(msg.sender, _to, _idTo, country); _removeWalletIfNoBalance(_getIdentity(msg.sender, _from), country); } /// @inheritdoc IModule - function moduleCheck(address _from, address _to, uint256 /*_value*/, address _compliance) external view returns (bool) { - address _idFrom = _getIdentity(_compliance, _from); + function moduleCheck(address /*_from*/, address _to, uint256 /*_value*/, address _compliance) external view returns (bool) { address _idTo = _getIdentity(_compliance, _to); // Bypassed identity are always allowed - if (_bypassedIdentities[_idFrom]) { + if (_bypassedIdentities[_idTo]) { return true; } uint16 country = _getCountry(_compliance, _to); - CountryParams storage params = _countryParams[country]; + CountryParams storage params = _countryParams[_compliance][country]; // If country is not capped, allow transfer if (!params.capped) { @@ -220,12 +231,14 @@ contract InvestorCountryCapModule is AbstractModuleUpgradeable { } // Check if adding new identity would exceed cap or max wallets per identity - return params.count + 1 <= params.cap && _identityToWallets[_idTo].length() + 1 < MAX_WALLET_PER_IDENTITY; + return params.count < params.cap && _identityToWallets[_compliance][_idTo].length() < MAX_WALLET_PER_IDENTITY; } /// @inheritdoc IModule - function canComplianceBind(address /*_compliance*/) external view override returns (bool) { - return true; + function canComplianceBind(address _compliance) external view override returns (bool) { + IToken token = IToken(IModularCompliance(_compliance).getTokenBound()); + + return token.paused() && calculatedSupply[address(token)] == token.totalSupply(); } /// @inheritdoc IModule @@ -239,12 +252,13 @@ contract InvestorCountryCapModule is AbstractModuleUpgradeable { } /// @dev Register a wallet for an identity, and check for country change + /// @param _compliance Address of the compliance /// @param _wallet Address of the wallet /// @param _identity Address of the identity /// @param _country Country code - function _registerWallet(address _wallet, address _identity, uint16 _country) internal { - IToken token = IToken(IModularCompliance(msg.sender).getTokenBound()); - CountryParams storage params = _countryParams[_country]; + function _registerWallet(address _compliance, address _wallet, address _identity, uint16 _country) internal { + IToken token = IToken(IModularCompliance(_compliance).getTokenBound()); + CountryParams storage params = _countryParams[_compliance][_country]; // Register wallet for this country if not already registered if (!params.identities[_identity]) { @@ -252,14 +266,14 @@ contract InvestorCountryCapModule is AbstractModuleUpgradeable { // Wallet has a balance, either: // - User have several countries (Identity already registered) // - User country has changed - if (_identityToWallets[_identity].length() == 0) { + if (_identityToWallets[_compliance][_identity].length() == 0) { uint256 countryCount = _countries.length(); for (uint16 i; i < countryCount; i++) { uint16 otherCountry = uint16(_countries.at(i)); - if (otherCountry != _country && _countryParams[otherCountry].identities[_identity]) { + if (otherCountry != _country && _countryParams[_compliance][otherCountry].identities[_identity]) { // Unlink previous country - _countryParams[otherCountry].identities[_identity] = false; - _countryParams[otherCountry].count--; + _countryParams[_compliance][otherCountry].identities[_identity] = false; + _countryParams[_compliance][otherCountry].count--; } } } @@ -269,7 +283,7 @@ contract InvestorCountryCapModule is AbstractModuleUpgradeable { params.identities[_identity] = true; } - _identityToWallets[_identity].add(_wallet); + _identityToWallets[_compliance][_identity].add(_wallet); } /// @dev Remove a wallet from an identity if no balance @@ -281,16 +295,16 @@ contract InvestorCountryCapModule is AbstractModuleUpgradeable { } IToken token = IToken(IModularCompliance(msg.sender).getTokenBound()); - uint256 walletCount = _identityToWallets[_identity].length(); + uint256 walletCount = _identityToWallets[msg.sender][_identity].length(); uint256 balance; for (uint256 i; i < walletCount; i++) { - balance += token.balanceOf(_identityToWallets[_identity].at(i)); + balance += token.balanceOf(_identityToWallets[msg.sender][_identity].at(i)); } // If balance is 0, the identity has no more wallets and should be uncounted if (balance == 0) { - _countryParams[_country].count--; - _countryParams[_country].identities[_identity] = false; + _countryParams[msg.sender][_country].count--; + _countryParams[msg.sender][_country].identities[_identity] = false; } } From a42e1383fdcf2f3af6705b65d8c10830f647a52f Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Mon, 25 Nov 2024 06:49:58 +0100 Subject: [PATCH 47/55] =?UTF-8?q?=E2=9C=85(test)=20BT-360=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/InvestorCountryCapModule.sol | 18 +- .../module-investor-country-cap.test.ts | 249 ++++++++++++++++++ 2 files changed, 261 insertions(+), 6 deletions(-) create mode 100644 test/compliances/module-investor-country-cap.test.ts diff --git a/contracts/compliance/modular/modules/InvestorCountryCapModule.sol b/contracts/compliance/modular/modules/InvestorCountryCapModule.sol index a88fac0e..4281261b 100644 --- a/contracts/compliance/modular/modules/InvestorCountryCapModule.sol +++ b/contracts/compliance/modular/modules/InvestorCountryCapModule.sol @@ -78,6 +78,7 @@ event CountryCapSet(uint16 indexed country, uint256 cap); event BypassedIdentityAdded(address indexed identity); event BypassedIdentityRemoved(address indexed identity); +error ExpectedPause(); error IdentityNotBypassed(address identity); error CapLowerThanCurrent(uint16 country, uint256 cap, uint256 currentCap); error WalletCountLimitReached(address identity, uint256 maxWallets); @@ -115,11 +116,12 @@ contract InvestorCountryCapModule is AbstractModuleUpgradeable { /// @dev Initialize the module for a compliance and a list of holders /// @param _compliance Address of the compliance. /// @param _holders Addresses of the holders already holding tokens (addresses should be unique - no control is done on that). - /// @notice This function should only be called before initialize. function batchInitialize(address _compliance, address[] memory _holders) external onlyOwner { // TODO calculate gas cost and revert if _holders.length is too high IToken token = IToken(IModularCompliance(_compliance).getTokenBound()); + require(token.paused(), ExpectedPause()); + uint256 holdersCount = _holders.length; for (uint256 i; i < holdersCount; i++) { address holder = _holders[i]; @@ -225,13 +227,17 @@ contract InvestorCountryCapModule is AbstractModuleUpgradeable { return true; } - // If identity is already counted, allow transfer - if (params.identities[_idTo]) { - return true; + // If identity is not already counted, check cap + if (!params.identities[_idTo]) { + return params.count < params.cap; + } + + // Check max wallets per identity + if (!_identityToWallets[_compliance][_idTo].contains(_to)) { + return _identityToWallets[_compliance][_idTo].length() + 1 < MAX_WALLET_PER_IDENTITY; } - // Check if adding new identity would exceed cap or max wallets per identity - return params.count < params.cap && _identityToWallets[_compliance][_idTo].length() < MAX_WALLET_PER_IDENTITY; + return true; } /// @inheritdoc IModule diff --git a/test/compliances/module-investor-country-cap.test.ts b/test/compliances/module-investor-country-cap.test.ts new file mode 100644 index 00000000..3f4d91e7 --- /dev/null +++ b/test/compliances/module-investor-country-cap.test.ts @@ -0,0 +1,249 @@ +import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { ethers } from 'hardhat'; +import { expect } from 'chai'; +import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; + +describe('InvestorCountryCapModule', () => { + // Test fixture + async function deployIvestorCountryCapModuleFullSuite() { + const context = await loadFixture(deploySuiteWithModularCompliancesFixture); + + const module = await ethers.deployContract('InvestorCountryCapModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('InvestorCountryCapModule', proxy.target); + + await context.suite.compliance.bindToken(context.suite.token.target); + + await context.suite.token.connect(context.accounts.tokenAgent).pause(); + await complianceModule.batchInitialize(context.suite.compliance.target, [ + context.accounts.aliceWallet.address, + context.accounts.bobWallet.address, + ]); + await context.suite.compliance.addModule(complianceModule.target); + await context.suite.token.connect(context.accounts.tokenAgent).unpause(); + + return { + ...context, + suite: { + ...context.suite, + complianceModule, + }, + }; + } + + describe('Initialization', () => { + it('should initialize correctly', async () => { + const { + suite: { complianceModule }, + } = await loadFixture(deployIvestorCountryCapModuleFullSuite); + + expect(await complianceModule.name()).to.equal('InvestorCountryCapModule'); + expect(await complianceModule.isPlugAndPlay()).to.be.false; + }); + }); + + describe('Country Cap Management', () => { + it('should revert when calling directly', async () => { + const { + suite: { complianceModule }, + } = await loadFixture(deployIvestorCountryCapModuleFullSuite); + + await expect(complianceModule.setCountryCap(840, 100)).to.be.revertedWithCustomError(complianceModule, 'OnlyBoundComplianceCanCall'); + }); + + it('should set country cap correctly', async () => { + const { + suite: { compliance, complianceModule }, + } = await loadFixture(deployIvestorCountryCapModuleFullSuite); + + const countryCode = 840; // USA + const cap = 100; + + const tx = await compliance.callModuleFunction( + new ethers.Interface(['function setCountryCap(uint16 _country, uint256 _cap)']).encodeFunctionData('setCountryCap', [countryCode, cap]), + complianceModule.target, + ); + + await expect(tx).to.emit(complianceModule, 'CountryCapSet').withArgs(countryCode, cap); + }); + + it('should revert when setting cap lower than current count', async () => { + const { + suite: { compliance, complianceModule }, + } = await loadFixture(deployIvestorCountryCapModuleFullSuite); + + const countryCode = 840; // USA + const cap = 100; + + await compliance.callModuleFunction( + new ethers.Interface(['function setCountryCap(uint16 _country, uint256 _cap)']).encodeFunctionData('setCountryCap', [countryCode, cap]), + complianceModule.target, + ); + + // Try to set cap lower than current count + await expect( + compliance.callModuleFunction( + new ethers.Interface(['function setCountryCap(uint16 _country, uint256 _cap)']).encodeFunctionData('setCountryCap', [countryCode, cap - 1]), + complianceModule.target, + ), + ).to.be.revertedWithCustomError(complianceModule, 'CapLowerThanCurrent'); + }); + }); + + describe('Bypassed Identity Management', () => { + it('should add bypassed identity correctly', async () => { + const { + suite: { compliance, complianceModule }, + accounts: { aliceWallet }, + } = await loadFixture(deployIvestorCountryCapModuleFullSuite); + + const tx = await compliance.callModuleFunction( + new ethers.Interface(['function addBypassedIdentity(address _identity)']).encodeFunctionData('addBypassedIdentity', [aliceWallet.address]), + complianceModule.target, + ); + await expect(tx).to.emit(complianceModule, 'BypassedIdentityAdded').withArgs(aliceWallet.address); + }); + + it('should revert if trying to remove bypassed identity that is not bypassed', async () => { + const { + suite: { compliance, complianceModule }, + accounts: { aliceWallet }, + } = await loadFixture(deployIvestorCountryCapModuleFullSuite); + + await expect( + compliance.callModuleFunction( + new ethers.Interface(['function removeBypassedIdentity(address _identity)']).encodeFunctionData('removeBypassedIdentity', [ + aliceWallet.address, + ]), + complianceModule.target, + ), + ).to.be.revertedWithCustomError(complianceModule, 'IdentityNotBypassed'); + }); + + it('should remove bypassed identity correctly', async () => { + const { + suite: { compliance, complianceModule }, + accounts: { aliceWallet }, + } = await loadFixture(deployIvestorCountryCapModuleFullSuite); + + await compliance.callModuleFunction( + new ethers.Interface(['function addBypassedIdentity(address _identity)']).encodeFunctionData('addBypassedIdentity', [aliceWallet.address]), + complianceModule.target, + ); + + const tx = await compliance.callModuleFunction( + new ethers.Interface(['function removeBypassedIdentity(address _identity)']).encodeFunctionData('removeBypassedIdentity', [ + aliceWallet.address, + ]), + complianceModule.target, + ); + await expect(tx).to.emit(complianceModule, 'BypassedIdentityRemoved').withArgs(aliceWallet.address); + }); + }); + + describe('Transfer Checks', () => { + it('should allow transfer for bypassed identity', async () => { + const { + suite: { compliance, complianceModule }, + accounts: { aliceWallet }, + } = await loadFixture(deployIvestorCountryCapModuleFullSuite); + + await compliance.callModuleFunction( + new ethers.Interface(['function addBypassedIdentity(address _identity)']).encodeFunctionData('addBypassedIdentity', [aliceWallet.address]), + complianceModule.target, + ); + + expect(await complianceModule.moduleCheck(aliceWallet.address, aliceWallet.address, 100, compliance.target)).to.be.true; + }); + + it('should allow transfer when country is not capped', async () => { + const { + suite: { compliance, complianceModule }, + accounts: { aliceWallet }, + } = await loadFixture(deployIvestorCountryCapModuleFullSuite); + + expect(await complianceModule.moduleCheck(aliceWallet.address, aliceWallet.address, 100, compliance.target)).to.be.true; + }); + + it('should enforce country cap', async () => { + const { + suite: { compliance, complianceModule, identityRegistry }, + accounts: { aliceWallet, charlieWallet, tokenAgent }, + identities: { charlieIdentity }, + } = await loadFixture(deployIvestorCountryCapModuleFullSuite); + + const aliceCountry = await identityRegistry.investorCountry(aliceWallet.address); + await compliance.callModuleFunction( + new ethers.Interface(['function setCountryCap(uint16 _country, uint256 _cap)']).encodeFunctionData('setCountryCap', [aliceCountry, 1]), + complianceModule.target, + ); + + await identityRegistry.connect(tokenAgent).registerIdentity(charlieWallet.address, charlieIdentity, aliceCountry); + + expect(await complianceModule.moduleCheck(aliceWallet.address, charlieWallet.address, 100, compliance.target)).to.be.false; + }); + }); + + describe('Wallet Management', () => { + it('should enforce wallet per identity limit', async () => { + const { + suite: { compliance, complianceModule, identityRegistry }, + accounts: { tokenAgent, aliceWallet }, + identities: { aliceIdentity }, + } = await loadFixture(deployIvestorCountryCapModuleFullSuite); + + const aliceCountry = await identityRegistry.investorCountry(aliceWallet.address); + await compliance.callModuleFunction( + new ethers.Interface(['function setCountryCap(uint16 _country, uint256 _cap)']).encodeFunctionData('setCountryCap', [aliceCountry, 100]), + complianceModule.target, + ); + + await Promise.all( + Array(21) + .fill(0) + .map(async () => { + const wallet = ethers.Wallet.createRandom().connect(ethers.provider); + await identityRegistry.connect(tokenAgent).registerIdentity(wallet.address, aliceIdentity, aliceCountry); + + expect(await complianceModule.moduleCheck(aliceWallet.address, wallet.address, 10, compliance.target)).to.be.true; + await compliance.callModuleFunction( + new ethers.Interface(['function moduleMintAction(address, uint256)']).encodeFunctionData('moduleMintAction', [wallet.address, 10]), + complianceModule.target, + ); + return wallet; + }), + ); + + const wallet = ethers.Wallet.createRandom().connect(ethers.provider); + await identityRegistry.connect(tokenAgent).registerIdentity(wallet.address, aliceIdentity, aliceCountry); + + // This should fail + expect(await complianceModule.moduleCheck(aliceWallet.address, wallet.address, 100, compliance.target)).to.be.false; + }); + }); + + describe('Country Change Handling', () => { + it('should handle country change correctly', async () => { + const { + suite: { compliance, complianceModule, identityRegistry }, + accounts: { aliceWallet, tokenAgent }, + } = await loadFixture(deployIvestorCountryCapModuleFullSuite); + + const newCountry = 250; // France + + await compliance.callModuleFunction( + new ethers.Interface(['function setCountryCap(uint16 _country, uint256 _cap)']).encodeFunctionData('setCountryCap', [newCountry, 10]), + complianceModule.target, + ); + + // Setup initial state + expect(await complianceModule.moduleCheck(aliceWallet.address, aliceWallet.address, 100, compliance.target)).to.be.true; + + // Change country + await identityRegistry.connect(tokenAgent).updateCountry(aliceWallet.address, newCountry); + + // Should still be able to transfer after country change + expect(await complianceModule.moduleCheck(aliceWallet.address, aliceWallet.address, 100, compliance.target)).to.be.true; + }); + }); +}); From c0bda1406e10db5336955c759523c9899a98fbaa Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Sun, 1 Dec 2024 16:51:27 +0100 Subject: [PATCH 48/55] =?UTF-8?q?=E2=9C=A8()=20Minimum=20transfer=20by=20c?= =?UTF-8?q?ountry=20module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/MinTransferByCountryModule.sol | 108 ++++++++++ index.d.ts | 1 + index.js | 2 +- .../module-min-transfer-by-country.ts | 204 ++++++++++++++++++ 4 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 contracts/compliance/modular/modules/MinTransferByCountryModule.sol create mode 100644 test/compliances/module-min-transfer-by-country.ts diff --git a/contracts/compliance/modular/modules/MinTransferByCountryModule.sol b/contracts/compliance/modular/modules/MinTransferByCountryModule.sol new file mode 100644 index 00000000..95be2bca --- /dev/null +++ b/contracts/compliance/modular/modules/MinTransferByCountryModule.sol @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.8.27; + +import "../IModularCompliance.sol"; +import "../../../token/IToken.sol"; +import "./AbstractModuleUpgradeable.sol"; + + event MinimumTransferAmountSet(uint16 indexed country, uint256 amount); + + +/** + * @title MinTransferByCountry Module + * @dev Enforces minimum transfer amounts for token holders from specified countries + * when creating new investors for that country + */ +contract MinTransferByCountryModule is AbstractModuleUpgradeable { + + mapping(address compliance => mapping(uint16 country => uint256 minAmount)) private _minimumTransferAmounts; + + function initialize() external initializer { + __AbstractModule_init(); + } + + /** + * @dev Sets minimum transfer amount for a country + * @param country Country code + * @param amount Minimum transfer amount + */ + function setMinimumTransferAmount(uint16 country, uint256 amount) external onlyComplianceCall { + _minimumTransferAmounts[msg.sender][country] = amount; + + emit MinimumTransferAmountSet(country, amount); + } + + /// @inheritdoc IModule + // solhint-disable-next-line no-empty-blocks + function moduleTransferAction(address _from, address _to, uint256 _value) external {} + + /// @inheritdoc IModule + // solhint-disable-next-line no-empty-blocks + function moduleMintAction(address _to, uint256 _value) external {} + + /// @inheritdoc IModule + // solhint-disable-next-line no-empty-blocks + function moduleBurnAction(address _from, uint256 _value) external {} + + /// @inheritdoc IModule + function moduleCheck( + address _from, + address _to, + uint256 _amount, + address _compliance + ) external view override returns (bool) { + uint16 recipientCountry = _getCountry(_compliance, _to); + if (_minimumTransferAmounts[_compliance][recipientCountry] == 0) { + return true; + } + + // Check for internal transfer in same country + address idFrom = _getIdentity(_compliance, _from); + address idTo = _getIdentity(_compliance, _to); + if (idFrom == idTo) { + uint16 senderCountry = _getCountry(_compliance, _from); + return senderCountry == recipientCountry + || _amount >= _minimumTransferAmounts[_compliance][recipientCountry]; + } + + IToken token = IToken(IModularCompliance(_compliance).getTokenBound()); + // Check for new user + return token.balanceOf(_to) > 0 + || _amount >= _minimumTransferAmounts[_compliance][recipientCountry]; + } + + /// @inheritdoc IModule + function canComplianceBind(address /*_compliance*/) external view override returns (bool) { + return true; + } + + /// @inheritdoc IModule + function isPlugAndPlay() external pure override returns (bool) { + return true; + } + + /** + * @dev Module name + */ + function name() public pure returns (string memory) { + return "MinTransferByCountryModule"; + } + + + /// @dev function used to get the country of a wallet address. + /// @param _compliance the compliance contract address for which the country verification is required + /// @param _userAddress the address of the wallet to be checked + /// @return the ISO 3166-1 standard country code of the wallet owner + function _getCountry(address _compliance, address _userAddress) internal view returns (uint16) { + return IToken(IModularCompliance(_compliance).getTokenBound()).identityRegistry().investorCountry(_userAddress); + } + + /// @dev Returns the ONCHAINID (Identity) of the _userAddress + /// @param _compliance the compliance contract address for which the country verification is required + /// @param _userAddress Address of the wallet + /// @return the ONCHAINID (Identity) of the _userAddress + function _getIdentity(address _compliance, address _userAddress) internal view returns (address) { + return address(IToken(IModularCompliance(_compliance).getTokenBound()).identityRegistry().identity + (_userAddress)); + } +} \ No newline at end of file diff --git a/index.d.ts b/index.d.ts index ee7dea56..fdbd9990 100644 --- a/index.d.ts +++ b/index.d.ts @@ -72,6 +72,7 @@ export namespace contracts { export const TransferFeesModule: ContractJSON; export const TransferRestrictModule: ContractJSON; export const TokenListingRestrictionsModule: ContractJSON; + export const MinTransferByCountrytModule: ContractJSON; } export namespace interfaces { diff --git a/index.js b/index.js index 5dc0f284..9b2bb1fc 100644 --- a/index.js +++ b/index.js @@ -74,7 +74,7 @@ const SupplyLimitModule = require('./artifacts/contracts/compliance/modular/modu const TransferFeesModule = require('./artifacts/contracts/compliance/modular/modules/TransferFeesModule.sol/TransferFeesModule.json'); const TransferRestrictModule = require('./artifacts/contracts/compliance/modular/modules/TransferRestrictModule.sol/TransferRestrictModule.json'); const TokenListingRestrictionsModule = require('./artifacts/contracts/compliance/modular/modules/TokenListingRestrictionsModule.sol/TokenListingRestrictionsModule.json'); - +const MinTransferByCountrytModule = require('./artifacts/contracts/compliance/modular/modules/MinTransferByCountrytModule.sol/MinTransferByCountrytModule.json'); module.exports = { contracts: { // Token diff --git a/test/compliances/module-min-transfer-by-country.ts b/test/compliances/module-min-transfer-by-country.ts new file mode 100644 index 00000000..63181f86 --- /dev/null +++ b/test/compliances/module-min-transfer-by-country.ts @@ -0,0 +1,204 @@ +import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { ethers } from 'hardhat'; +import { expect } from 'chai'; +import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; + +describe('MinTransferByCountryModule', () => { + // Test fixture + async function deployMinTransferByCountryModuleFullSuite() { + const context = await loadFixture(deploySuiteWithModularCompliancesFixture); + + const module = await ethers.deployContract('MinTransferByCountryModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('MinTransferByCountryModule', proxy.target); + + await context.suite.compliance.bindToken(context.suite.token.target); + await context.suite.compliance.addModule(complianceModule.target); + + return { + ...context, + suite: { + ...context.suite, + complianceModule, + }, + }; + } + + describe('Initialization', () => { + it('should initialize correctly', async () => { + const { + suite: { complianceModule }, + } = await loadFixture(deployMinTransferByCountryModuleFullSuite); + + expect(await complianceModule.name()).to.equal('MinTransferByCountryModule'); + expect(await complianceModule.isPlugAndPlay()).to.be.true; + }); + }); + + describe('Country Settings', () => { + it('should set minimum transfer amount for a country', async () => { + const { + suite: { compliance, complianceModule }, + accounts: { deployer }, + } = await loadFixture(deployMinTransferByCountryModuleFullSuite); + + const countryCode = 42; + const minAmount = ethers.parseEther('100'); + + const tx = await compliance + .connect(deployer) + .callModuleFunction( + new ethers.Interface(['function setMinimumTransferAmount(uint16 country, uint256 amount)']).encodeFunctionData('setMinimumTransferAmount', [ + countryCode, + minAmount, + ]), + complianceModule.target, + ); + await expect(tx).to.emit(complianceModule, 'MinimumTransferAmountSet').withArgs(countryCode, minAmount); + }); + + it('should revert when other than compliance tries to set minimum transfer amount', async () => { + const { + suite: { complianceModule }, + accounts: { aliceWallet }, + } = await loadFixture(deployMinTransferByCountryModuleFullSuite); + + const countryCode = 1; + const minAmount = ethers.parseEther('100'); + + await expect(complianceModule.connect(aliceWallet).setMinimumTransferAmount(countryCode, minAmount)).to.be.revertedWithCustomError( + complianceModule, + 'OnlyBoundComplianceCanCall', + ); + }); + }); + + describe('Transfer Validation', () => { + it('should allow transfer when amount meets minimum requirement', async () => { + const { + suite: { compliance, complianceModule, identityRegistry }, + accounts: { deployer, aliceWallet, bobWallet }, + } = await loadFixture(deployMinTransferByCountryModuleFullSuite); + + const countryCode = await identityRegistry.investorCountry(aliceWallet.address); + const minAmount = ethers.parseEther('100'); + + await compliance + .connect(deployer) + .callModuleFunction( + new ethers.Interface(['function setMinimumTransferAmount(uint16 country, uint256 amount)']).encodeFunctionData('setMinimumTransferAmount', [ + countryCode, + minAmount, + ]), + complianceModule.target, + ); + + const transferAmount = ethers.parseEther('150'); + expect(await complianceModule.moduleCheck(bobWallet.address, aliceWallet.address, transferAmount, compliance.target)).to.be.true; + }); + + it('should prevent transfer when amount is below minimum requirement', async () => { + const { + suite: { compliance, complianceModule, identityRegistry }, + accounts: { deployer, charlieWallet, bobWallet }, + } = await loadFixture(deployMinTransferByCountryModuleFullSuite); + + const countryCode = await identityRegistry.investorCountry(charlieWallet.address); + const minAmount = ethers.parseEther('100'); + + await compliance + .connect(deployer) + .callModuleFunction( + new ethers.Interface(['function setMinimumTransferAmount(uint16 country, uint256 amount)']).encodeFunctionData('setMinimumTransferAmount', [ + countryCode, + minAmount, + ]), + complianceModule.target, + ); + + const transferAmount = ethers.parseEther('99'); + expect(await complianceModule.moduleCheck(bobWallet.address, charlieWallet.address, transferAmount, compliance.target)).to.be.false; + }); + + it('should allow transfer when no minimum amount is set for country', async () => { + const { + suite: { compliance, complianceModule }, + accounts: { aliceWallet, charlieWallet }, + } = await loadFixture(deployMinTransferByCountryModuleFullSuite); + + expect(await complianceModule.moduleCheck(aliceWallet.address, charlieWallet.address, 1, compliance.target)).to.be.true; + }); + + it('should allow transfer when user as already a balance', async () => { + const { + suite: { compliance, complianceModule, identityRegistry }, + accounts: { deployer, aliceWallet, bobWallet }, + } = await loadFixture(deployMinTransferByCountryModuleFullSuite); + + const countryCode = await identityRegistry.investorCountry(bobWallet.address); + const minAmount = ethers.parseEther('100'); + + await compliance + .connect(deployer) + .callModuleFunction( + new ethers.Interface(['function setMinimumTransferAmount(uint16 country, uint256 amount)']).encodeFunctionData('setMinimumTransferAmount', [ + countryCode, + minAmount, + ]), + complianceModule.target, + ); + + expect(await complianceModule.moduleCheck(aliceWallet.address, bobWallet.address, 1, compliance.target)).to.be.true; + }); + + it('should allow transfer when transfer into same identity and same country with amount below the minimum amount set', async () => { + const { + suite: { compliance, complianceModule, identityRegistry }, + accounts: { deployer, aliceWallet, anotherWallet, tokenAgent }, + identities: { aliceIdentity }, + } = await loadFixture(deployMinTransferByCountryModuleFullSuite); + + const countryCode = await identityRegistry.investorCountry(aliceWallet.address); + + await identityRegistry.connect(tokenAgent).registerIdentity(anotherWallet.address, aliceIdentity, countryCode); + + const minAmount = ethers.parseEther('100'); + await compliance + .connect(deployer) + .callModuleFunction( + new ethers.Interface(['function setMinimumTransferAmount(uint16 country, uint256 amount)']).encodeFunctionData('setMinimumTransferAmount', [ + countryCode, + minAmount, + ]), + complianceModule.target, + ); + + expect(await complianceModule.moduleCheck(aliceWallet.address, anotherWallet.address, 1, compliance.target)).to.be.true; + }); + + it('should prevent transfer when transfer into same identity and different country with amount below the minimum amount set', async () => { + const { + suite: { compliance, complianceModule, identityRegistry }, + accounts: { deployer, aliceWallet, anotherWallet, tokenAgent }, + identities: { aliceIdentity }, + } = await loadFixture(deployMinTransferByCountryModuleFullSuite); + + const countryCode = 1n + (await identityRegistry.investorCountry(aliceWallet.address)); + + await identityRegistry.connect(tokenAgent).registerIdentity(anotherWallet.address, aliceIdentity, countryCode); + + const minAmount = ethers.parseEther('100'); + await compliance + .connect(deployer) + .callModuleFunction( + new ethers.Interface(['function setMinimumTransferAmount(uint16 country, uint256 amount)']).encodeFunctionData('setMinimumTransferAmount', [ + countryCode, + minAmount, + ]), + complianceModule.target, + ); + + expect(await complianceModule.moduleCheck(aliceWallet.address, anotherWallet.address, 1, compliance.target)).to.be.false; + }); + }); +}); From dc035b646d25d02e530a6bbe259c22acd2eec3b5 Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Sun, 1 Dec 2024 17:57:19 +0100 Subject: [PATCH 49/55] =?UTF-8?q?=E2=99=BB()=20Add=20limit=20for=20batchIn?= =?UTF-8?q?itialize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/InvestorCountryCapModule.sol | 15 ++++++++----- .../module-investor-country-cap.test.ts | 22 +++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/contracts/compliance/modular/modules/InvestorCountryCapModule.sol b/contracts/compliance/modular/modules/InvestorCountryCapModule.sol index 4281261b..c7b2a9ff 100644 --- a/contracts/compliance/modular/modules/InvestorCountryCapModule.sol +++ b/contracts/compliance/modular/modules/InvestorCountryCapModule.sol @@ -74,6 +74,7 @@ import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; import "../../../roles/AgentRole.sol"; +error BatchInitializeTooManyHolders(uint256 holdersCount, uint256 maxHolders); event CountryCapSet(uint16 indexed country, uint256 cap); event BypassedIdentityAdded(address indexed identity); event BypassedIdentityRemoved(address indexed identity); @@ -83,8 +84,9 @@ error IdentityNotBypassed(address identity); error CapLowerThanCurrent(uint16 country, uint256 cap, uint256 currentCap); error WalletCountLimitReached(address identity, uint256 maxWallets); -uint256 constant MAX_WALLET_PER_IDENTITY = 20; +uint256 constant MAX_WALLET_PER_IDENTITY = 20; +uint256 constant MAX_HOLDERS_BATCH_INITIALIZE = 50; contract InvestorCountryCapModule is AbstractModuleUpgradeable { using EnumerableSet for EnumerableSet.AddressSet; @@ -117,7 +119,10 @@ contract InvestorCountryCapModule is AbstractModuleUpgradeable { /// @param _compliance Address of the compliance. /// @param _holders Addresses of the holders already holding tokens (addresses should be unique - no control is done on that). function batchInitialize(address _compliance, address[] memory _holders) external onlyOwner { - // TODO calculate gas cost and revert if _holders.length is too high + require( + _holders.length < MAX_HOLDERS_BATCH_INITIALIZE, + BatchInitializeTooManyHolders(_holders.length, MAX_HOLDERS_BATCH_INITIALIZE) + ); IToken token = IToken(IModularCompliance(_compliance).getTokenBound()); require(token.paused(), ExpectedPause()); @@ -127,12 +132,10 @@ contract InvestorCountryCapModule is AbstractModuleUpgradeable { address holder = _holders[i]; address idTo = _getIdentity(_compliance, holder); - if (_bypassedIdentities[idTo]) { - return; + if (!_bypassedIdentities[idTo]) { + _registerWallet(_compliance, holder, idTo, _getCountry(_compliance, holder)); } - _registerWallet(_compliance, holder, idTo, _getCountry(_compliance, holder)); - calculatedSupply[address(token)] += token.balanceOf(holder); } } diff --git a/test/compliances/module-investor-country-cap.test.ts b/test/compliances/module-investor-country-cap.test.ts index 3f4d91e7..a4153381 100644 --- a/test/compliances/module-investor-country-cap.test.ts +++ b/test/compliances/module-investor-country-cap.test.ts @@ -246,4 +246,26 @@ describe('InvestorCountryCapModule', () => { expect(await complianceModule.moduleCheck(aliceWallet.address, aliceWallet.address, 100, compliance.target)).to.be.true; }); }); + + describe('Batch Initialize (For gas cost)', () => { + it('should initialize correctly', async () => { + const context = await loadFixture(deploySuiteWithModularCompliancesFixture); + + const module = await ethers.deployContract('InvestorCountryCapModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('InvestorCountryCapModule', proxy.target); + + await context.suite.compliance.bindToken(context.suite.token.target); + + await context.suite.token.connect(context.accounts.tokenAgent).pause(); + await complianceModule.batchInitialize(context.suite.compliance.target, [ + context.accounts.aliceWallet.address, + context.accounts.bobWallet.address, + // context.accounts.charlieWallet.address, + // context.accounts.anotherWallet.address, + ]); + await context.suite.compliance.addModule(complianceModule.target); + await context.suite.token.connect(context.accounts.tokenAgent).unpause(); + }); + }); }); From 8f7f3b16e58da8a018c9314f0db8531728e64dbf Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Mon, 9 Dec 2024 15:07:33 +0100 Subject: [PATCH 50/55] =?UTF-8?q?=E2=9C=A8()=20Add=20InitialLockupPeriod?= =?UTF-8?q?=20module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/InitialLockupPeriodModule.sol | 161 ++++++++++++++++++ test/compliance.test.ts | 7 +- .../module-initial-lockup-period.test.ts | 149 ++++++++++++++++ test/compliances/module-max-balance.test.ts | 11 +- test/fixtures/deploy-full-suite.fixture.ts | 2 + 5 files changed, 325 insertions(+), 5 deletions(-) create mode 100644 contracts/compliance/modular/modules/InitialLockupPeriodModule.sol create mode 100644 test/compliances/module-initial-lockup-period.test.ts diff --git a/contracts/compliance/modular/modules/InitialLockupPeriodModule.sol b/contracts/compliance/modular/modules/InitialLockupPeriodModule.sol new file mode 100644 index 00000000..46127d2b --- /dev/null +++ b/contracts/compliance/modular/modules/InitialLockupPeriodModule.sol @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-3.0 +// This contract is also licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. +// +// :+#####%%%%%%%%%%%%%%+ +// .-*@@@%+.:+%@@@@@%%#***%@@%= +// :=*%@@@#=. :#@@% *@@@%= +// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- +// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. +// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ +// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- +// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: +// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. +// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. +// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ +// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- +// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: +// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- +// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- +// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# +// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- +// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: +// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: +// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. +// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. +// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. +// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. +// @@@@@@+. +@@*. .+@@@@@%=. +// -@@@@@= =@@%: -#@@@@%+. +// +@@@@@. =@@@= .+@@@@@*: +// #@@@@#:%@@#. :*@@@@#- +// @@@@@%@@@= :#@@@@+. +// :@@@@@@@#.:#@@@%- +// +@@@@@@-.*@@@*: +// #@@@@#.=@@@+. +// @@@@+-%@%= +// :@@@#%@%= +// +@@@@%- +// :#%%= +// +/** + * NOTICE + * + * The T-REX software is licensed under a proprietary license or the GPL v.3. + * If you choose to receive it under the GPL v.3 license, the following applies: + * T-REX is a suite of smart contracts implementing the ERC-3643 standard and + * developed by Tokeny to manage and transfer financial assets on EVM blockchains + * + * Copyright (C) 2024, Tokeny sàrl. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This specific smart contract is also licensed under the Creative Commons + * Attribution-NonCommercial 4.0 International License (CC-BY-NC-4.0), + * which prohibits commercial use. For commercial inquiries, please contact + * Tokeny sàrl for licensing options. + */ + +pragma solidity 0.8.27; + +import "./AbstractModuleUpgradeable.sol"; + +error InsufficientBalanceTokensLocked(address user, uint256 value, uint256 availableAmount); + +event LockupPeriodSet(address indexed compliance, uint256 lockupPeriod); + + +contract InitialLockupPeriodModule is AbstractModuleUpgradeable { + + struct LockedTokens { + uint256 amount; + uint256 releaseTimestamp; + } + + mapping(address compliance => uint256 lockupPeriod) private _lockupPeriods; + mapping(address compliance => mapping(address user => LockedTokens[] lockedTokens)) private _lockedTokens; + + /// @dev initializes the contract and sets the initial state. + function initialize() external initializer { + __AbstractModule_init(); + } + + /// @dev sets the lockup period for a compliance contract. + /// @param _compliance the address of the compliance contract. + /// @param _lockupPeriod the lockup period in seconds. + function setLockupPeriod(address _compliance, uint256 _lockupPeriod) external onlyComplianceCall { + _lockupPeriods[_compliance] = _lockupPeriod; + + emit LockupPeriodSet(_compliance, _lockupPeriod); + } + + /// @inheritdoc IModule + function moduleTransferAction(address _from, address /*_to*/, uint256 _value) external override onlyComplianceCall { + if (_from != address(0)) { + // Check if the user has enough unlocked tokens to transfer + uint256 availableAmount = _calculateAvailableAmount(msg.sender, _from); + if (_value > availableAmount) { + revert InsufficientBalanceTokensLocked(_from, _value, availableAmount); + } + } + } + + /// @inheritdoc IModule + function moduleMintAction(address _to, uint256 _value) external override onlyComplianceCall { + _lockedTokens[msg.sender][_to].push( + LockedTokens({ + amount: _value, + releaseTimestamp: block.timestamp + _lockupPeriods[msg.sender] + }) + ); + } + + /// @inheritdoc IModule + // solhint-disable-next-line no-empty-blocks + function moduleBurnAction(address _from, uint256 _value) external override onlyComplianceCall { } + + /// @inheritdoc IModule + function moduleCheck(address _from, address /*_to*/, uint256 _value, address _compliance) external + view override returns (bool) { + return _from == address(0) || _calculateAvailableAmount(_compliance, _from) >= _value; + } + + /// @inheritdoc IModule + function canComplianceBind(address /*_compliance*/) external view override returns (bool) { + return true; + } + + /// @inheritdoc IModule + function isPlugAndPlay() external pure override returns (bool) { + return true; + } + + /// @inheritdoc IModule + function name() external pure override returns (string memory _name) { + return "InitialLockupPeriodModule"; + } + + /// @dev calculates the available amount of unlocked tokens for a user. + /// @param _compliance the address of the compliance contract. + /// @param _user the address of the user. + /// @return _availableAmount the available amount of unlocked tokens. + function _calculateAvailableAmount(address _compliance, address _user) internal view returns (uint256 _availableAmount) { + uint256 periodsLength = _lockedTokens[_compliance][_user].length; + for (uint256 i; i < periodsLength; i++) { + if (_lockedTokens[_compliance][_user][i].releaseTimestamp <= block.timestamp) { + _availableAmount += _lockedTokens[_compliance][_user][i].amount; + } + } + } + +} \ No newline at end of file diff --git a/test/compliance.test.ts b/test/compliance.test.ts index 40f21014..7b66ab1f 100644 --- a/test/compliance.test.ts +++ b/test/compliance.test.ts @@ -104,8 +104,11 @@ describe('ModularCompliance', () => { describe('when token is a zero address', () => { it('should revert', async () => { const { - suite: { compliance }, - } = await loadFixture(deploySuiteWithModularCompliancesFixture); + authorities: { trexImplementationAuthority }, + } = await loadFixture(deployFullSuiteFixture); + + const complianceProxy = await ethers.deployContract('ModularComplianceProxy', [trexImplementationAuthority.target]); + const compliance = await ethers.getContractAt('ModularCompliance', complianceProxy.target); await expect(compliance.unbindToken(ethers.ZeroAddress)).to.be.revertedWithCustomError(compliance, 'ZeroAddress'); }); diff --git a/test/compliances/module-initial-lockup-period.test.ts b/test/compliances/module-initial-lockup-period.test.ts new file mode 100644 index 00000000..2e0e242e --- /dev/null +++ b/test/compliances/module-initial-lockup-period.test.ts @@ -0,0 +1,149 @@ +import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { ethers } from 'hardhat'; +import { expect } from 'chai'; +import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; +import { ModularCompliance, InitialLockupPeriodModule } from '../../typechain-types'; + +describe('InitialLockupPeriodModule', () => { + // Test fixture + async function deployInitialLockupPeriodModuleFullSuite() { + const context = await loadFixture(deploySuiteWithModularCompliancesFixture); + + const module = await ethers.deployContract('InitialLockupPeriodModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('InitialLockupPeriodModule', proxy.target); + + await context.suite.compliance.bindToken(context.suite.token.target); + await context.suite.compliance.addModule(complianceModule.target); + + // Reset already minted tokens to have 0 balance + const token = context.suite.token; + await token + .connect(context.accounts.tokenAgent) + .burn(context.accounts.aliceWallet.address, await token.balanceOf(context.accounts.aliceWallet.address)); + await token + .connect(context.accounts.tokenAgent) + .burn(context.accounts.bobWallet.address, await token.balanceOf(context.accounts.bobWallet.address)); + + return { + ...context, + suite: { + ...context.suite, + complianceModule, + }, + accounts: { + ...context.accounts, + complianceSigner: await ethers.getImpersonatedSigner(context.suite.compliance.target.toString()), + }, + }; + } + + async function increaseTimestamp(timestamp: number) { + await ethers.provider.send('evm_increaseTime', [timestamp]); + await ethers.provider.send('evm_mine', []); + } + + async function setLockupPeriod(compliance: ModularCompliance, complianceModule: InitialLockupPeriodModule, lockupPeriod: number) { + return compliance.callModuleFunction( + new ethers.Interface(['function setLockupPeriod(address _compliance, uint256 _lockupPeriod)']).encodeFunctionData('setLockupPeriod', [ + compliance.target, + lockupPeriod, + ]), + complianceModule.target, + ); + } + + describe('Initialization', () => { + it('should initialize correctly', async () => { + const { + suite: { complianceModule }, + } = await loadFixture(deployInitialLockupPeriodModuleFullSuite); + + expect(await complianceModule.name()).to.equal('InitialLockupPeriodModule'); + expect(await complianceModule.isPlugAndPlay()).to.be.true; + }); + }); + + describe('Lockup Period Management', () => { + it('should revert when calling by not owner', async () => { + const { + suite: { compliance, complianceModule }, + accounts: { aliceWallet }, + } = await loadFixture(deployInitialLockupPeriodModuleFullSuite); + + await expect(complianceModule.connect(aliceWallet).setLockupPeriod(compliance.target, 100)).to.be.revertedWithCustomError( + complianceModule, + 'OnlyBoundComplianceCanCall', + ); + }); + + it('should set lockup period correctly', async () => { + const { + suite: { compliance, complianceModule }, + } = await loadFixture(deployInitialLockupPeriodModuleFullSuite); + + const lockupPeriod = 100; + const tx = await setLockupPeriod(compliance, complianceModule, lockupPeriod); + + await expect(tx).to.emit(complianceModule, 'LockupPeriodSet').withArgs(compliance.target, lockupPeriod); + }); + }); + + describe('Transfer Checks', () => { + it('should allow transfer after lockup period', async () => { + const { + suite: { compliance, complianceModule, token }, + accounts: { aliceWallet, bobWallet, tokenAgent, complianceSigner }, + } = await loadFixture(deployInitialLockupPeriodModuleFullSuite); + + const lockupPeriod = 100; + await setLockupPeriod(compliance, complianceModule, lockupPeriod); + + await token.connect(tokenAgent).mint(aliceWallet.address, 100); + + // Advance time beyond lockup period + await increaseTimestamp(lockupPeriod + 1); + expect(await complianceModule.connect(complianceSigner).moduleCheck(aliceWallet.address, bobWallet.address, 100, compliance.target)).to.be.true; + }); + + it('should prevent transfer during lockup period', async () => { + const { + suite: { compliance, complianceModule, token }, + accounts: { aliceWallet, bobWallet, tokenAgent }, + } = await loadFixture(deployInitialLockupPeriodModuleFullSuite); + + const lockupPeriod = 100; + await setLockupPeriod(compliance, complianceModule, lockupPeriod); + + await token.connect(tokenAgent).mint(aliceWallet.address, 100); + expect(await complianceModule.moduleCheck(aliceWallet.address, bobWallet.address, 100, compliance.target)).to.be.false; + + await increaseTimestamp(lockupPeriod - 1); + expect(await complianceModule.moduleCheck(aliceWallet.address, bobWallet.address, 100, compliance.target)).to.be.false; + }); + + describe('Transfer Checks with multiple lockup periods', () => { + it('should allow transfer after lockup period', async () => { + const { + suite: { compliance, complianceModule, token }, + accounts: { aliceWallet, bobWallet, tokenAgent }, + } = await loadFixture(deployInitialLockupPeriodModuleFullSuite); + + const lockupPeriod = 100; + await setLockupPeriod(compliance, complianceModule, lockupPeriod); + + await token.connect(tokenAgent).mint(aliceWallet.address, 100); + expect(await complianceModule.moduleCheck(aliceWallet.address, bobWallet.address, 100, compliance.target)).to.be.false; + + await increaseTimestamp(lockupPeriod); + await token.connect(tokenAgent).mint(aliceWallet.address, 100); + + expect(await complianceModule.moduleCheck(aliceWallet.address, bobWallet.address, 200, compliance.target)).to.be.false; + expect(await complianceModule.moduleCheck(aliceWallet.address, bobWallet.address, 100, compliance.target)).to.be.true; + + await increaseTimestamp(lockupPeriod); + expect(await complianceModule.moduleCheck(aliceWallet.address, bobWallet.address, 200, compliance.target)).to.be.true; + }); + }); + }); +}); diff --git a/test/compliances/module-max-balance.test.ts b/test/compliances/module-max-balance.test.ts index 7e05b525..af4b654c 100644 --- a/test/compliances/module-max-balance.test.ts +++ b/test/compliances/module-max-balance.test.ts @@ -52,9 +52,14 @@ describe('Compliance Module: MaxBalance', () => { describe('when token totalSupply is greater than zero', () => { describe('when compliance preset status is false', () => { it('should return false', async () => { - const context = await loadFixture(deployMaxBalanceFullSuite); - await context.suite.token.connect(context.accounts.tokenAgent).mint(context.accounts.aliceWallet.address, 1000); - expect(await context.suite.complianceModule.canComplianceBind(context.suite.compliance.target)).to.be.false; + const context = await loadFixture(deploySuiteWithModularCompliancesFixture); + const module = await ethers.deployContract('MaxBalanceModule'); + const proxy = await ethers.deployContract('ModuleProxy', [module.target, module.interface.encodeFunctionData('initialize')]); + const complianceModule = await ethers.getContractAt('MaxBalanceModule', proxy.target); + await context.suite.compliance.bindToken(context.suite.token.target); + + expect(await context.suite.token.totalSupply()).to.be.greaterThan(0); + expect(await complianceModule.canComplianceBind(context.suite.compliance.target)).to.be.false; }); }); diff --git a/test/fixtures/deploy-full-suite.fixture.ts b/test/fixtures/deploy-full-suite.fixture.ts index 6d3cafba..d5b8066d 100644 --- a/test/fixtures/deploy-full-suite.fixture.ts +++ b/test/fixtures/deploy-full-suite.fixture.ts @@ -234,6 +234,8 @@ export async function deploySuiteWithModularCompliancesFixture() { const complianceBeta = await ethers.deployContract('ModularCompliance'); await complianceBeta.init(); + await context.suite.token.connect(context.accounts.deployer).setCompliance(compliance.target); + return { ...context, suite: { From 409b91a441fc27185a3a02043da1a8573059c9f4 Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Wed, 11 Dec 2024 18:04:00 +0100 Subject: [PATCH 51/55] =?UTF-8?q?=E2=9C=85()=20Update=20tests=20bt-359?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/MinTransferByCountryModule.sol | 2 +- index.d.ts | 1 + index.js | 3 + .../module-min-transfer-by-country.ts | 102 ++++++++---------- 4 files changed, 47 insertions(+), 61 deletions(-) diff --git a/contracts/compliance/modular/modules/MinTransferByCountryModule.sol b/contracts/compliance/modular/modules/MinTransferByCountryModule.sol index 95be2bca..b5e9eb16 100644 --- a/contracts/compliance/modular/modules/MinTransferByCountryModule.sol +++ b/contracts/compliance/modular/modules/MinTransferByCountryModule.sol @@ -72,7 +72,7 @@ contract MinTransferByCountryModule is AbstractModuleUpgradeable { } /// @inheritdoc IModule - function canComplianceBind(address /*_compliance*/) external view override returns (bool) { + function canComplianceBind(address /*_compliance*/) external pure override returns (bool) { return true; } diff --git a/index.d.ts b/index.d.ts index fdbd9990..774d410d 100644 --- a/index.d.ts +++ b/index.d.ts @@ -72,6 +72,7 @@ export namespace contracts { export const TransferFeesModule: ContractJSON; export const TransferRestrictModule: ContractJSON; export const TokenListingRestrictionsModule: ContractJSON; + export const InvestorCountryCapModule: ContractJSON; export const MinTransferByCountrytModule: ContractJSON; } diff --git a/index.js b/index.js index 9b2bb1fc..a2933146 100644 --- a/index.js +++ b/index.js @@ -74,6 +74,7 @@ const SupplyLimitModule = require('./artifacts/contracts/compliance/modular/modu const TransferFeesModule = require('./artifacts/contracts/compliance/modular/modules/TransferFeesModule.sol/TransferFeesModule.json'); const TransferRestrictModule = require('./artifacts/contracts/compliance/modular/modules/TransferRestrictModule.sol/TransferRestrictModule.json'); const TokenListingRestrictionsModule = require('./artifacts/contracts/compliance/modular/modules/TokenListingRestrictionsModule.sol/TokenListingRestrictionsModule.json'); +const InvestorCountryCapModule = require('./artifacts/contracts/compliance/modular/modules/InvestorCountryCapModule.sol/InvestorCountryCapModule.json'); const MinTransferByCountrytModule = require('./artifacts/contracts/compliance/modular/modules/MinTransferByCountrytModule.sol/MinTransferByCountrytModule.json'); module.exports = { contracts: { @@ -139,6 +140,8 @@ module.exports = { TransferFeesModule, TransferRestrictModule, TokenListingRestrictionsModule, + InvestorCountryCapModule, + MinTransferByCountrytModule, }, interfaces: { IToken, diff --git a/test/compliances/module-min-transfer-by-country.ts b/test/compliances/module-min-transfer-by-country.ts index 63181f86..ec534e6f 100644 --- a/test/compliances/module-min-transfer-by-country.ts +++ b/test/compliances/module-min-transfer-by-country.ts @@ -1,7 +1,9 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; import { ethers } from 'hardhat'; import { expect } from 'chai'; import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-full-suite.fixture'; +import { MinTransferByCountryModule, ModularCompliance } from '../../index.js'; describe('MinTransferByCountryModule', () => { // Test fixture @@ -24,14 +26,46 @@ describe('MinTransferByCountryModule', () => { }; } + async function setMinimumTransferAmount( + compliance: ModularCompliance, + complianceModule: MinTransferByCountryModule, + deployer: SignerWithAddress, + countryCode: bigint, + minAmount: bigint, + ) { + return compliance + .connect(deployer) + .callModuleFunction( + new ethers.Interface(['function setMinimumTransferAmount(uint16 country, uint256 amount)']).encodeFunctionData('setMinimumTransferAmount', [ + countryCode, + minAmount, + ]), + complianceModule.target, + ); + } + describe('Initialization', () => { it('should initialize correctly', async () => { const { - suite: { complianceModule }, + suite: { compliance, complianceModule }, } = await loadFixture(deployMinTransferByCountryModuleFullSuite); expect(await complianceModule.name()).to.equal('MinTransferByCountryModule'); expect(await complianceModule.isPlugAndPlay()).to.be.true; + expect(await complianceModule.canComplianceBind(compliance.target)).to.be.true; + }); + }); + + describe('Basic operations', () => { + it('Should mint/burn/transfer tokens if no minimum transfer amount is set', async () => { + const { + suite: { token }, + accounts: { tokenAgent, aliceWallet, bobWallet }, + } = await loadFixture(deployMinTransferByCountryModuleFullSuite); + + await token.connect(tokenAgent).mint(aliceWallet.address, 10); + await token.connect(aliceWallet).transfer(bobWallet.address, 10); + await token.connect(tokenAgent).burn(bobWallet.address, 10); }); }); @@ -42,18 +76,9 @@ describe('MinTransferByCountryModule', () => { accounts: { deployer }, } = await loadFixture(deployMinTransferByCountryModuleFullSuite); - const countryCode = 42; + const countryCode = 42n; const minAmount = ethers.parseEther('100'); - - const tx = await compliance - .connect(deployer) - .callModuleFunction( - new ethers.Interface(['function setMinimumTransferAmount(uint16 country, uint256 amount)']).encodeFunctionData('setMinimumTransferAmount', [ - countryCode, - minAmount, - ]), - complianceModule.target, - ); + const tx = await setMinimumTransferAmount(compliance, complianceModule, deployer, countryCode, minAmount); await expect(tx).to.emit(complianceModule, 'MinimumTransferAmountSet').withArgs(countryCode, minAmount); }); @@ -82,16 +107,7 @@ describe('MinTransferByCountryModule', () => { const countryCode = await identityRegistry.investorCountry(aliceWallet.address); const minAmount = ethers.parseEther('100'); - - await compliance - .connect(deployer) - .callModuleFunction( - new ethers.Interface(['function setMinimumTransferAmount(uint16 country, uint256 amount)']).encodeFunctionData('setMinimumTransferAmount', [ - countryCode, - minAmount, - ]), - complianceModule.target, - ); + await setMinimumTransferAmount(compliance, complianceModule, deployer, countryCode, minAmount); const transferAmount = ethers.parseEther('150'); expect(await complianceModule.moduleCheck(bobWallet.address, aliceWallet.address, transferAmount, compliance.target)).to.be.true; @@ -106,16 +122,7 @@ describe('MinTransferByCountryModule', () => { const countryCode = await identityRegistry.investorCountry(charlieWallet.address); const minAmount = ethers.parseEther('100'); - await compliance - .connect(deployer) - .callModuleFunction( - new ethers.Interface(['function setMinimumTransferAmount(uint16 country, uint256 amount)']).encodeFunctionData('setMinimumTransferAmount', [ - countryCode, - minAmount, - ]), - complianceModule.target, - ); - + await setMinimumTransferAmount(compliance, complianceModule, deployer, countryCode, minAmount); const transferAmount = ethers.parseEther('99'); expect(await complianceModule.moduleCheck(bobWallet.address, charlieWallet.address, transferAmount, compliance.target)).to.be.false; }); @@ -138,16 +145,7 @@ describe('MinTransferByCountryModule', () => { const countryCode = await identityRegistry.investorCountry(bobWallet.address); const minAmount = ethers.parseEther('100'); - await compliance - .connect(deployer) - .callModuleFunction( - new ethers.Interface(['function setMinimumTransferAmount(uint16 country, uint256 amount)']).encodeFunctionData('setMinimumTransferAmount', [ - countryCode, - minAmount, - ]), - complianceModule.target, - ); - + await setMinimumTransferAmount(compliance, complianceModule, deployer, countryCode, minAmount); expect(await complianceModule.moduleCheck(aliceWallet.address, bobWallet.address, 1, compliance.target)).to.be.true; }); @@ -163,15 +161,7 @@ describe('MinTransferByCountryModule', () => { await identityRegistry.connect(tokenAgent).registerIdentity(anotherWallet.address, aliceIdentity, countryCode); const minAmount = ethers.parseEther('100'); - await compliance - .connect(deployer) - .callModuleFunction( - new ethers.Interface(['function setMinimumTransferAmount(uint16 country, uint256 amount)']).encodeFunctionData('setMinimumTransferAmount', [ - countryCode, - minAmount, - ]), - complianceModule.target, - ); + await setMinimumTransferAmount(compliance, complianceModule, deployer, countryCode, minAmount); expect(await complianceModule.moduleCheck(aliceWallet.address, anotherWallet.address, 1, compliance.target)).to.be.true; }); @@ -188,15 +178,7 @@ describe('MinTransferByCountryModule', () => { await identityRegistry.connect(tokenAgent).registerIdentity(anotherWallet.address, aliceIdentity, countryCode); const minAmount = ethers.parseEther('100'); - await compliance - .connect(deployer) - .callModuleFunction( - new ethers.Interface(['function setMinimumTransferAmount(uint16 country, uint256 amount)']).encodeFunctionData('setMinimumTransferAmount', [ - countryCode, - minAmount, - ]), - complianceModule.target, - ); + await setMinimumTransferAmount(compliance, complianceModule, deployer, countryCode, minAmount); expect(await complianceModule.moduleCheck(aliceWallet.address, anotherWallet.address, 1, compliance.target)).to.be.false; }); From 781a5a118a012a76f0e46403301105bf1fc29f60 Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Fri, 13 Dec 2024 09:54:59 +0100 Subject: [PATCH 52/55] =?UTF-8?q?=F0=9F=90=9B()=20Update=20on=20setLockupP?= =?UTF-8?q?eriod=20after=20review?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modular/modules/InitialLockupPeriodModule.sol | 7 +++---- test/compliances/module-initial-lockup-period.test.ts | 9 +++------ 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/contracts/compliance/modular/modules/InitialLockupPeriodModule.sol b/contracts/compliance/modular/modules/InitialLockupPeriodModule.sol index 46127d2b..f54f2e0a 100644 --- a/contracts/compliance/modular/modules/InitialLockupPeriodModule.sol +++ b/contracts/compliance/modular/modules/InitialLockupPeriodModule.sol @@ -91,12 +91,11 @@ contract InitialLockupPeriodModule is AbstractModuleUpgradeable { } /// @dev sets the lockup period for a compliance contract. - /// @param _compliance the address of the compliance contract. /// @param _lockupPeriod the lockup period in seconds. - function setLockupPeriod(address _compliance, uint256 _lockupPeriod) external onlyComplianceCall { - _lockupPeriods[_compliance] = _lockupPeriod; + function setLockupPeriod(uint256 _lockupPeriod) external onlyComplianceCall { + _lockupPeriods[msg.sender] = _lockupPeriod; - emit LockupPeriodSet(_compliance, _lockupPeriod); + emit LockupPeriodSet(msg.sender, _lockupPeriod); } /// @inheritdoc IModule diff --git a/test/compliances/module-initial-lockup-period.test.ts b/test/compliances/module-initial-lockup-period.test.ts index 2e0e242e..53620cba 100644 --- a/test/compliances/module-initial-lockup-period.test.ts +++ b/test/compliances/module-initial-lockup-period.test.ts @@ -45,10 +45,7 @@ describe('InitialLockupPeriodModule', () => { async function setLockupPeriod(compliance: ModularCompliance, complianceModule: InitialLockupPeriodModule, lockupPeriod: number) { return compliance.callModuleFunction( - new ethers.Interface(['function setLockupPeriod(address _compliance, uint256 _lockupPeriod)']).encodeFunctionData('setLockupPeriod', [ - compliance.target, - lockupPeriod, - ]), + new ethers.Interface(['function setLockupPeriod(uint256 _lockupPeriod)']).encodeFunctionData('setLockupPeriod', [lockupPeriod]), complianceModule.target, ); } @@ -67,11 +64,11 @@ describe('InitialLockupPeriodModule', () => { describe('Lockup Period Management', () => { it('should revert when calling by not owner', async () => { const { - suite: { compliance, complianceModule }, + suite: { complianceModule }, accounts: { aliceWallet }, } = await loadFixture(deployInitialLockupPeriodModuleFullSuite); - await expect(complianceModule.connect(aliceWallet).setLockupPeriod(compliance.target, 100)).to.be.revertedWithCustomError( + await expect(complianceModule.connect(aliceWallet).setLockupPeriod(100)).to.be.revertedWithCustomError( complianceModule, 'OnlyBoundComplianceCanCall', ); From 83b6ff0e6c5bcc31ffc98a121e5e0ad58ce7ec71 Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Mon, 16 Dec 2024 08:09:48 +0100 Subject: [PATCH 53/55] =?UTF-8?q?=E2=9C=85()=20Update=20after=20review?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compliance/modular/modules/MinTransferByCountryModule.sol | 4 ++-- test/compliances/module-min-transfer-by-country.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/compliance/modular/modules/MinTransferByCountryModule.sol b/contracts/compliance/modular/modules/MinTransferByCountryModule.sol index b5e9eb16..2359a0bb 100644 --- a/contracts/compliance/modular/modules/MinTransferByCountryModule.sol +++ b/contracts/compliance/modular/modules/MinTransferByCountryModule.sol @@ -5,7 +5,7 @@ import "../IModularCompliance.sol"; import "../../../token/IToken.sol"; import "./AbstractModuleUpgradeable.sol"; - event MinimumTransferAmountSet(uint16 indexed country, uint256 amount); + event MinimumTransferAmountSet(address indexed compliance, uint16 indexed country, uint256 amount); /** @@ -29,7 +29,7 @@ contract MinTransferByCountryModule is AbstractModuleUpgradeable { function setMinimumTransferAmount(uint16 country, uint256 amount) external onlyComplianceCall { _minimumTransferAmounts[msg.sender][country] = amount; - emit MinimumTransferAmountSet(country, amount); + emit MinimumTransferAmountSet(msg.sender, country, amount); } /// @inheritdoc IModule diff --git a/test/compliances/module-min-transfer-by-country.ts b/test/compliances/module-min-transfer-by-country.ts index ec534e6f..603817e7 100644 --- a/test/compliances/module-min-transfer-by-country.ts +++ b/test/compliances/module-min-transfer-by-country.ts @@ -79,7 +79,7 @@ describe('MinTransferByCountryModule', () => { const countryCode = 42n; const minAmount = ethers.parseEther('100'); const tx = await setMinimumTransferAmount(compliance, complianceModule, deployer, countryCode, minAmount); - await expect(tx).to.emit(complianceModule, 'MinimumTransferAmountSet').withArgs(countryCode, minAmount); + await expect(tx).to.emit(complianceModule, 'MinimumTransferAmountSet').withArgs(compliance.target, countryCode, minAmount); }); it('should revert when other than compliance tries to set minimum transfer amount', async () => { From 7bf4a98b0b9fe3133da6c7f50e125f4d7469a3cd Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Tue, 17 Dec 2024 09:26:45 +0100 Subject: [PATCH 54/55] =?UTF-8?q?=E2=99=BB()=20Update=20after=20review?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/InitialLockupPeriodModule.sol | 108 ++++++++++++++---- .../module-initial-lockup-period.test.ts | 33 +++++- 2 files changed, 113 insertions(+), 28 deletions(-) diff --git a/contracts/compliance/modular/modules/InitialLockupPeriodModule.sol b/contracts/compliance/modular/modules/InitialLockupPeriodModule.sol index f54f2e0a..1acf5449 100644 --- a/contracts/compliance/modular/modules/InitialLockupPeriodModule.sol +++ b/contracts/compliance/modular/modules/InitialLockupPeriodModule.sol @@ -68,13 +68,23 @@ pragma solidity 0.8.27; +import "../IModularCompliance.sol"; +import "../../../token/IToken.sol"; import "./AbstractModuleUpgradeable.sol"; +/// @dev Error emitted when the user has insufficient balance because of locked tokens. +/// @param user the address of the user. +/// @param value the value of the transfer. +/// @param availableAmount the available amount of unlocked tokens. error InsufficientBalanceTokensLocked(address user, uint256 value, uint256 availableAmount); -event LockupPeriodSet(address indexed compliance, uint256 lockupPeriod); - +/// @notice Event emitted when the lockup period is set. +/// @param compliance the address of the compliance contract. +/// @param lockupPeriodInDays the lockup period in days. +event LockupPeriodSet(address indexed compliance, uint256 lockupPeriodInDays); +/// @title InitialLockupPeriodModule +/// @notice Enforces a lockup period for all investors whenever they receive tokens through primary emissions contract InitialLockupPeriodModule is AbstractModuleUpgradeable { struct LockedTokens { @@ -83,7 +93,7 @@ contract InitialLockupPeriodModule is AbstractModuleUpgradeable { } mapping(address compliance => uint256 lockupPeriod) private _lockupPeriods; - mapping(address compliance => mapping(address user => LockedTokens[] lockedTokens)) private _lockedTokens; + mapping(address compliance => mapping(address user => LockedTokens[])) private _lockedTokens; /// @dev initializes the contract and sets the initial state. function initialize() external initializer { @@ -91,21 +101,24 @@ contract InitialLockupPeriodModule is AbstractModuleUpgradeable { } /// @dev sets the lockup period for a compliance contract. - /// @param _lockupPeriod the lockup period in seconds. - function setLockupPeriod(uint256 _lockupPeriod) external onlyComplianceCall { - _lockupPeriods[msg.sender] = _lockupPeriod; + /// @param _lockupPeriodInDays the lockup period in days. + function setLockupPeriod(uint256 _lockupPeriodInDays) external onlyComplianceCall { + _lockupPeriods[msg.sender] = _lockupPeriodInDays * 1 days; - emit LockupPeriodSet(msg.sender, _lockupPeriod); + emit LockupPeriodSet(msg.sender, _lockupPeriodInDays); } /// @inheritdoc IModule - function moduleTransferAction(address _from, address /*_to*/, uint256 _value) external override onlyComplianceCall { - if (_from != address(0)) { - // Check if the user has enough unlocked tokens to transfer - uint256 availableAmount = _calculateAvailableAmount(msg.sender, _from); - if (_value > availableAmount) { - revert InsufficientBalanceTokensLocked(_from, _value, availableAmount); - } + function moduleTransferAction(address _from, address /*_to*/, uint256 _value) external override onlyComplianceCall { + if (_from == address(0)) { + return; + } + + (uint256 lockedAmount, uint256 unlockedAmount) = _calculateLockedAmount(msg.sender, _from); + uint256 freeAmount = + IToken(IModularCompliance(msg.sender).getTokenBound()).balanceOf(_from) - lockedAmount - unlockedAmount; + if (_value > freeAmount) { + _updateLockedTokens(_from, _value - freeAmount); } } @@ -120,17 +133,32 @@ contract InitialLockupPeriodModule is AbstractModuleUpgradeable { } /// @inheritdoc IModule - // solhint-disable-next-line no-empty-blocks - function moduleBurnAction(address _from, uint256 _value) external override onlyComplianceCall { } + function moduleBurnAction(address _from, uint256 _value) external override onlyComplianceCall { + (uint256 lockedAmount, uint256 unlockedAmount) = _calculateLockedAmount(msg.sender, _from); + uint256 previousBalance = IToken(IModularCompliance(msg.sender).getTokenBound()).balanceOf(_from) + _value; + + require( + (previousBalance - lockedAmount) >= _value, + InsufficientBalanceTokensLocked(_from, _value, previousBalance - lockedAmount) + ); + + uint256 freeAmount = previousBalance - lockedAmount - unlockedAmount; + if (_value > freeAmount) { + _updateLockedTokens(_from, _value - freeAmount); + } + } /// @inheritdoc IModule function moduleCheck(address _from, address /*_to*/, uint256 _value, address _compliance) external view override returns (bool) { - return _from == address(0) || _calculateAvailableAmount(_compliance, _from) >= _value; + (uint256 lockedAmount, ) = _calculateLockedAmount(_compliance, _from); + + return _from == address(0) + || IToken(IModularCompliance(_compliance).getTokenBound()).balanceOf(_from) - lockedAmount >= _value; } /// @inheritdoc IModule - function canComplianceBind(address /*_compliance*/) external view override returns (bool) { + function canComplianceBind(address /*_compliance*/) external pure override returns (bool) { return true; } @@ -144,15 +172,49 @@ contract InitialLockupPeriodModule is AbstractModuleUpgradeable { return "InitialLockupPeriodModule"; } - /// @dev calculates the available amount of unlocked tokens for a user. + /// @dev updates the locked tokens for a user. + /// @param _user the address of the user. + /// @param _value the amount of tokens to unlock. + function _updateLockedTokens(address _user, uint256 _value) internal { + LockedTokens[] storage lockedTokens = _lockedTokens[msg.sender][_user]; + for (uint256 i; _value > 0 && i < lockedTokens.length; ) { + if (lockedTokens[i].releaseTimestamp <= block.timestamp) { + if (_value >= lockedTokens[i].amount) { + _value -= lockedTokens[i].amount; + + // Remove entry + if (i == lockedTokens.length - 1) { + lockedTokens.pop(); + break; + } else { + lockedTokens[i] = lockedTokens[lockedTokens.length - 1]; + lockedTokens.pop(); + } + } else { + lockedTokens[i].amount -= _value; + break; + } + } + else { + i++; + } + } + } + + /// @dev calculates the locked amount of tokens for a user. /// @param _compliance the address of the compliance contract. /// @param _user the address of the user. - /// @return _availableAmount the available amount of unlocked tokens. - function _calculateAvailableAmount(address _compliance, address _user) internal view returns (uint256 _availableAmount) { + /// @return _lockedAmount the locked amount of tokens. + /// @return _unlockedAmount the unlocked amount of tokens. + function _calculateLockedAmount(address _compliance, address _user) internal view + returns (uint256 _lockedAmount, uint256 _unlockedAmount) { uint256 periodsLength = _lockedTokens[_compliance][_user].length; for (uint256 i; i < periodsLength; i++) { - if (_lockedTokens[_compliance][_user][i].releaseTimestamp <= block.timestamp) { - _availableAmount += _lockedTokens[_compliance][_user][i].amount; + if (_lockedTokens[_compliance][_user][i].releaseTimestamp > block.timestamp) { + _lockedAmount += _lockedTokens[_compliance][_user][i].amount; + } + else { + _unlockedAmount += _lockedTokens[_compliance][_user][i].amount; } } } diff --git a/test/compliances/module-initial-lockup-period.test.ts b/test/compliances/module-initial-lockup-period.test.ts index 53620cba..b3c31472 100644 --- a/test/compliances/module-initial-lockup-period.test.ts +++ b/test/compliances/module-initial-lockup-period.test.ts @@ -38,8 +38,8 @@ describe('InitialLockupPeriodModule', () => { }; } - async function increaseTimestamp(timestamp: number) { - await ethers.provider.send('evm_increaseTime', [timestamp]); + async function increaseTimestamp(days: number) { + await ethers.provider.send('evm_increaseTime', [days * 24 * 60 * 60]); await ethers.provider.send('evm_mine', []); } @@ -68,7 +68,7 @@ describe('InitialLockupPeriodModule', () => { accounts: { aliceWallet }, } = await loadFixture(deployInitialLockupPeriodModuleFullSuite); - await expect(complianceModule.connect(aliceWallet).setLockupPeriod(100)).to.be.revertedWithCustomError( + await expect(complianceModule.connect(aliceWallet).setLockupPeriod(10)).to.be.revertedWithCustomError( complianceModule, 'OnlyBoundComplianceCanCall', ); @@ -79,7 +79,7 @@ describe('InitialLockupPeriodModule', () => { suite: { compliance, complianceModule }, } = await loadFixture(deployInitialLockupPeriodModuleFullSuite); - const lockupPeriod = 100; + const lockupPeriod = 10; const tx = await setLockupPeriod(compliance, complianceModule, lockupPeriod); await expect(tx).to.emit(complianceModule, 'LockupPeriodSet').withArgs(compliance.target, lockupPeriod); @@ -93,7 +93,7 @@ describe('InitialLockupPeriodModule', () => { accounts: { aliceWallet, bobWallet, tokenAgent, complianceSigner }, } = await loadFixture(deployInitialLockupPeriodModuleFullSuite); - const lockupPeriod = 100; + const lockupPeriod = 10; await setLockupPeriod(compliance, complianceModule, lockupPeriod); await token.connect(tokenAgent).mint(aliceWallet.address, 100); @@ -143,4 +143,27 @@ describe('InitialLockupPeriodModule', () => { }); }); }); + + describe('Burn Checks', () => { + it('should allow burn after lockup period', async () => { + const { + suite: { compliance, complianceModule, token }, + accounts: { aliceWallet, tokenAgent }, + } = await loadFixture(deployInitialLockupPeriodModuleFullSuite); + + const lockupPeriod = 10; + await setLockupPeriod(compliance, complianceModule, lockupPeriod); + + await token.connect(tokenAgent).mint(aliceWallet.address, 100); + + // Burn will fail because the lockup period is not over + await expect(token.connect(tokenAgent).burn(aliceWallet.address, 100)) + .to.be.revertedWithCustomError(complianceModule, 'InsufficientBalanceTokensLocked') + .withArgs(aliceWallet.address, 100, 0); + + // Burn will succeed because the lockup period is over + await increaseTimestamp(lockupPeriod); + await token.connect(tokenAgent).burn(aliceWallet.address, 100); + }); + }); }); From d4370d08733763b52a857fd04b034dece28564f3 Mon Sep 17 00:00:00 2001 From: Philippe Gonday Date: Tue, 17 Dec 2024 10:12:01 +0100 Subject: [PATCH 55/55] =?UTF-8?q?=E2=99=BB()=20Gas=20optim=20after=20revie?= =?UTF-8?q?w?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/InitialLockupPeriodModule.sol | 79 +++++++++++-------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/contracts/compliance/modular/modules/InitialLockupPeriodModule.sol b/contracts/compliance/modular/modules/InitialLockupPeriodModule.sol index 1acf5449..d89fe5ba 100644 --- a/contracts/compliance/modular/modules/InitialLockupPeriodModule.sol +++ b/contracts/compliance/modular/modules/InitialLockupPeriodModule.sol @@ -92,8 +92,13 @@ contract InitialLockupPeriodModule is AbstractModuleUpgradeable { uint256 releaseTimestamp; } + struct LockedDetails { + uint256 totalLocked; + LockedTokens[] lockedTokens; + } + mapping(address compliance => uint256 lockupPeriod) private _lockupPeriods; - mapping(address compliance => mapping(address user => LockedTokens[])) private _lockedTokens; + mapping(address compliance => mapping(address user => LockedDetails)) private _lockedDetails; /// @dev initializes the contract and sets the initial state. function initialize() external initializer { @@ -114,9 +119,9 @@ contract InitialLockupPeriodModule is AbstractModuleUpgradeable { return; } - (uint256 lockedAmount, uint256 unlockedAmount) = _calculateLockedAmount(msg.sender, _from); + LockedDetails storage lockedDetails = _lockedDetails[msg.sender][_from]; uint256 freeAmount = - IToken(IModularCompliance(msg.sender).getTokenBound()).balanceOf(_from) - lockedAmount - unlockedAmount; + IToken(IModularCompliance(msg.sender).getTokenBound()).balanceOf(_from) - lockedDetails.totalLocked; if (_value > freeAmount) { _updateLockedTokens(_from, _value - freeAmount); } @@ -124,7 +129,9 @@ contract InitialLockupPeriodModule is AbstractModuleUpgradeable { /// @inheritdoc IModule function moduleMintAction(address _to, uint256 _value) external override onlyComplianceCall { - _lockedTokens[msg.sender][_to].push( + LockedDetails storage lockedDetails = _lockedDetails[msg.sender][_to]; + lockedDetails.totalLocked += _value; + lockedDetails.lockedTokens.push( LockedTokens({ amount: _value, releaseTimestamp: block.timestamp + _lockupPeriods[msg.sender] @@ -134,15 +141,20 @@ contract InitialLockupPeriodModule is AbstractModuleUpgradeable { /// @inheritdoc IModule function moduleBurnAction(address _from, uint256 _value) external override onlyComplianceCall { - (uint256 lockedAmount, uint256 unlockedAmount) = _calculateLockedAmount(msg.sender, _from); + LockedDetails storage lockedDetails = _lockedDetails[msg.sender][_from]; uint256 previousBalance = IToken(IModularCompliance(msg.sender).getTokenBound()).balanceOf(_from) + _value; + uint256 freeAmount = previousBalance - lockedDetails.totalLocked; + + if (freeAmount < _value) { + // We need to calculate more accurately the free amount, as totalLocked can include now unlocked tokens. + freeAmount = freeAmount + _calculateUnlockedAmount(lockedDetails); + } require( - (previousBalance - lockedAmount) >= _value, - InsufficientBalanceTokensLocked(_from, _value, previousBalance - lockedAmount) + freeAmount >= _value, + InsufficientBalanceTokensLocked(_from, _value, freeAmount) ); - uint256 freeAmount = previousBalance - lockedAmount - unlockedAmount; if (_value > freeAmount) { _updateLockedTokens(_from, _value - freeAmount); } @@ -151,10 +163,15 @@ contract InitialLockupPeriodModule is AbstractModuleUpgradeable { /// @inheritdoc IModule function moduleCheck(address _from, address /*_to*/, uint256 _value, address _compliance) external view override returns (bool) { - (uint256 lockedAmount, ) = _calculateLockedAmount(_compliance, _from); + if (_from == address(0)) { + return true; + } + + LockedDetails storage lockedDetails = _lockedDetails[_compliance][_from]; + uint256 balance = IToken(IModularCompliance(_compliance).getTokenBound()).balanceOf(_from); - return _from == address(0) - || IToken(IModularCompliance(_compliance).getTokenBound()).balanceOf(_from) - lockedAmount >= _value; + return (balance - lockedDetails.totalLocked) >= _value + || (balance - lockedDetails.totalLocked + _calculateUnlockedAmount(lockedDetails)) >= _value; } /// @inheritdoc IModule @@ -176,22 +193,22 @@ contract InitialLockupPeriodModule is AbstractModuleUpgradeable { /// @param _user the address of the user. /// @param _value the amount of tokens to unlock. function _updateLockedTokens(address _user, uint256 _value) internal { - LockedTokens[] storage lockedTokens = _lockedTokens[msg.sender][_user]; - for (uint256 i; _value > 0 && i < lockedTokens.length; ) { - if (lockedTokens[i].releaseTimestamp <= block.timestamp) { - if (_value >= lockedTokens[i].amount) { - _value -= lockedTokens[i].amount; + LockedDetails storage lockedDetails = _lockedDetails[msg.sender][_user]; + for (uint256 i; _value > 0 && i < lockedDetails.lockedTokens.length; ) { + if (lockedDetails.lockedTokens[i].releaseTimestamp <= block.timestamp) { + if (_value >= lockedDetails.lockedTokens[i].amount) { + _value -= lockedDetails.lockedTokens[i].amount; // Remove entry - if (i == lockedTokens.length - 1) { - lockedTokens.pop(); + if (i == lockedDetails.lockedTokens.length - 1) { + lockedDetails.lockedTokens.pop(); break; } else { - lockedTokens[i] = lockedTokens[lockedTokens.length - 1]; - lockedTokens.pop(); + lockedDetails.lockedTokens[i] = lockedDetails.lockedTokens[lockedDetails.lockedTokens.length - 1]; + lockedDetails.lockedTokens.pop(); } } else { - lockedTokens[i].amount -= _value; + lockedDetails.lockedTokens[i].amount -= _value; break; } } @@ -201,20 +218,14 @@ contract InitialLockupPeriodModule is AbstractModuleUpgradeable { } } - /// @dev calculates the locked amount of tokens for a user. - /// @param _compliance the address of the compliance contract. - /// @param _user the address of the user. - /// @return _lockedAmount the locked amount of tokens. + /// @dev calculates the unlocked amount of tokens for a user. + /// @param _details the locked details of the user. /// @return _unlockedAmount the unlocked amount of tokens. - function _calculateLockedAmount(address _compliance, address _user) internal view - returns (uint256 _lockedAmount, uint256 _unlockedAmount) { - uint256 periodsLength = _lockedTokens[_compliance][_user].length; - for (uint256 i; i < periodsLength; i++) { - if (_lockedTokens[_compliance][_user][i].releaseTimestamp > block.timestamp) { - _lockedAmount += _lockedTokens[_compliance][_user][i].amount; - } - else { - _unlockedAmount += _lockedTokens[_compliance][_user][i].amount; + function _calculateUnlockedAmount(LockedDetails storage _details) internal view + returns (uint256 _unlockedAmount) { + for (uint256 i; i < _details.lockedTokens.length; i++) { + if (_details.lockedTokens[i].releaseTimestamp <= block.timestamp) { + _unlockedAmount += _details.lockedTokens[i].amount; } } }