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/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/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/ModuleProxy.sol b/contracts/compliance/modular/modules/ModuleProxy.sol
new file mode 100644
index 00000000..32d921a4
--- /dev/null
+++ b/contracts/compliance/modular/modules/ModuleProxy.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 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
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/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/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..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": {
@@ -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..5134cffd 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,10 @@ describe('ConditionalTransferModule', () => {
const context = await loadFixture(deployComplianceFixture);
const { compliance } = context.suite;
- const conditionalTransferModule = await ethers.deployContract('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);
const mockContract = await ethers.deployContract('MockContract');
@@ -42,6 +45,79 @@ 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('.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 () => {
+ 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..bf446d86 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,9 @@ describe('CountryAllowModule', () => {
const context = await loadFixture(deployComplianceFixture);
const { compliance } = context.suite;
- const countryAllowModule = await ethers.deployContract('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 } };
@@ -38,6 +40,97 @@ 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('.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 () => {
+ 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 {
+ 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 countryAllowModule.connect(deployer).upgradeTo(newImplementation.address);
+
+ // then
+ 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.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;
+ });
+ });
+ });
+
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..b11c5669 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,9 +8,10 @@ describe('CountryRestrictModule', () => {
const context = await loadFixture(deployComplianceFixture);
const { compliance } = context.suite;
- const countryRestrictModule = await ethers.deployContract('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 } };
}
@@ -38,6 +39,79 @@ 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('.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 () => {
+ 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..8adda7e2 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,10 @@ import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-ful
async function deployExchangeMonthlyLimitsFixture() {
const context = await loadFixture(deployComplianceFixture);
- const complianceModule = await ethers.deployContract('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 {
@@ -21,7 +24,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 +68,79 @@ 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('.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 () => {
+ 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..73d37199 100644
--- a/test/compliances/module-max-balance.test.ts
+++ b/test/compliances/module-max-balance.test.ts
@@ -1,12 +1,16 @@
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 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);
@@ -101,6 +105,79 @@ 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('.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 () => {
+ 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..a3c800f1 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,10 @@ import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-ful
async function deploySupplyLimitFixture() {
const context = await loadFixture(deployComplianceFixture);
- const complianceModule = await ethers.deployContract('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 {
@@ -21,7 +24,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 +68,79 @@ 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('.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 () => {
+ 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..4362b4da 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,10 @@ import { deploySuiteWithModularCompliancesFixture } from '../fixtures/deploy-ful
async function deployTimeExchangeLimitsFixture() {
const context = await loadFixture(deployComplianceFixture);
- const complianceModule = await ethers.deployContract('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 {
@@ -21,7 +24,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 +54,79 @@ 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('.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 () => {
+ 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..c3120b61 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,11 @@ async function deployTimeTransferLimitsFixture() {
async function deployTimeTransferLimitsFullSuite() {
const context = await loadFixture(deploySuiteWithModularCompliancesFixture);
- const complianceModule = await ethers.deployContract('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);
@@ -50,6 +55,79 @@ 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('.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 () => {
+ 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..c63e5b6f 100644
--- a/test/compliances/module-transfer-fees.test.ts
+++ b/test/compliances/module-transfer-fees.test.ts
@@ -1,11 +1,16 @@
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';
+import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture';
async function deployTransferFeesFullSuite() {
const context = await loadFixture(deploySuiteWithModularCompliancesFixture);
- const complianceModule = await ethers.deployContract('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);
@@ -30,6 +35,79 @@ 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('.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 () => {
+ 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..3a560dff 100644
--- a/test/compliances/module-transfer-restrict.test.ts
+++ b/test/compliances/module-transfer-restrict.test.ts
@@ -1,11 +1,15 @@
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';
+import { deployComplianceFixture } from '../fixtures/deploy-compliance.fixture';
async function deployTransferRestrictFullSuite() {
const context = await loadFixture(deploySuiteWithModularCompliancesFixture);
- const complianceModule = await ethers.deployContract('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);
@@ -49,6 +53,79 @@ 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('.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 () => {
+ 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 () => {