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 () => {