diff --git a/contracts/interfaces/engine/IFixDescriptorEngine.sol b/contracts/interfaces/engine/IFixDescriptorEngine.sol new file mode 100644 index 00000000..90ac114f --- /dev/null +++ b/contracts/interfaces/engine/IFixDescriptorEngine.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +/* + * @dev minimum interface to define a FixDescriptorEngine + */ +interface IFixDescriptorEngine { + /** + * @notice Returns the address of the token this engine is bound to. + * @return token The associated token contract address. + */ + function token() external view returns (address token); +} diff --git a/contracts/interfaces/modules/IFixDescriptorEngineModule.sol b/contracts/interfaces/modules/IFixDescriptorEngineModule.sol new file mode 100644 index 00000000..bb8f016c --- /dev/null +++ b/contracts/interfaces/modules/IFixDescriptorEngineModule.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +/* ==== Engine === */ +import {IFixDescriptorEngine} from "../engine/IFixDescriptorEngine.sol"; + +/** + * @title IFixDescriptorEngineModule + * @notice Minimal interface for integrating a FIX descriptor engine module. + * @dev Provides methods to set and retrieve a FIX descriptor engine used for managing FIX descriptors. + */ +interface IFixDescriptorEngineModule { + /* ============ Events ============ */ + /** + * @notice Emitted when a new FIX descriptor engine is set. + * @param newFixDescriptorEngine The address of the newly assigned FIX descriptor engine contract. + */ + event FixDescriptorEngine(IFixDescriptorEngine indexed newFixDescriptorEngine); + /* ============ Error ============ */ + /** + * @dev Reverts if the new FIX descriptor engine is the same as the current one. + */ + error CMTAT_FixDescriptorModule_SameValue(); + /** + * @dev Reverts if the provided engine is not bound to the current token. + */ + error CMTAT_FixDescriptorModule_InvalidTokenBinding(address expectedToken, address actualToken); + /* ============ Functions ============ */ + /** + * @notice Sets the address of the FIX descriptor engine contract. + * @dev The FIX descriptor engine is responsible for managing FIX descriptors and SBE data. + * Emits a {FixDescriptorEngine} event. + * Reverts with {CMTAT_FixDescriptorModule_SameValue} if the new engine is the same as the current one. + * @param fixDescriptorEngine_ The new FIX descriptor engine contract address to set. + */ + function setFixDescriptorEngine( + IFixDescriptorEngine fixDescriptorEngine_ + ) external; + /** + * @notice Returns the currently set FIX descriptor engine. + * @return The address of the active FIX descriptor engine contract. + */ + function fixDescriptorEngine() external view returns (IFixDescriptorEngine); +} diff --git a/contracts/mocks/FixDescriptorEngineMock.sol b/contracts/mocks/FixDescriptorEngineMock.sol new file mode 100644 index 00000000..c2fd9575 --- /dev/null +++ b/contracts/mocks/FixDescriptorEngineMock.sol @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {IFixDescriptorEngine} from "../interfaces/engine/IFixDescriptorEngine.sol"; +import {IFixDescriptor} from "./library/fix/IFixDescriptor.sol"; + +/* + * @title a FixDescriptorEngine mock for testing, not suitable for production + */ +contract FixDescriptorEngineMock is IFixDescriptorEngine, IFixDescriptor { + address public immutable token; + IFixDescriptor.FixDescriptor private _descriptor; + bool private _initialized; + bool private _verifyFieldResult; // for testing verification results + + constructor(address token_, address admin) { + token = token_; + // admin not used but kept for consistency with SnapshotEngineMock pattern + _verifyFieldResult = true; // default to true for tests + } + + /** + * @notice Set the descriptor for testing + * @param descriptor The FixDescriptor struct to store + */ + function setFixDescriptor(IFixDescriptor.FixDescriptor memory descriptor) external { + bytes32 oldRoot = _descriptor.fixRoot; + _descriptor = descriptor; + _initialized = true; + + if (oldRoot != bytes32(0)) { + emit FixDescriptorUpdated(oldRoot, descriptor.fixRoot, descriptor.fixSBEPtr); + } else { + emit FixDescriptorSet( + descriptor.fixRoot, + descriptor.schemaHash, + descriptor.fixSBEPtr, + descriptor.fixSBELen + ); + } + } + + /** + * @notice Set the verifyField result for testing + * @param result The boolean result to return from verifyField + */ + function setVerifyFieldResult(bool result) external { + _verifyFieldResult = result; + } + + /** + * @notice Get the complete FIX descriptor + * @return descriptor The FixDescriptor struct + */ + function getFixDescriptor() external view override returns (IFixDescriptor.FixDescriptor memory descriptor) { + return _descriptor; + } + + /** + * @notice Get the Merkle root commitment + * @return root The fixRoot for verification + */ + function getFixRoot() external view override returns (bytes32 root) { + return _descriptor.fixRoot; + } + + /** + * @notice Verify a specific field against the committed descriptor + * @param pathSBE SBE-encoded bytes of the field path + * @param value Raw FIX value bytes + * @param proof Merkle proof (sibling hashes) + * @param directions Direction array (true=right child, false=left child) + * @return valid True if the proof is valid (returns configured test result) + */ + function verifyField( + bytes calldata pathSBE, + bytes calldata value, + bytes32[] calldata proof, + bool[] calldata directions + ) external view override returns (bool valid) { + // Return configured result for testing + return _verifyFieldResult; + } + + /** + * @notice Get the descriptor engine address + * @return engine Address of the FixDescriptorEngine contract (returns self) + */ + function getDescriptorEngine() external view override returns (address engine) { + return address(this); + } +} diff --git a/contracts/mocks/library/fix/IFixDescriptor.sol b/contracts/mocks/library/fix/IFixDescriptor.sol new file mode 100644 index 00000000..d527a7b0 --- /dev/null +++ b/contracts/mocks/library/fix/IFixDescriptor.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +/** + * @title IFixDescriptor + * @notice Standard interface for assets with embedded FIX descriptors + * @dev Asset contracts (ERC20, ERC721, etc.) implement this to expose their FIX descriptor + * This is a local copy for testing purposes to avoid external package dependencies + */ +interface IFixDescriptor { + /// @notice FIX descriptor structure + struct FixDescriptor { + bytes32 schemaHash; // FIX schema/dictionary hash + bytes32 fixRoot; // Merkle root commitment + address fixSBEPtr; // SSTORE2 data contract address + uint32 fixSBELen; // SBE data length + string schemaURI; // Optional SBE schema URI (ipfs:// or https://) + } + + /// @notice Emitted when descriptor is first set + event FixDescriptorSet( + bytes32 indexed fixRoot, + bytes32 indexed schemaHash, + address fixSBEPtr, + uint32 fixSBELen + ); + + /// @notice Emitted when descriptor is updated + event FixDescriptorUpdated( + bytes32 indexed oldRoot, + bytes32 indexed newRoot, + address newPtr + ); + + /** + * @notice Get the complete FIX descriptor for this asset + * @return descriptor The FixDescriptor struct + */ + function getFixDescriptor() external view returns (FixDescriptor memory descriptor); + + /** + * @notice Get the Merkle root commitment + * @return root The fixRoot for verification + */ + function getFixRoot() external view returns (bytes32 root); + + /** + * @notice Verify a specific field against the committed descriptor + * @param pathSBE SBE-encoded bytes of the field path + * @param value Raw FIX value bytes + * @param proof Merkle proof (sibling hashes) + * @param directions Direction array (true=right child, false=left child) + * @return valid True if the proof is valid + */ + function verifyField( + bytes calldata pathSBE, + bytes calldata value, + bytes32[] calldata proof, + bool[] calldata directions + ) external view returns (bool valid); + + /** + * @notice Get the descriptor engine address (optional) + * @dev Returns address(0) if token uses embedded storage instead of engine + * @return engine Address of the FixDescriptorEngine contract, or address(0) if not using engine + */ + function getDescriptorEngine() external view returns (address engine); +} diff --git a/contracts/modules/0_CMTATBaseCommon.sol b/contracts/modules/0_CMTATBaseCommon.sol index 64f78dd9..7d647b8b 100644 --- a/contracts/modules/0_CMTATBaseCommon.sol +++ b/contracts/modules/0_CMTATBaseCommon.sol @@ -13,6 +13,7 @@ import {ExtraInformationModule} from "./wrapper/extensions/ExtraInformationModul import {ERC20EnforcementModule, ERC20EnforcementModuleInternal} from "./wrapper/extensions/ERC20EnforcementModule.sol"; import {DocumentEngineModule, IERC1643} from "./wrapper/extensions/DocumentEngineModule.sol"; import {SnapshotEngineModule} from "./wrapper/extensions/SnapshotEngineModule.sol"; +import {FixDescriptorEngineModule} from "./wrapper/extensions/FixDescriptorEngineModule.sol"; // options import {ERC20BaseModule, ERC20Upgradeable} from "./wrapper/core/ERC20BaseModule.sol"; /* ==== Interface and other library === */ @@ -30,6 +31,7 @@ abstract contract CMTATBaseCommon is SnapshotEngineModule, ERC20EnforcementModule, DocumentEngineModule, + FixDescriptorEngineModule, ExtraInformationModule, // Interfaces IBurnMintERC20, @@ -108,7 +110,7 @@ abstract contract CMTATBaseCommon is * - Input validation is also managed by the functions burn and mint * - You can mint more tokens than burnt */ - function burnAndMint(address from, address to, uint256 amountToBurn, uint256 amountToMint, bytes calldata data) + function burnAndMint(address from, address to, uint256 amountToBurn, uint256 amountToMint, bytes calldata data) public virtual override(IBurnMintERC20) { ERC20BurnModule.burn(from, amountToBurn, data); ERC20MintModule.mint(to, amountToMint, data); diff --git a/contracts/modules/1_CMTATBaseAccessControl.sol b/contracts/modules/1_CMTATBaseAccessControl.sol index fe4e4757..58664ec5 100644 --- a/contracts/modules/1_CMTATBaseAccessControl.sol +++ b/contracts/modules/1_CMTATBaseAccessControl.sol @@ -15,6 +15,7 @@ import {ExtraInformationModule} from "./wrapper/extensions/ExtraInformationModul import {ERC20EnforcementModule} from "./wrapper/extensions/ERC20EnforcementModule.sol"; import {DocumentEngineModule, IERC1643} from "./wrapper/extensions/DocumentEngineModule.sol"; import {SnapshotEngineModule} from "./wrapper/extensions/SnapshotEngineModule.sol"; +import {FixDescriptorEngineModule} from "./wrapper/extensions/FixDescriptorEngineModule.sol"; // options import {ERC20BaseModule, ERC20Upgradeable} from "./wrapper/core/ERC20BaseModule.sol"; /* ==== Interface and other library === */ @@ -103,4 +104,10 @@ abstract contract CMTATBaseAccessControl is * - the caller must have the `SNAPSHOOTER_ROLE`. */ function _authorizeSnapshots() internal virtual override(SnapshotEngineModule) onlyRole(SNAPSHOOTER_ROLE){} + + /** + * @custom:access-control + * - the caller must have the `DESCRIPTOR_ENGINE_ROLE`. + */ + function _authorizeFixDescriptorEngine() internal virtual override(FixDescriptorEngineModule) onlyRole(DESCRIPTOR_ENGINE_ROLE){} } diff --git a/contracts/modules/wrapper/extensions/FixDescriptorEngineModule.sol b/contracts/modules/wrapper/extensions/FixDescriptorEngineModule.sol new file mode 100644 index 00000000..a9a29eaa --- /dev/null +++ b/contracts/modules/wrapper/extensions/FixDescriptorEngineModule.sol @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +/* ==== OpenZeppelin === */ +import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; +/* ==== Engine === */ +import {IFixDescriptorEngine, IFixDescriptorEngineModule} from "../../../interfaces/modules/IFixDescriptorEngineModule.sol"; + +abstract contract FixDescriptorEngineModule is Initializable, IFixDescriptorEngineModule { + /* ============ State Variables ============ */ + bytes32 public constant DESCRIPTOR_ENGINE_ROLE = keccak256("DESCRIPTOR_ENGINE_ROLE"); + + /* ============ ERC-7201 ============ */ + // keccak256(abi.encode(uint256(keccak256("CMTAT.storage.FixDescriptorEngineModule")) - 1)) & ~bytes32(uint256(0xff)) + bytes32 private constant FixDescriptorEngineModuleStorageLocation = 0xc09aa28957960c2b82e3fad477567fe122f23bca69560181151331ec7041c600; + /* ==== ERC-7201 State Variables === */ + struct FixDescriptorEngineModuleStorage { + IFixDescriptorEngine _fixDescriptorEngine; + } + + /* ============ Modifier ============ */ + modifier onlyDescriptorEngine() { + _authorizeFixDescriptorEngine(); + _; + } + /* ============ Initializer Function ============ */ + /** + * @dev + * + * - The grant to the admin role is done by AccessControlDefaultAdminRules + * - The control of the zero address is done by AccessControlDefaultAdminRules + * + */ + function __FixDescriptorEngineModule_init_unchained(IFixDescriptorEngine fixDescriptorEngine_) + internal virtual onlyInitializing { + if (address(fixDescriptorEngine_) != address (0)) { + FixDescriptorEngineModuleStorage storage $ = _getFixDescriptorEngineModuleStorage(); + _setFixDescriptorEngine($, fixDescriptorEngine_); + } + } + + + /*////////////////////////////////////////////////////////////// + PUBLIC/EXTERNAL FUNCTIONS + //////////////////////////////////////////////////////////////*/ + + /* ============ State Restricted Functions ============ */ + /** + * @inheritdoc IFixDescriptorEngineModule + * @custom:access-control + * - The caller must have the `DESCRIPTOR_ENGINE_ROLE`. + */ + function setFixDescriptorEngine( + IFixDescriptorEngine fixDescriptorEngine_ + ) public virtual override(IFixDescriptorEngineModule) onlyDescriptorEngine { + FixDescriptorEngineModuleStorage storage $ = _getFixDescriptorEngineModuleStorage(); + require($._fixDescriptorEngine != fixDescriptorEngine_, CMTAT_FixDescriptorModule_SameValue()); + if (address(fixDescriptorEngine_) != address(0)) { + address engineToken = fixDescriptorEngine_.token(); + require( + engineToken == address(this), + CMTAT_FixDescriptorModule_InvalidTokenBinding(address(this), engineToken) + ); + } + _setFixDescriptorEngine($, fixDescriptorEngine_); + } + + + /* ============ View functions ============ */ + + /** + * @inheritdoc IFixDescriptorEngineModule + */ + function fixDescriptorEngine() public view virtual override(IFixDescriptorEngineModule) returns (IFixDescriptorEngine) { + FixDescriptorEngineModuleStorage storage $ = _getFixDescriptorEngineModuleStorage(); + return $._fixDescriptorEngine; + } + /*////////////////////////////////////////////////////////////// + INTERNAL/PRIVATE FUNCTIONS + //////////////////////////////////////////////////////////////*/ + + function _setFixDescriptorEngine( + FixDescriptorEngineModuleStorage storage $, IFixDescriptorEngine fixDescriptorEngine_ + ) internal virtual { + $._fixDescriptorEngine = fixDescriptorEngine_; + emit FixDescriptorEngine(fixDescriptorEngine_); + } + + /* ============ Access Control ============ */ + function _authorizeFixDescriptorEngine() internal virtual; + /* ============ ERC-7201 ============ */ + function _getFixDescriptorEngineModuleStorage() private pure returns (FixDescriptorEngineModuleStorage storage $) { + assembly { + $.slot := FixDescriptorEngineModuleStorageLocation + } + } + + +} diff --git a/test/common/FixDescriptorModule/FixDescriptorModuleCommon.js b/test/common/FixDescriptorModule/FixDescriptorModuleCommon.js new file mode 100644 index 00000000..e48bc37c --- /dev/null +++ b/test/common/FixDescriptorModule/FixDescriptorModuleCommon.js @@ -0,0 +1,32 @@ +const { expect } = require('chai') +const { ZERO_ADDRESS } = require('../../utils') + +function FixDescriptorModuleCommon () { + context('FixDescriptor Module Test', function () { + beforeEach(async function () { + if (!this.definedAtDeployment) { + this.fixDescriptorEngineMock = await ethers.deployContract( + 'FixDescriptorEngineMock', + [this.cmtat.target, this.admin] + ) + } + if ((await this.cmtat.fixDescriptorEngine()) === ZERO_ADDRESS) { + await this.cmtat + .connect(this.admin) + .setFixDescriptorEngine(this.fixDescriptorEngineMock.target) + } + }) + it('testCanReturnTheRightAddressIfSet', async function () { + const fixDescriptorEngine = await this.cmtat.fixDescriptorEngine() + expect(this.fixDescriptorEngineMock.target).to.equal(fixDescriptorEngine) + }) + it('testCanSetZeroAddressEngine', async function () { + await this.cmtat + .connect(this.admin) + .setFixDescriptorEngine(ZERO_ADDRESS) + + expect(await this.cmtat.fixDescriptorEngine()).to.equal(ZERO_ADDRESS) + }) + }) +} +module.exports = FixDescriptorModuleCommon diff --git a/test/common/FixDescriptorModule/FixDescriptorModuleSetFixDescriptorEngineCommon.js b/test/common/FixDescriptorModule/FixDescriptorModuleSetFixDescriptorEngineCommon.js new file mode 100644 index 00000000..382e23b8 --- /dev/null +++ b/test/common/FixDescriptorModule/FixDescriptorModuleSetFixDescriptorEngineCommon.js @@ -0,0 +1,69 @@ +const { expect } = require('chai') +const { DESCRIPTOR_ENGINE_ROLE, ZERO_ADDRESS } = require('../../utils.js') + +function FixDescriptorModuleSetFixDescriptorEngineCommon () { + context('FixDescriptorEngineSetTest', function () { + it('testCanBeSetByAdmin', async function () { + this.fixDescriptorEngineMock = await ethers.deployContract( + 'FixDescriptorEngineMock', + [this.cmtat.target, this.admin] + ) + // Act + this.logs = await this.cmtat + .connect(this.admin) + .setFixDescriptorEngine(this.fixDescriptorEngineMock.target) + // Assert + // emits a FixDescriptorEngineSet event + await expect(this.logs) + .to.emit(this.cmtat, 'FixDescriptorEngine') + .withArgs(this.fixDescriptorEngineMock.target) + }) + + it('testCannotBeSetByAdminWithTheSameValue', async function () { + const fixDescriptorEngineCurrent = await this.cmtat.fixDescriptorEngine() + // Act + await expect( + this.cmtat.connect(this.admin).setFixDescriptorEngine(fixDescriptorEngineCurrent) + ).to.be.revertedWithCustomError( + this.cmtat, + 'CMTAT_FixDescriptorModule_SameValue' + ) + }) + + it('testCannotBeSetByNonAdmin', async function () { + this.fixDescriptorEngineMock = await ethers.deployContract( + 'FixDescriptorEngineMock', + [this.cmtat.target, this.admin] + ) + // Act + await expect( + this.cmtat + .connect(this.address1) + .setFixDescriptorEngine(this.fixDescriptorEngineMock.target) + ) + .to.be.revertedWithCustomError( + this.cmtat, + 'AccessControlUnauthorizedAccount' + ) + .withArgs(this.address1.address, DESCRIPTOR_ENGINE_ROLE) + }) + + it('testCannotSetEngineBoundToAnotherToken', async function () { + const otherToken = this.address2.address + this.fixDescriptorEngineMock = await ethers.deployContract( + 'FixDescriptorEngineMock', + [otherToken, this.admin] + ) + + await expect( + this.cmtat.connect(this.admin).setFixDescriptorEngine(this.fixDescriptorEngineMock.target) + ) + .to.be.revertedWithCustomError( + this.cmtat, + 'CMTAT_FixDescriptorModule_InvalidTokenBinding' + ) + .withArgs(this.cmtat.target, otherToken) + }) + }) +} +module.exports = FixDescriptorModuleSetFixDescriptorEngineCommon diff --git a/test/deployment/deploymentUpgradeableUUPSManual.test.js b/test/deployment/deploymentUpgradeableUUPSManual.test.js index 2f91f116..66d50ab5 100644 --- a/test/deployment/deploymentUpgradeableUUPSManual.test.js +++ b/test/deployment/deploymentUpgradeableUUPSManual.test.js @@ -52,7 +52,7 @@ describe('CMTAT UUPS - Manual Deployment', function () { [ZERO_ADDRESS] ) }) - // Core + // Core VersionModuleCommon() PauseModuleCommon() ERC20BaseModuleCommon() diff --git a/test/proxy/modules/FixDescriptorModule/FixDescriptorModule.test.js b/test/proxy/modules/FixDescriptorModule/FixDescriptorModule.test.js new file mode 100644 index 00000000..5e61df5f --- /dev/null +++ b/test/proxy/modules/FixDescriptorModule/FixDescriptorModule.test.js @@ -0,0 +1,19 @@ +const FixDescriptorModuleSetFixDescriptorEngineCommon = require('../../../common/FixDescriptorModule/FixDescriptorModuleSetFixDescriptorEngineCommon') +const FixDescriptorModuleCommon = require('../../../common/FixDescriptorModule/FixDescriptorModuleCommon') +const { + deployCMTATProxy, + fixture, + loadFixture +} = require('../../../deploymentUtils') +describe('Proxy - FixDescriptorModule', function () { + beforeEach(async function () { + Object.assign(this, await loadFixture(fixture)) + this.cmtat = await deployCMTATProxy( + this._.address, + this.admin.address, + this.deployerAddress.address + ) + }) + FixDescriptorModuleCommon() + FixDescriptorModuleSetFixDescriptorEngineCommon() +}) diff --git a/test/proxy/modules/FixDescriptorModule/FixDescriptorModuleConstructor.test.js b/test/proxy/modules/FixDescriptorModule/FixDescriptorModuleConstructor.test.js new file mode 100644 index 00000000..f8382ddd --- /dev/null +++ b/test/proxy/modules/FixDescriptorModule/FixDescriptorModuleConstructor.test.js @@ -0,0 +1,30 @@ +const FixDescriptorModuleCommon = require('../../../common/FixDescriptorModule/FixDescriptorModuleCommon') +const { + deployCMTATProxyWithParameter, + fixture, + loadFixture, + TERMS, + DEPLOYMENT_DECIMAL +} = require('../../../deploymentUtils') + +const { ZERO_ADDRESS } = require('../../../utils') + +describe('Proxy - FixDescriptorModule - Constructor', function () { + beforeEach(async function () { + Object.assign(this, await loadFixture(fixture)) + this.definedAtDeployment = false + this.cmtat = await deployCMTATProxyWithParameter( + this.deployerAddress.address, + this._.address, + this.admin.address, + 'CMTA Token', + 'CMTAT', + DEPLOYMENT_DECIMAL, + 'CMTAT_ISIN', + TERMS, + 'CMTAT_info', + [ZERO_ADDRESS] + ) + }) + FixDescriptorModuleCommon() +}) diff --git a/test/standard/modules/FixDescriptorModule/FixDescriptorModule.test.js b/test/standard/modules/FixDescriptorModule/FixDescriptorModule.test.js new file mode 100644 index 00000000..028d5062 --- /dev/null +++ b/test/standard/modules/FixDescriptorModule/FixDescriptorModule.test.js @@ -0,0 +1,19 @@ +const FixDescriptorModuleSetFixDescriptorEngineCommon = require('../../../common/FixDescriptorModule/FixDescriptorModuleSetFixDescriptorEngineCommon') +const FixDescriptorModuleCommon = require('../../../common/FixDescriptorModule/FixDescriptorModuleCommon') +const { + deployCMTATStandalone, + fixture, + loadFixture +} = require('../../../deploymentUtils') +describe('Standard - FixDescriptorModule', function () { + beforeEach(async function () { + Object.assign(this, await loadFixture(fixture)) + this.cmtat = await deployCMTATStandalone( + this._.address, + this.admin.address, + this.deployerAddress.address + ) + }) + FixDescriptorModuleCommon() + FixDescriptorModuleSetFixDescriptorEngineCommon() +}) diff --git a/test/standard/modules/FixDescriptorModule/FixDescriptorModuleConstructor.test.js b/test/standard/modules/FixDescriptorModule/FixDescriptorModuleConstructor.test.js new file mode 100644 index 00000000..dec9a167 --- /dev/null +++ b/test/standard/modules/FixDescriptorModule/FixDescriptorModuleConstructor.test.js @@ -0,0 +1,30 @@ +const FixDescriptorModuleCommon = require('../../../common/FixDescriptorModule/FixDescriptorModuleCommon') +const { + deployCMTATStandaloneWithParameter, + fixture, + loadFixture, + TERMS, + DEPLOYMENT_DECIMAL +} = require('../../../deploymentUtils') + +const { ZERO_ADDRESS } = require('../../../utils') + +describe('Standard - FixDescriptorModule - Constructor', function () { + beforeEach(async function () { + Object.assign(this, await loadFixture(fixture)) + this.definedAtDeployment = false + this.cmtat = await deployCMTATStandaloneWithParameter( + this.deployerAddress.address, + this._.address, + this.admin.address, + 'CMTA Token', + 'CMTAT', + DEPLOYMENT_DECIMAL, + 'CMTAT_ISIN', + TERMS, + 'CMTAT_info', + [ZERO_ADDRESS] + ) + }) + FixDescriptorModuleCommon() +}) diff --git a/test/utils.js b/test/utils.js index 761eeca3..a14850e7 100644 --- a/test/utils.js +++ b/test/utils.js @@ -23,6 +23,8 @@ module.exports = { '0x0000000000000000000000000000000000000000000000000000000000000000', DOCUMENT_ROLE: '0xdd7c9aafbb91d54fb2041db1d5b172ea665309b32f5fffdbddf452802a1e3b20', + DESCRIPTOR_ENGINE_ROLE: + '0x685e41c7deaeb9fafe5d911d6517cee9d8a679233028ad5b0d8ff59d1c617d0c', // keccak256("DESCRIPTOR_ENGINE_ROLE"); CROSS_CHAIN_ROLE: '0x620d362b92b6ef580d4e86c5675d679fe08d31dff47b72f281959a4eecdd036a', PROXY_UPGRADE_ROLE: