diff --git a/FAQ.md b/FAQ.md new file mode 100644 index 00000000..f80ef5d2 --- /dev/null +++ b/FAQ.md @@ -0,0 +1,105 @@ +# FAQ + +This FAQ is intended to developers familiar with smart contracts +development. + +## Toolkit support + +> Why do you continue using Truffle instead of migrating to HardHat or Foundry? + +Regarding [Hardhat](https://hardhat.org/): + +- Our tests are not working with Hardhat so to migrate to hardhat, we will have to update our tests which will require a lot of works. +- Moreover, we do not see a use case where hardhat will be better than Truffle. +- Hardhat has a lot of plugins, but for example, for the coverage, we can run the coverage without be fully compatible with Hardhat. + +Regarding [Foundry](https://book.getfoundry.sh/): + +- The plugin "upgrades plugin" by OpenZeppelin is not available with Foundry and it is a very good tool to check the proxy implementation and perform automatic tests. See [https://docs.openzeppelin.com/upgrades-plugins/1.x/](https://docs.openzeppelin.com/upgrades-plugins/1.x/) +- The tests for the gasless module (MetaTx) would be difficult to write + in Solidity, as Foundry requires, see [https://github.com/CMTA/CMTAT/blob/master/test/common/MetaTxModuleCommon.js](https://github.com/CMTA/CMTAT/blob/master/test/common/MetaTxModuleCommon.js) +- The OpenZeppelin libraries that we use have their tests mainly written in JavaScript, which provides a good basis for our tests +- Performance wise, we observed that Foundry is superior to Truffle, notably to test the Snapshot module +- We have a repository [CMTA/CMTAT-Foundry](https://github.com/CMTA/CMTAT-foundry) that provides experimental support for Foundry, but it does not provide complete support and testing for the latest CMTAT version. + + +> Do you plan to fully support Foundry in the near future? + +For the foreseeable future, we plan to keep Truffle as the main +development and testing suite. + +We have not planned to export all the tests from the Truffle suite to +their Solidity version equivalent suitable to Foundry, though some tests +are already available. + +The CMTAT-Foundry repository uses CMTAT as a submodule, whose version is +documented in its +[README](https://github.com/CMTA/CMTAT-Foundry/blob/main/README.md#cmtat---using-the-foundry-suite). + + +> Can Hardhat be used to run tests? + +No, please use Truffle to run the tests. + + +## Modules + +> What is the reason the Snapshot module wasn't audited in version v2.3.0? + +This module was left out of scope because it is not used yet (and not +included in a default deployment) and will be +subject to changes soon. + +> What is the status of [ERC1404](https://erc1404) compatibility? + +We have not planned to be fully compatible with ERC1404 (which, in fact, +is only an EIP at the time of writing). +CMTAT includes the two functions defind by ERC1404, namely +`detectTransferRestriction` and `messageForTransferRestriction`. +Thus CMTAT can provide the same functionality as ERC1404. + +However, from a pure technical perspective, CMTAT is not fully compliant +with the ERC1404 specification, due the way it inherits the ERC20 +interface. + +> What is the purpose of the flag parameter in the Base module? + +It is just a variable to include some additional information under the form of bit fields. +It is not used inside the code because it is destined to provide more +information on the tokens to the "outside", for example for the token +owners. + + +> Is the Validation module optional? + +Generally, for a CMTAT token, the Validation functionality is optional +from the legal perspective (please contact admin@cmta.ch for detailed +information). + +However, in order to use the functions from the Pause and Enforcement +modules, our CMTAT implementation requires the Validation module +Therefore, the Validation module is effectively required *in this +implementation*. + +If you remove the Validation module and want to use the Pause or the +Enforcement module, you have to call the functions of modules inside the +main contracts. It was initially the case but we have changed this +behaviour when addressing an issue reported by a security audit. +Here is an old version: +[https://github.com/CMTA/CMTAT/blob/ed23bfc69cfacc932945da751485c6472705c975/contracts/CMTAT.sol#L205](https://github.com/CMTA/CMTAT/blob/ed23bfc69cfacc932945da751485c6472705c975/contracts/CMTAT.sol#L205), +and the relevant Pull [Request](https://github.com/CMTA/CMTAT/pull/153). + + +## Documentation + +> What is the code coverage of the test suite? + +A [code coverage report](https://github.com/CMTA/CMTAT/blob/master/doc/general/test/coverage/index.html) +is available. + +Normally, you can run the test suite and generate a code coverage report with `npx hardhat coverage`. + +Please clone the repository and open the file inside your browser. + +You will find a summary of all automatic tests in +[test.pdf](https://github.com/CMTA/CMTAT/blob/master/doc/general/test/test.pdf). diff --git a/README.md b/README.md index 6b5ed5e8..48683243 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ The CMTAT was developed by a working group of CMTA's Technical Committee that in The preferred way to receive comments is through the GitHub issue tracker. Private comments and questions can be sent to the CMTA secretariat at admin@cmta.ch. For security matters, please see [SECURITY.md](./SECURITY.MD). +Note that CMTAT may be used in other jurisdictions than Switzerland, and for tokenizing various asset types, beyond equity and debt products. + ## Functionality ### Overview @@ -147,7 +149,7 @@ The second audit covered version [2.2](https://github.com/CMTA/CMTAT/releases/ta Version 2.3 contains the different fixes and improvements related to this audit. -The report is available in [ABDK_CMTA_CMTATRuleEngine_v_1_0.pdf](doc/audits/ABDK_CMTA_CMTATRuleEngine_v_1_0.pdf). +The report is available in [ABDK_CMTA_CMTATRuleEngine_v_1_0.pdf](doc/audits/ABDK_CMTA_CMTATRuleEngine_v_1_0/ABDK_CMTA_CMTATRuleEngine_v_1_0.pdf). ### Tools diff --git a/contracts/CMTAT_PROXY.sol b/contracts/CMTAT_PROXY.sol index 7ae2ae9b..770cf37d 100644 --- a/contracts/CMTAT_PROXY.sol +++ b/contracts/CMTAT_PROXY.sol @@ -6,8 +6,8 @@ import "./modules/CMTAT_BASE.sol"; contract CMTAT_PROXY is CMTAT_BASE { /** - @notice Contract version for the deployment with a proxy - @param forwarderIrrevocable address of the forwarder, required for the gasless support + * @notice Contract version for the deployment with a proxy + * @param forwarderIrrevocable address of the forwarder, required for the gasless support */ /// @custom:oz-upgrades-unsafe-allow constructor constructor( diff --git a/contracts/CMTAT_STANDALONE.sol b/contracts/CMTAT_STANDALONE.sol index 7c726cdc..b183e7e0 100644 --- a/contracts/CMTAT_STANDALONE.sol +++ b/contracts/CMTAT_STANDALONE.sol @@ -6,16 +6,17 @@ import "./modules/CMTAT_BASE.sol"; contract CMTAT_STANDALONE is CMTAT_BASE { /** - @notice Contract version for standalone deployment - @param forwarderIrrevocable address of the forwarder, required for the gasless support - @param admin address of the admin of contract (Access Control) - @param nameIrrevocable name of the token - @param symbolIrrevocable name of the symbol - @param tokenId name of the tokenId - @param terms terms associated with the token - @param ruleEngine address of the ruleEngine to apply rules to transfers - @param information additional information to describe the token - @param flag add information under the form of bit(0, 1) + * @notice Contract version for standalone deployment + * @param forwarderIrrevocable address of the forwarder, required for the gasless support + * @param admin address of the admin of contract (Access Control) + * @param nameIrrevocable name of the token + * @param symbolIrrevocable name of the symbol + * @param decimalsIrrevocable number of decimals used to get its user representation, should be 0 to be compliant with the CMTAT specifications. + * @param tokenId_ name of the tokenId + * @param terms_ terms associated with the token + * @param ruleEngine_ address of the ruleEngine to apply rules to transfers + * @param information_ additional information to describe the token + * @param flag_ add information under the form of bit(0, 1) */ /// @custom:oz-upgrades-unsafe-allow constructor constructor( @@ -23,6 +24,7 @@ contract CMTAT_STANDALONE is CMTAT_BASE { address admin, string memory nameIrrevocable, string memory symbolIrrevocable, + uint8 decimalsIrrevocable, string memory tokenId_, string memory terms_, IEIP1404Wrapper ruleEngine_, @@ -35,6 +37,7 @@ contract CMTAT_STANDALONE is CMTAT_BASE { admin, nameIrrevocable, symbolIrrevocable, + decimalsIrrevocable, tokenId_, terms_, ruleEngine_, diff --git a/contracts/modules/CMTAT_BASE.sol b/contracts/modules/CMTAT_BASE.sol index a05dff87..d6865121 100644 --- a/contracts/modules/CMTAT_BASE.sol +++ b/contracts/modules/CMTAT_BASE.sol @@ -42,14 +42,24 @@ abstract contract CMTAT_BASE is CreditEventsModule { /** - @notice - initialize the proxy contract - The calls to this function will revert if the contract was deployed without a proxy + * @notice + * initialize the proxy contract + * The calls to this function will revert if the contract was deployed without a proxy + * @param admin address of the admin of contract (Access Control) + * @param nameIrrevocable name of the token + * @param symbolIrrevocable name of the symbol + * @param decimalsIrrevocable number of decimals of the token, must be 0 to be compliant with Swiss law as per CMTAT specifications (non-zero decimal number may be needed for other use cases) + * @param tokenId_ name of the tokenId + * @param terms_ terms associated with the token + * @param ruleEngine_ address of the ruleEngine to apply rules to transfers + * @param information_ additional information to describe the token + * @param flag_ add information under the form of bit(0, 1) */ function initialize( address admin, string memory nameIrrevocable, string memory symbolIrrevocable, + uint8 decimalsIrrevocable, string memory tokenId_, string memory terms_, IEIP1404Wrapper ruleEngine_, @@ -60,6 +70,7 @@ abstract contract CMTAT_BASE is admin, nameIrrevocable, symbolIrrevocable, + decimalsIrrevocable, tokenId_, terms_, ruleEngine_, @@ -69,12 +80,13 @@ abstract contract CMTAT_BASE is } /** - @dev calls the different initialize functions from the different modules + * @dev calls the different initialize functions from the different modules */ function __CMTAT_init( address admin, string memory nameIrrevocable, string memory symbolIrrevocable, + uint8 decimalsIrrevocable, string memory tokenId_, string memory terms_, IEIP1404Wrapper ruleEngine_, @@ -107,7 +119,7 @@ abstract contract CMTAT_BASE is __MintModule_init_unchained(); // EnforcementModule_init_unchained is called before ValidationModule_init_unchained due to inheritance __EnforcementModule_init_unchained(); - __ERC20Module_init_unchained(0); + __ERC20Module_init_unchained(decimalsIrrevocable); // PauseModule_init_unchained is called before ValidationModule_init_unchained due to inheritance __PauseModule_init_unchained(); __ValidationModule_init_unchained(); @@ -132,7 +144,7 @@ abstract contract CMTAT_BASE is } /** - @notice Returns the number of decimals used to get its user representation. + * @notice Returns the number of decimals used to get its user representation. */ function decimals() public @@ -157,12 +169,12 @@ abstract contract CMTAT_BASE is return ERC20BaseModule.transferFrom(sender, recipient, amount); } - /* - @dev - SnapshotModule: - - override SnapshotModuleInternal if you add the SnapshotModule - e.g. override(SnapshotModuleInternal, ERC20Upgradeable) - - remove the keyword view + /** + * @dev + * SnapshotModule: + * - override SnapshotModuleInternal if you add the SnapshotModule + * e.g. override(SnapshotModuleInternal, ERC20Upgradeable) + * - remove the keyword view */ function _beforeTokenTransfer( address from, @@ -179,7 +191,7 @@ abstract contract CMTAT_BASE is } /** - @dev This surcharge is not necessary if you do not use the MetaTxModule + * @dev This surcharge is not necessary if you do not use the MetaTxModule */ function _msgSender() internal @@ -191,7 +203,7 @@ abstract contract CMTAT_BASE is } /** - @dev This surcharge is not necessary if you do not use the MetaTxModule + * @dev This surcharge is not necessary if you do not use the MetaTxModule */ function _msgData() internal diff --git a/contracts/modules/wrapper/mandatory/BurnModule.sol b/contracts/modules/wrapper/mandatory/BurnModule.sol index d9398030..b95e02af 100644 --- a/contracts/modules/wrapper/mandatory/BurnModule.sol +++ b/contracts/modules/wrapper/mandatory/BurnModule.sol @@ -7,7 +7,10 @@ import "../../../../openzeppelin-contracts-upgradeable/contracts/proxy/utils/Ini import "../../security/AuthorizationModule.sol"; abstract contract BurnModule is ERC20Upgradeable, AuthorizationModule { - event Burn(address indexed owner, uint256 amount, string reason); + /** + * @notice Emitted when the specified `value` amount of tokens owned by `owner`are destroyed with the given `reason` + */ + event Burn(address indexed owner, uint256 value, string reason); function __BurnModule_init( string memory name_, @@ -35,17 +38,60 @@ abstract contract BurnModule is ERC20Upgradeable, AuthorizationModule { } /** - * @dev Destroys `amount` tokens from `account` - * + * @notice Destroys a `value` amount of tokens from `account`, by transferring it to address(0). + * @dev * See {ERC20-_burn} + * Emits a {Burn} event + * Emits a {Transfer} event with `to` set to the zero address (emits inside _burn). + * Requirements: + * - the caller must have the `BURNER_ROLE`. */ function forceBurn( address account, - uint256 amount, + uint256 value, string memory reason ) public onlyRole(BURNER_ROLE) { - _burn(account, amount); - emit Burn(account, amount, reason); + _burn(account, value); + emit Burn(account, value, reason); + } + + /** + * + * @notice batch version of {forceBurn}. + * @dev + * See {ERC20-_burn} and {OpenZeppelin ERC1155_burnBatch}. + * + * For each burn action: + * -Emits a {Burn} event + * -Emits a {Transfer} event with `to` set to the zero address (emits inside _burn). + * The burn `reason`is the same for all `accounts` which tokens are burnt. + * Requirements: + * - `accounts` and `values` must have the same length + * - the caller must have the `BURNER_ROLE`. + */ + function forceBurnBatch( + address[] calldata accounts, + uint256[] calldata values, + string memory reason + ) public onlyRole(BURNER_ROLE) { + require( + accounts.length > 0, + "CMTAT: accounts is empty" + ); + // We do not check that values is not empty since + // this require will throw an error in this case. + require( + accounts.length == values.length, + "CMTAT: accounts and values length mismatch" + ); + + for (uint256 i = 0; i < accounts.length; ) { + _burn(accounts[i], values[i]); + emit Burn(accounts[i], values[i], reason); + unchecked { + ++i; + } + } } uint256[50] private __gap; diff --git a/contracts/modules/wrapper/mandatory/ERC20BaseModule.sol b/contracts/modules/wrapper/mandatory/ERC20BaseModule.sol index 54590ec0..0ec13ace 100644 --- a/contracts/modules/wrapper/mandatory/ERC20BaseModule.sol +++ b/contracts/modules/wrapper/mandatory/ERC20BaseModule.sol @@ -5,22 +5,24 @@ pragma solidity ^0.8.17; // required OZ imports here import "../../../../openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol"; import "../../../../openzeppelin-contracts-upgradeable/contracts/token/ERC20/ERC20Upgradeable.sol"; - import "../../../libraries/Errors.sol"; abstract contract ERC20BaseModule is ERC20Upgradeable { /* Events */ - event Spend(address indexed owner, address indexed spender, uint256 amount); + /** + @notice Emitted when the specified `spender` spends the specified `value` tokens owned by the specified `owner` reducing the corresponding allowance. + */ + event Spend(address indexed owner, address indexed spender, uint256 value); /* Variables */ uint8 private _decimals; /* Initializers */ /** - * @dev Sets the values for {name} and {symbol}. + * @dev Sets the values for {name}, {symbol} and decimals. * - * All two of these values are immutable: they can only be set once during - * construction. + * These values are immutable: they can only be set once during + * construction/initialization. */ function __ERC20Module_init( string memory name_, @@ -43,64 +45,89 @@ abstract contract ERC20BaseModule is ERC20Upgradeable { /* Methods */ /** - * @notice Returns the number of decimals used to get its user representation. - * @dev - * For example, if `decimals` equals `2`, a balance of `505` tokens should - * be displayed to a user as `5,05` (`505 / 10 ** 2`). - * - * Tokens usually opt for a value of 18, imitating the relationship between - * Ether and Wei. This is the value {ERC20} uses, unless this function is - * overridden; * - * NOTE: This information is only used for _display_ purposes: it in - * no way affects any of the arithmetic of the contract, including - * {IERC20-balanceOf} and {IERC20-transfer}. + * @notice Returns the number of decimals used to get its user representation. + * @inheritdoc ERC20Upgradeable */ function decimals() public view virtual override returns (uint8) { return _decimals; } /** - * @dev See {IERC20-transferFrom}. + * @notice batch version of transfer + * @param tos can not be empty, must have the same length as values + * @param values can not be empty + * @dev See {OpenZeppelin ERC20-transfer & ERC1155-safeBatchTransferFrom}. * - * Emits an {Approval} event indicating the updated allowance. This is not - * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: - * - * - `sender` and `recipient` cannot be the zero address. - * - `sender` must have a balance of at least `amount`. - * - the caller must have allowance for ``sender``'s tokens of at least - * `amount`. + * - `tos` and `values` must have the same length + * - `tos`cannot contain a zero address (check made by transfer) + * - the caller must have a balance cooresponding to the total values + */ + function transferBatch( + address[] calldata tos, + uint256[] calldata values + ) public returns (bool) { + require( + tos.length > 0, + "CMTAT: tos is empty" + ); + // We do not check that values is not empty since + // this require will throw an error in this case. + require( + tos.length == values.length, + "CMTAT: tos and values length mismatch" + ); + for (uint256 i = 0; i < tos.length; ) { + // We call directly the internal function transfer + // The reason is that the public function adds only the owner address recovery + ERC20Upgradeable._transfer(_msgSender(), tos[i], values[i]); + unchecked { + ++i; + } + } + // not really useful + // Here only to keep the same behaviour as transfer + return true; + } + + /** + * @notice Transfers `value` amount of tokens from address `from` to address `to` + * @inheritdoc ERC20Upgradeable + * @custom:dev-cmtat + * Emits a {Spend} event indicating the spended allowance. */ function transferFrom( - address sender, - address recipient, - uint256 amount + address from, + address to, + uint256 value ) public virtual override returns (bool) { - bool result = super.transferFrom(sender, recipient, amount); - // The result will be normally always true because OpenZeppelin uses require to check all the conditions. + bool result = ERC20Upgradeable.transferFrom(from, to, value); + // The result will be normally always true because OpenZeppelin will revert in case of an error if (result) { - emit Spend(sender, _msgSender(), amount); + emit Spend(from, _msgSender(), value); } return result; } /** - * @dev See {IERC20-approve}. - * - * Requirements: - * - * - `spender` cannot be the zero address. + * @notice Allows `spender` to withdraw from your account multiple times, up to the `value` amount + * @dev see {OpenZeppelin ERC20 - approve} */ function approve( address spender, - uint256 amount, + uint256 value, uint256 currentAllowance ) public virtual returns (bool) { - if(allowance(_msgSender(), spender) != currentAllowance) revert Errors.WrongAllowance(allowance(_msgSender(), spender), currentAllowance); - super.approve(spender, amount); + address owner = _msgSender(); + if(allowance(_msgSender(), spender) != currentAllowance) { + revert Errors.WrongAllowance(allowance(owner , spender), currentAllowance); + } + // We call directly the internal function _approve + // The reason is that the public function adds only the owner address recovery + ERC20Upgradeable._approve(owner, spender, value); return true; } diff --git a/contracts/modules/wrapper/mandatory/MintModule.sol b/contracts/modules/wrapper/mandatory/MintModule.sol index 4d6bbaf6..82bdf847 100644 --- a/contracts/modules/wrapper/mandatory/MintModule.sol +++ b/contracts/modules/wrapper/mandatory/MintModule.sol @@ -7,7 +7,11 @@ import "../../../../openzeppelin-contracts-upgradeable/contracts/proxy/utils/Ini import "../../security/AuthorizationModule.sol"; abstract contract MintModule is ERC20Upgradeable, AuthorizationModule { - event Mint(address indexed beneficiary, uint256 amount); + /** + * @notice Emitted when the specified `value` amount of new tokens are created and + * allocated to the specified `account`. + */ + event Mint(address indexed account, uint256 value); function __MintModule_init( string memory name_, @@ -35,17 +39,58 @@ abstract contract MintModule is ERC20Upgradeable, AuthorizationModule { } /** - * @dev Creates `amount` new tokens for `to`. - * - * See {ERC20-_mint}. + * @notice Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0) + * @dev + * See {OpenZeppelin ERC20-_mint}. + * Emits a {Mint} event. + * Emits a {Transfer} event with `from` set to the zero address (emits inside _mint). * * Requirements: + * - `account` cannot be the zero address (check made by _mint). + * - The caller must have the `MINTER_ROLE`. + */ + function mint(address account, uint256 value) public onlyRole(MINTER_ROLE) { + _mint(account, value); + emit Mint(account, value); + } + + /** + * + * @notice batch version of {mint} + * @dev + * See {OpenZeppelin ERC20-_mint} and {OpenZeppelin ERC1155_mintBatch}. + * + * For each mint action: + * - Emits a {Mint} event. + * - Emits a {Transfer} event with `from` set to the zero address (emits inside _mint). * + * Requirements: + * - `accounts` and `values` must have the same length + * - `accounts` cannot contain a zero address (check made by _mint). * - the caller must have the `MINTER_ROLE`. */ - function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) { - _mint(to, amount); - emit Mint(to, amount); + function mintBatch( + address[] calldata accounts, + uint256[] calldata values + ) public onlyRole(MINTER_ROLE) { + require( + accounts.length > 0, + "CMTAT: accounts is empty" + ); + // We do not check that values is not empty since + // this require will throw an error in this case. + require( + accounts.length == values.length, + "CMTAT: accounts and values length mismatch" + ); + + for (uint256 i = 0; i < accounts.length; ) { + _mint(accounts[i], values[i]); + emit Mint(accounts[i], values[i]); + unchecked { + ++i; + } + } } uint256[50] private __gap; diff --git a/contracts/test/CMTATSnapshot/CMTATSnapshotStandaloneTest.sol b/contracts/test/CMTATSnapshot/CMTATSnapshotStandaloneTest.sol index 81f8e164..02055881 100644 --- a/contracts/test/CMTATSnapshot/CMTATSnapshotStandaloneTest.sol +++ b/contracts/test/CMTATSnapshot/CMTATSnapshotStandaloneTest.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.17; import "./CMTAT_BASE_SnapshotTest.sol"; contract CMTATSnapshotStandaloneTest is CMTAT_BASE_SnapshotTest { - /** + /** @notice Contract version for standalone deployment @param forwarderIrrevocable address of the forwarder, required for the gasless support @param admin address of the admin of contract (Access Control) @@ -23,11 +23,12 @@ contract CMTATSnapshotStandaloneTest is CMTAT_BASE_SnapshotTest { address admin, string memory nameIrrevocable, string memory symbolIrrevocable, - string memory tokenId, - string memory terms, - IEIP1404Wrapper ruleEngine, - string memory information, - uint256 flag + uint8 decimalsIrrevocable, + string memory tokenId_, + string memory terms_, + IEIP1404Wrapper ruleEngine_, + string memory information_, + uint256 flag_ ) MetaTxModule(forwarderIrrevocable) { // Initialize the contract to avoid front-running // Warning : do not initialize the proxy @@ -35,11 +36,12 @@ contract CMTATSnapshotStandaloneTest is CMTAT_BASE_SnapshotTest { admin, nameIrrevocable, symbolIrrevocable, - tokenId, - terms, - ruleEngine, - information, - flag + decimalsIrrevocable, + tokenId_, + terms_, + ruleEngine_, + information_, + flag_ ); } diff --git a/contracts/test/CMTATSnapshot/CMTAT_BASE_SnapshotTest.sol b/contracts/test/CMTATSnapshot/CMTAT_BASE_SnapshotTest.sol index 21d1149b..6ef6b51d 100644 --- a/contracts/test/CMTATSnapshot/CMTAT_BASE_SnapshotTest.sol +++ b/contracts/test/CMTATSnapshot/CMTAT_BASE_SnapshotTest.sol @@ -41,7 +41,7 @@ abstract contract CMTAT_BASE_SnapshotTest is DebtBaseModule, CreditEventsModule { - /** +/** @notice initialize the proxy contract The calls to this function will revert if the contract was deployed without a proxy @@ -50,37 +50,39 @@ abstract contract CMTAT_BASE_SnapshotTest is address admin, string memory nameIrrevocable, string memory symbolIrrevocable, - string memory tokenId, - string memory terms, - IEIP1404Wrapper ruleEngine, - string memory information, - uint256 flag + uint8 decimalsIrrevocable, + string memory tokenId_, + string memory terms_, + IEIP1404Wrapper ruleEngine_, + string memory information_, + uint256 flag_ ) public initializer { __CMTAT_init( admin, nameIrrevocable, symbolIrrevocable, - tokenId, - terms, - ruleEngine, - information, - flag + decimalsIrrevocable, + tokenId_, + terms_, + ruleEngine_, + information_, + flag_ ); } /** @dev calls the different initialize functions from the different modules - @param admin the address has to be different from 0, check made in AuthorizationModule */ function __CMTAT_init( address admin, string memory nameIrrevocable, string memory symbolIrrevocable, - string memory tokenId, - string memory terms, - IEIP1404Wrapper ruleEngine, - string memory information, - uint256 flag + uint8 decimalsIrrevocable, + string memory tokenId_, + string memory terms_, + IEIP1404Wrapper ruleEngine_, + string memory information_, + uint256 flag_ ) internal onlyInitializing { /* OpenZeppelin library */ // OZ init_unchained functions are called firstly due to inheritance @@ -97,10 +99,9 @@ abstract contract CMTAT_BASE_SnapshotTest is /* SnapshotModule: Add this call in case you add the SnapshotModule - */ __Snapshot_init_unchained(); - - __Validation_init_unchained(ruleEngine); + */ + __Validation_init_unchained(ruleEngine_); /* Wrapper */ // AuthorizationModule_init_unchained is called firstly due to inheritance @@ -109,7 +110,7 @@ abstract contract CMTAT_BASE_SnapshotTest is __MintModule_init_unchained(); // EnforcementModule_init_unchained is called before ValidationModule_init_unchained due to inheritance __EnforcementModule_init_unchained(); - __ERC20Module_init_unchained(0); + __ERC20Module_init_unchained(decimalsIrrevocable); // PauseModule_init_unchained is called before ValidationModule_init_unchained due to inheritance __PauseModule_init_unchained(); __ValidationModule_init_unchained(); @@ -119,11 +120,12 @@ abstract contract CMTAT_BASE_SnapshotTest is Add this call in case you add the SnapshotModule */ __SnasphotModule_init_unchained(); + /* Other modules */ __DebtBaseModule_init_unchained(); __CreditEvents_init_unchained(); - __Base_init_unchained(tokenId, terms, information, flag); + __Base_init_unchained(tokenId_, terms_, information_, flag_); /* own function */ __CMTAT_init_unchained(); diff --git a/contracts/test/killTest/CMTATKillTest.sol b/contracts/test/killTest/CMTATKillTest.sol index c3a3c7a0..c8b8c2d0 100644 --- a/contracts/test/killTest/CMTATKillTest.sol +++ b/contracts/test/killTest/CMTATKillTest.sol @@ -66,21 +66,23 @@ contract CMTAT_KILL_TEST is address admin, string memory nameIrrevocable, string memory symbolIrrevocable, - string memory tokenId, - string memory terms, - IEIP1404Wrapper ruleEngine, - string memory information, - uint256 flag + uint8 decimalsIrrevocable, + string memory tokenId_, + string memory terms_, + IEIP1404Wrapper ruleEngine_, + string memory information_, + uint256 flag_ ) public initializer { __CMTAT_init( admin, nameIrrevocable, symbolIrrevocable, - tokenId, - terms, - ruleEngine, - information, - flag + decimalsIrrevocable, + tokenId_, + terms_, + ruleEngine_, + information_, + flag_ ); } @@ -91,11 +93,12 @@ contract CMTAT_KILL_TEST is address admin, string memory nameIrrevocable, string memory symbolIrrevocable, - string memory tokenId, - string memory terms, - IEIP1404Wrapper ruleEngine, - string memory information, - uint256 flag + uint8 decimalsIrrevocable, + string memory tokenId_, + string memory terms_, + IEIP1404Wrapper ruleEngine_, + string memory information_, + uint256 flag_ ) internal onlyInitializing { /* OpenZeppelin library */ // OZ init_unchained functions are called firstly due to inheritance @@ -114,7 +117,7 @@ contract CMTAT_KILL_TEST is Add this call in case you add the SnapshotModule __Snapshot_init_unchained(); */ - __Validation_init_unchained(ruleEngine); + __Validation_init_unchained(ruleEngine_); /* Wrapper */ // AuthorizationModule_init_unchained is called firstly due to inheritance @@ -123,7 +126,7 @@ contract CMTAT_KILL_TEST is __MintModule_init_unchained(); // EnforcementModule_init_unchained is called before ValidationModule_init_unchained due to inheritance __EnforcementModule_init_unchained(); - __ERC20Module_init_unchained(0); + __ERC20Module_init_unchained(decimalsIrrevocable); // PauseModule_init_unchained is called before ValidationModule_init_unchained due to inheritance __PauseModule_init_unchained(); __ValidationModule_init_unchained(); @@ -137,7 +140,7 @@ contract CMTAT_KILL_TEST is /* Other modules */ __DebtBaseModule_init_unchained(); __CreditEvents_init_unchained(); - __Base_init_unchained(tokenId, terms, information, flag); + __Base_init_unchained(tokenId_, terms_, information_, flag_); /* own function */ __CMTAT_init_unchained(); diff --git a/doc/audits/ABDK-CMTAT-audit-20210910.pdf b/doc/audits/ABDK-CMTAT-audit-20210910/ABDK-CMTAT-audit-20210910.pdf similarity index 100% rename from doc/audits/ABDK-CMTAT-audit-20210910.pdf rename to doc/audits/ABDK-CMTAT-audit-20210910/ABDK-CMTAT-audit-20210910.pdf diff --git a/doc/audits/workDocument/CMTAT-Audit-20210910-summary.odt b/doc/audits/ABDK-CMTAT-audit-20210910/CMTAT-Audit-20210910-summary.odt similarity index 100% rename from doc/audits/workDocument/CMTAT-Audit-20210910-summary.odt rename to doc/audits/ABDK-CMTAT-audit-20210910/CMTAT-Audit-20210910-summary.odt diff --git a/doc/audits/CMTAT-Audit-20210910-summary.pdf b/doc/audits/ABDK-CMTAT-audit-20210910/CMTAT-Audit-20210910-summary.pdf similarity index 100% rename from doc/audits/CMTAT-Audit-20210910-summary.pdf rename to doc/audits/ABDK-CMTAT-audit-20210910/CMTAT-Audit-20210910-summary.pdf diff --git a/doc/audits/ABDK_CMTA_CMTATRuleEngine_v_1_0.pdf b/doc/audits/ABDK_CMTA_CMTATRuleEngine_v_1_0/ABDK_CMTA_CMTATRuleEngine_v_1_0.pdf similarity index 100% rename from doc/audits/ABDK_CMTA_CMTATRuleEngine_v_1_0.pdf rename to doc/audits/ABDK_CMTA_CMTATRuleEngine_v_1_0/ABDK_CMTA_CMTATRuleEngine_v_1_0.pdf diff --git a/doc/audits/ABDK_CMTA_CMTATRuleEngine_v_1_0/Taurus. Audit 3.3. Collected.ods b/doc/audits/ABDK_CMTA_CMTATRuleEngine_v_1_0/Taurus. Audit 3.3. Collected.ods new file mode 100644 index 00000000..a544cd7e Binary files /dev/null and b/doc/audits/ABDK_CMTA_CMTATRuleEngine_v_1_0/Taurus. Audit 3.3. Collected.ods differ diff --git a/doc/audits/ABDK_CMTA_CMTATRuleEngine_v_1_0/Taurus.Audit3.1.CollectedIssues.ods b/doc/audits/ABDK_CMTA_CMTATRuleEngine_v_1_0/Taurus.Audit3.1.CollectedIssues.ods new file mode 100644 index 00000000..683b6679 Binary files /dev/null and b/doc/audits/ABDK_CMTA_CMTATRuleEngine_v_1_0/Taurus.Audit3.1.CollectedIssues.ods differ diff --git a/doc/audits/workDocument/Taurus.Audit3.1.CollectedIssues.ods b/doc/audits/workDocument/Taurus.Audit3.1.CollectedIssues.ods deleted file mode 100644 index 2221c13c..00000000 Binary files a/doc/audits/workDocument/Taurus.Audit3.1.CollectedIssues.ods and /dev/null differ diff --git a/doc/modules/presentation/mandatory/burn.md b/doc/modules/presentation/mandatory/burn.md index 62b7311e..5043d426 100644 --- a/doc/modules/presentation/mandatory/burn.md +++ b/doc/modules/presentation/mandatory/burn.md @@ -26,28 +26,6 @@ This document defines Burn Module for the CMTA Token specification. -## Sūrya's Description Report - -### Files Description Table - - -| File Name | SHA-1 Hash | -| ------------------------------------------ | ---------------------------------------- | -| ./modules/wrapper/mandatory/BurnModule.sol | 3547e217049388e5b1a48524255301aac8d301de | - - -### Contracts Description Table - - -| Contract | Type | Bases | | | -| :------------: | :-------------------------: | :-----------------------------------: | :------------: | :--------------: | -| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | -| | | | | | -| **BurnModule** | Implementation | ERC20Upgradeable, AuthorizationModule | | | -| └ | __BurnModule_init | Internal 🔒 | 🛑 | onlyInitializing | -| └ | __BurnModule_init_unchained | Internal 🔒 | 🛑 | onlyInitializing | -| └ | forceBurn | Public ❗️ | 🛑 | onlyRole | - ### Legend @@ -64,28 +42,54 @@ This section describes the Ethereum API of Burn Module. #### `forceBurn(address,uint256,string)` -##### Signature: +##### Definition ```solidity function forceBurn(address account,uint256 amount,string memory reason) public onlyRole(BURNER_ROLE) ``` -##### Description: +##### Description + +Destroys a `value` amount of tokens from `account`, by transferring it to address(0). + +##### Requirements + +Only authorized users (*BURNER_ROLE*) are allowed to call this function. + +#### `forceBurnBatch(address[],uint256[],string) ` -Redeem the given `amount` of tokens from the given `account`. -Only authorized users are allowed to call this function. +##### Definition + +```solidity +function forceBurnBatch(address[] calldata accounts,uint256[] calldata amounts,string memory reason) +public onlyRole(BURNER_ROLE) +``` + +##### Description + +For each account in `accounts`, destroys a `value` amount of tokens from `account`, by transferring it to address(0). + +The burn `reason`is the same for all `accounts` which tokens are burnt. + +##### Requirements + +- `accounts` and `values` must have the same length + +- The caller must have the `BURNER_ROLE`. ### Events #### `Burn(address,uint,string)` -##### Signature: +##### Definition ```solidity event Burn(address indexed owner, uint256 amount, string reason) ``` -##### Description: +##### Description + +Emitted when the specified `value` amount of tokens owned by `owner`are destroyed with the given `reason` -Emitted when the specified `amount` of tokens was burnt from the specified `account`. +​ diff --git a/doc/modules/presentation/mandatory/enforcement.md b/doc/modules/presentation/mandatory/enforcement.md index e7ab2a8b..77e7c34e 100644 --- a/doc/modules/presentation/mandatory/enforcement.md +++ b/doc/modules/presentation/mandatory/enforcement.md @@ -14,7 +14,7 @@ This document defines Enforcement Module for the CMTA Token specification. #### EnforcementModule -![surya_inheritance_EnforcementModule.sol](/home/ryan/Downloads/CM/cmtat-2.3/CMTAT-doc/doc/modules/schema/surya_inheritance/surya_inheritance_EnforcementModule.sol.png) +![surya_inheritance_EnforcementModule.sol](../../schema/surya_inheritance/surya_inheritance_EnforcementModule.sol.png) #### EnforcementModuleInternal diff --git a/doc/modules/presentation/mandatory/erc20base.md b/doc/modules/presentation/mandatory/erc20base.md index 8b72035d..26c59790 100644 --- a/doc/modules/presentation/mandatory/erc20base.md +++ b/doc/modules/presentation/mandatory/erc20base.md @@ -22,7 +22,7 @@ The ERC20Base Module sets forth the ERC20 basic functionalities a token must hav ### Graph -![surya_graph_ERC20BaseModule.sol](../..//schema/surya_graph/surya_graph_ERC20BaseModule.sol.png) +![surya_graph_ERC20BaseModule.sol](/home/ryan/Downloads/no_backup/CM/cmtat-2.3/CMTAT/out/surya_graph/surya_graph_ERC20BaseModule.sol.png) ## Sūrya's Description Report @@ -33,7 +33,6 @@ The ERC20Base Module sets forth the ERC20 basic functionalities a token must hav | ----------------------------------------------- | ---------------------------------------- | | ./modules/wrapper/mandatory/ERC20BaseModule.sol | fdaf8d8a710a4ae6166fb0e491018c559acb4e89 | - ### Contracts Description Table @@ -45,10 +44,10 @@ The ERC20Base Module sets forth the ERC20 basic functionalities a token must hav | └ | __ERC20Module_init | Internal 🔒 | 🛑 | onlyInitializing | | └ | __ERC20Module_init_unchained | Internal 🔒 | 🛑 | onlyInitializing | | └ | decimals | Public ❗️ | | NO❗️ | +| └ | transferBatch | Public ❗️ | 🛑 | NO❗️ | | └ | transferFrom | Public ❗️ | 🛑 | NO❗️ | | └ | approve | Public ❗️ | 🛑 | NO❗️ | - ### Legend | Symbol | Meaning | @@ -62,101 +61,113 @@ Base Module API for Ethereum blockchain extends the [ERC-20](https://github.com/ ### Functions -#### `totalSupply()` +#### OpenZeppelin + +##### `totalSupply()` Origin: OpenZeppelin (ERC20Upgradeable) -##### Definition: +###### Definition ```solidity -function totalSupply() -external view +function totalSupply() public view virtual returns (uint256) ``` -##### Description: +###### Description Return the total number of tokens currently in circulation. -#### `balanceOf(address)` +##### `balanceOf(address)` Origin: OpenZeppelin (ERC20Upgradeable) -##### Definition: +###### Definition ```solidity function balanceOf(address account) -external view +public view virtual returns (uint256) ``` -##### Description: +###### Description Return the number of tokens currently owned by the given `owner`. -#### `transfer(address,uint256)` +##### `transfer(address,uint256)` Origin: OpenZeppelin (ERC20Upgradeable) -##### Definition: +###### Definition ```solidity -function transfer(address to, uint256 amount) -external +function transfer(address to, uint256 value) +public virtual returns (bool) ``` -##### Description: +###### Description Transfer the given `amount` of tokens from the caller to the given `destination` address. The function returns `true` on success and reverts on error. -#### `approve(address,uint256)` +###### Requirements + + * `to` cannot be the zero address. + * the caller must have a balance of at least `value`. + +##### `approve(address,uint256)` Origin: OpenZeppelin (ERC20Upgradeable) -##### Definition: +###### Definition ```solidity -function approve(address spender, uint256 amount) -external +function approve(address spender, uint256 value) +public virtual returns (bool) ``` -##### Description: +###### Description Allow the given `spender` to transfer at most the given `amount` of tokens from the caller. The function returns `true` on success and reverts of error. -#### `allowance(address,address)` +###### Requirement + +`spender` cannot be the zero address. + +##### `allowance(address,address)` Origin: OpenZeppelin (ERC20Upgradeable) -##### Definition: +###### Definition ```solidity function allowance(address owner, address spender) -external view +public view virtual returns (uint256) ``` -##### Description: +###### Description Return the number of tokens the given `spender` is currently allowed to transfer from the given `owner`. -#### `approve(address,uint256,uint256)` +#### CMTAT -##### Definition: +##### `approve(address,uint256,uint256)` + +###### Definition ```solidity -function approve(address spender,uint256 amount,uint256 currentAllowance) +function approve(address spender,uint256 value,uint256 currentAllowance) public virtual returns (bool) ``` -##### Description: +###### Description -Allow the given `spender` to transfer at most the given `amount` of tokens from the caller. +Allows `spender` to withdraw from your account multiple times, up to the `value` amount The function may be successfully executed only when the given `currentAllowance` values equals to the amount of token the spender is currently allowed to transfer from the caller. The function returns `true` on success and reverts of error. @@ -174,62 +185,79 @@ So, Bob got 210 tokens in total, while Alice never means to allow him to transfe In order to mitigate this kind of attack, Alice at step 3 calls `approve (bob, 110, 100)`. Such call could only succeed if the allowance is still 100, i.e. Bob's attempt to front run the transaction will make Alice's transaction to fail. -#### `transferFrom(address,address,uint256)` +###### Requirement -##### Definition: +- The given `currentAllowance` value has to be equal to the amount of token the spender is currently allowed to transfer from the caller. +- `spender`and the sender cannot be the zero address (check made by `OpenZeppelin-_approve`). + +##### `transferFrom(address,address,uint256)` + +This function overrides the function `transferFrom`from OpenZeppelin + +###### Definition ```solidity -function transferFrom(address sender,address recipient,uint256 amount) +function transferFrom(address from,address to,uint256 value) public virtual override -returns (bool) +returns (bool) ``` -##### Description: +###### Description -Transfer the given `amount` of tokens from the given `owner` to the given `destination` address. -`sender` and `recipient` cannot be the zero address. -The function returns `true` on success and reverts of error. +Transfers `value` amount of tokens from address `from` to address `to` + +The function returns `true` on success, nothing if the parent function return false. The behavior of the parent function in case of an error is to revert rather than returned false. + +###### Requirement + +`from` and `to` cannot be the zero address. ### Events -#### `Transfer(address,address,uint256)` +#### OpenZeppelin + +##### `Transfer(address,address,uint256)` Origin: OpenZeppelin (ERC20Upgradeable) -##### Definition: +###### Definition ```solidity event Transfer(address indexed from, address indexed to, uint256 value) ``` -##### Description: +###### Description -Emitted when the specified `amount` of tokens was transferred from the specified `origin` address to the specified `destination` address. +Emitted when `value` tokens are moved from one account (`from`) to another (`to`). -#### `Approval(address,address,uint256)` +Note that `value` may be zero. + +##### `Approval(address,address,uint256)` Origin: OpenZeppelin (ERC20Upgradeable) -##### Definition: +###### Definition ```solidity event Approval(address indexed owner, address indexed spender, uint256 value) ``` -##### Description: +###### Description + +Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance. -Emitted when the specified `owner` allowed the specified `spender` to transfer the specified `amount` of tokens. +#### CMTAT -#### `Spend(address,address,uint256)` +##### `Spend(address,address,uint256)` -##### Definition: +###### Definition ```solidity -event Spend (address indexed owner, address indexed spender, uint256 amount) +event Spend (address indexed owner, address indexed spender, uint256 value) ``` -##### Description: +###### Description -Emitted when the specified `spender` spends the specified `amount` of the tokens owned by the specified `owner` reducing the corresponding allowance. +Emitted when the specified `spender` spends the specified `value` tokens owned by the specified `owner` reducing the corresponding allowance. This event is not defined by ERC-20 and is needed to track allowance changes. diff --git a/doc/modules/presentation/mandatory/mint.md b/doc/modules/presentation/mandatory/mint.md index 6651c6d1..af3f3474 100644 --- a/doc/modules/presentation/mandatory/mint.md +++ b/doc/modules/presentation/mandatory/mint.md @@ -33,7 +33,7 @@ This document defines Mint Module for the CMTA Token specification. | File Name | SHA-1 Hash | | ------------------------------------------ | ---------------------------------------- | -| ./modules/wrapper/mandatory/MintModule.sol | c0300d093480b66e7a9c5acd1a1c46c34f6221bb | +| ./modules/wrapper/mandatory/MintModule.sol | 3d6fa6f2890f85f4f426aee39ea2ee31203f2109 | ### Contracts Description Table @@ -47,6 +47,9 @@ This document defines Mint Module for the CMTA Token specification. | └ | __MintModule_init | Internal 🔒 | 🛑 | onlyInitializing | | └ | __MintModule_init_unchained | Internal 🔒 | 🛑 | onlyInitializing | | └ | mint | Public ❗️ | 🛑 | onlyRole | +| └ | mintBatch | Public ❗️ | 🛑 | onlyRole | + + ### Legend @@ -56,6 +59,8 @@ This document defines Mint Module for the CMTA Token specification. | 🛑 | Function can modify state | | 💵 | Function is payable | + + ## API for Ethereum This section describes the Ethereum API of Issue Module. @@ -64,31 +69,57 @@ This section describes the Ethereum API of Issue Module. #### `mint(address,uint256)` -##### Definition: +##### Definition ```solidity -function mint(address to, uint256 amount) +function mint(address account, uint256 value) public onlyRole(MINTER_ROLE) ``` -##### Description: +##### Description + + Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0) + + +##### Requirements + +- Only authorized users (`MINTER_ROLE`) are allowed to call this function. +- `account` cannot be the zero address (check made by _mint). + +#### `mintBatch(address[],uint256[]) ` + +##### Definition + +```solidity +function mintBatch(address[] calldata accounts,uint256[] calldata values) +public onlyRole(MINTER_ROLE) +``` + +##### Description + +For each address in `accounts`, create the corresponding amount of tokens given by `amounts` and allocate them to the given address`to`. + +##### Requirements + +Only authorized users (`MINTER_ROLE`) are allowed to call this function + +`accounts` and `values` must have the same length -Create the given `amount` of tokens and allocate them to the given address`to`. -Only authorized users are allowed to call this function. +`accounts` cannot contain a zero address (check made by _mint). ### Events #### `Mint(address,uint256)` -##### Definition: +##### Definition ```solidity -event Mint (address indexed beneficiary,uint256 amount) +event Mint(address indexed account, uint256 value) ``` ##### Description -Emitted when the specified `amount` of new tokens was created and -allocated to the specified `beneficiary`. +Emitted when the specified `value` amount of new tokens are created and +allocated to the specified `account`. diff --git a/doc/modules/schema/sol2uml/mandatory/BurnModule.svg b/doc/modules/schema/sol2uml/mandatory/BurnModule.svg index 6a6c60e2..59a74bc0 100644 --- a/doc/modules/schema/sol2uml/mandatory/BurnModule.svg +++ b/doc/modules/schema/sol2uml/mandatory/BurnModule.svg @@ -4,69 +4,70 @@ - - + + UmlClassDiagram - + cluster_0 - -contracts/modules/security + +contracts/modules/security cluster_1 - + contracts/modules/wrapper/mandatory - + -19 - -<<Abstract>> -AuthorizationModule -contracts/modules/security/AuthorizationModule.sol - -Private: -   __gap: uint256[50] -Public: -   BURNER_ROLE: bytes32 -   ENFORCER_ROLE: bytes32 -   MINTER_ROLE: bytes32 -   PAUSER_ROLE: bytes32 -   SNAPSHOOTER_ROLE: bytes32 -   DEBT_ROLE: bytes32 -   DEBT_CREDIT_EVENT_ROLE: bytes32 - -Internal: -    __AuthorizationModule_init(admin: address) <<onlyInitializing>> -    __AuthorizationModule_init_unchained(admin: address) <<onlyInitializing>> -Public: -    hasRole(role: bytes32, account: address): bool +17 + +<<Abstract>> +AuthorizationModule +contracts/modules/security/AuthorizationModule.sol + +Private: +   __gap: uint256[50] +Public: +   BURNER_ROLE: bytes32 +   ENFORCER_ROLE: bytes32 +   MINTER_ROLE: bytes32 +   PAUSER_ROLE: bytes32 +   SNAPSHOOTER_ROLE: bytes32 +   DEBT_ROLE: bytes32 +   DEBT_CREDIT_EVENT_ROLE: bytes32 + +Internal: +    __AuthorizationModule_init(admin: address) <<onlyInitializing>> +    __AuthorizationModule_init_unchained(admin: address) <<onlyInitializing>> +Public: +    hasRole(role: bytes32, account: address): bool - + -24 - -<<Abstract>> -BurnModule -contracts/modules/wrapper/mandatory/BurnModule.sol - -Private: -   __gap: uint256[50] - -Internal: -    __BurnModule_init(name_: string, symbol_: string, admin: address) <<onlyInitializing>> -    __BurnModule_init_unchained() <<onlyInitializing>> -Public: -    <<event>> Burn(owner: address, amount: uint256, reason: string) -    forceBurn(account: address, amount: uint256, reason: string) <<onlyRole>> +27 + +<<Abstract>> +BurnModule +contracts/modules/wrapper/mandatory/BurnModule.sol + +Private: +   __gap: uint256[50] + +Internal: +    __BurnModule_init(name_: string, symbol_: string, admin: address) <<onlyInitializing>> +    __BurnModule_init_unchained() <<onlyInitializing>> +Public: +    <<event>> Burn(owner: address, value: uint256, reason: string) +    forceBurn(account: address, value: uint256, reason: string) <<onlyRole>> +    forceBurnBatch(accounts: address[], values: uint256[], reason: string) <<onlyRole>> - + -24->19 - - +27->17 + + diff --git a/doc/modules/schema/sol2uml/mandatory/ERC20BaseModule.svg b/doc/modules/schema/sol2uml/mandatory/ERC20BaseModule.svg index bcf5742a..71f5fcd9 100644 --- a/doc/modules/schema/sol2uml/mandatory/ERC20BaseModule.svg +++ b/doc/modules/schema/sol2uml/mandatory/ERC20BaseModule.svg @@ -4,36 +4,37 @@ - - + + UmlClassDiagram - + cluster_0 - + contracts/modules/wrapper/mandatory - + -25 - -<<Abstract>> -ERC20BaseModule -contracts/modules/wrapper/mandatory/ERC20BaseModule.sol - -Private: -   _decimals: uint8 -   __gap: uint256[50] - -Internal: -    __ERC20Module_init(name_: string, symbol_: string, decimals_: uint8) <<onlyInitializing>> -    __ERC20Module_init_unchained(decimals_: uint8) <<onlyInitializing>> -Public: -    <<event>> Spend(owner: address, spender: address, amount: uint256) -    decimals(): uint8 -    transferFrom(sender: address, recipient: address, amount: uint256): bool -    approve(spender: address, amount: uint256, currentAllowance: uint256): bool +28 + +<<Abstract>> +ERC20BaseModule +contracts/modules/wrapper/mandatory/ERC20BaseModule.sol + +Private: +   _decimals: uint8 +   __gap: uint256[50] + +Internal: +    __ERC20Module_init(name_: string, symbol_: string, decimals_: uint8) <<onlyInitializing>> +    __ERC20Module_init_unchained(decimals_: uint8) <<onlyInitializing>> +Public: +    <<event>> Spend(owner: address, spender: address, value: uint256) +    decimals(): uint8 +    transferBatch(tos: address[], values: uint256[]): bool +    transferFrom(from: address, to: address, value: uint256): bool +    approve(spender: address, value: uint256, currentAllowance: uint256): bool diff --git a/doc/modules/schema/sol2uml/mandatory/MintModule.svg b/doc/modules/schema/sol2uml/mandatory/MintModule.svg index ab3444ef..1deb5ab8 100644 --- a/doc/modules/schema/sol2uml/mandatory/MintModule.svg +++ b/doc/modules/schema/sol2uml/mandatory/MintModule.svg @@ -4,69 +4,70 @@ - - + + UmlClassDiagram - + cluster_0 - -contracts/modules/security + +contracts/modules/security cluster_1 - + contracts/modules/wrapper/mandatory - + -19 - -<<Abstract>> -AuthorizationModule -contracts/modules/security/AuthorizationModule.sol - -Private: -   __gap: uint256[50] -Public: -   BURNER_ROLE: bytes32 -   ENFORCER_ROLE: bytes32 -   MINTER_ROLE: bytes32 -   PAUSER_ROLE: bytes32 -   SNAPSHOOTER_ROLE: bytes32 -   DEBT_ROLE: bytes32 -   DEBT_CREDIT_EVENT_ROLE: bytes32 - -Internal: -    __AuthorizationModule_init(admin: address) <<onlyInitializing>> -    __AuthorizationModule_init_unchained(admin: address) <<onlyInitializing>> -Public: -    hasRole(role: bytes32, account: address): bool +17 + +<<Abstract>> +AuthorizationModule +contracts/modules/security/AuthorizationModule.sol + +Private: +   __gap: uint256[50] +Public: +   BURNER_ROLE: bytes32 +   ENFORCER_ROLE: bytes32 +   MINTER_ROLE: bytes32 +   PAUSER_ROLE: bytes32 +   SNAPSHOOTER_ROLE: bytes32 +   DEBT_ROLE: bytes32 +   DEBT_CREDIT_EVENT_ROLE: bytes32 + +Internal: +    __AuthorizationModule_init(admin: address) <<onlyInitializing>> +    __AuthorizationModule_init_unchained(admin: address) <<onlyInitializing>> +Public: +    hasRole(role: bytes32, account: address): bool - + -27 - -<<Abstract>> -MintModule -contracts/modules/wrapper/mandatory/MintModule.sol - -Private: -   __gap: uint256[50] - -Internal: -    __MintModule_init(name_: string, symbol_: string, admin: address) <<onlyInitializing>> -    __MintModule_init_unchained() <<onlyInitializing>> -Public: -    <<event>> Mint(beneficiary: address, amount: uint256) -    mint(to: address, amount: uint256) <<onlyRole>> +30 + +<<Abstract>> +MintModule +contracts/modules/wrapper/mandatory/MintModule.sol + +Private: +   __gap: uint256[50] + +Internal: +    __MintModule_init(name_: string, symbol_: string, admin: address) <<onlyInitializing>> +    __MintModule_init_unchained() <<onlyInitializing>> +Public: +    <<event>> Mint(account: address, value: uint256) +    mint(account: address, value: uint256) <<onlyRole>> +    mintBatch(accounts: address[], values: uint256[]) <<onlyRole>> - + -27->19 - - +30->17 + + diff --git a/doc/modules/schema/surya_graph/surya_graph_BurnModule.sol.png b/doc/modules/schema/surya_graph/surya_graph_BurnModule.sol.png index 7b621eb5..2c44984c 100644 Binary files a/doc/modules/schema/surya_graph/surya_graph_BurnModule.sol.png and b/doc/modules/schema/surya_graph/surya_graph_BurnModule.sol.png differ diff --git a/doc/modules/schema/surya_graph/surya_graph_ERC20BaseModule.sol.png b/doc/modules/schema/surya_graph/surya_graph_ERC20BaseModule.sol.png index 63f732c1..dfd36bb1 100644 Binary files a/doc/modules/schema/surya_graph/surya_graph_ERC20BaseModule.sol.png and b/doc/modules/schema/surya_graph/surya_graph_ERC20BaseModule.sol.png differ diff --git a/doc/modules/schema/surya_graph/surya_graph_MintModule.sol.png b/doc/modules/schema/surya_graph/surya_graph_MintModule.sol.png index abe2b073..ab81b30a 100644 Binary files a/doc/modules/schema/surya_graph/surya_graph_MintModule.sol.png and b/doc/modules/schema/surya_graph/surya_graph_MintModule.sol.png differ diff --git a/migrations/1_deploy_contracts.js b/migrations/1_deploy_contracts.js index a224ddbe..d69a0648 100644 --- a/migrations/1_deploy_contracts.js +++ b/migrations/1_deploy_contracts.js @@ -14,6 +14,7 @@ module.exports = async function (deployer, _network, account) { admin, "Test CMTA Token", "TCMTAT", + 0, "TCMTAT_ISIN", "https://cmta.ch", ZERO_ADDRESS, diff --git a/package.json b/package.json index ce755b58..1073b97b 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,11 @@ "lint:js:fix": "npx eslint test --fix", "lint:sol": "npx solium -d contracts", "lint:sol:fix": "npx solium -d contracts --fix", - "lint:all": "npx run lint && npm run lint:sol", - "lint:all:fix": "npx run lint:fix && npm run lint:sol:fix", + "lint:all": "npx run lint && npx run lint:sol", + "lint:all:fix": "npm run-script lint:js:fix && npm run-script lint:sol:fix", "lint:sol:prettier": "npx prettier --write 'contracts/**/*.sol'", "lint:js:prettier": "npx prettier test", + "lint:all:prettier": "npm run-script lint:js:prettier && npm run-script lint:sol:prettier", "console": "truffle console", "coverage": "npx hardhat coverage", "docgen": "npx hardhat docgen", diff --git a/test/common/BurnModuleCommon.js b/test/common/BurnModuleCommon.js index d3c235e8..4a36dc74 100644 --- a/test/common/BurnModuleCommon.js +++ b/test/common/BurnModuleCommon.js @@ -1,19 +1,23 @@ -const { expectEvent, expectRevert } = require('@openzeppelin/test-helpers') +const { BN, expectEvent, expectRevert } = require('@openzeppelin/test-helpers') const { BURNER_ROLE, ZERO_ADDRESS } = require('../utils') const { should } = require('chai').should() function BurnModuleCommon (admin, address1, address2) { context('Burn', function () { + const INITIAL_SUPPLY = new BN(50) + const REASON = 'BURN_TEST' + const VALUE1 = new BN(20) + const DIFFERENCE = INITIAL_SUPPLY.sub(VALUE1) + beforeEach(async function () { - await this.cmtat.mint(address1, 50, { from: admin }); - (await this.cmtat.totalSupply()).should.be.bignumber.equal('50') + await this.cmtat.mint(address1, INITIAL_SUPPLY, { from: admin }); + (await this.cmtat.totalSupply()).should.be.bignumber.equal(INITIAL_SUPPLY) }) - it('testCanBeBurntByAdminWithAllowance', async function () { - const reason = 'BURN_TEST'; + it('testCanBeBurntByAdmin', async function () { // Act // Burn 20 - ({ logs: this.logs1 } = await this.cmtat.forceBurn(address1, 20, reason, { + ({ logs: this.logs1 } = await this.cmtat.forceBurn(address1, VALUE1, REASON, { from: admin })) // Assert @@ -21,21 +25,21 @@ function BurnModuleCommon (admin, address1, address2) { expectEvent.inLogs(this.logs1, 'Transfer', { from: address1, to: ZERO_ADDRESS, - value: '20' + value: VALUE1 }) // Emits a Burn event expectEvent.inLogs(this.logs1, 'Burn', { owner: address1, - amount: '20', - reason + value: VALUE1, + reason: REASON }); // Check balances and total supply - (await this.cmtat.balanceOf(address1)).should.be.bignumber.equal('30'); - (await this.cmtat.totalSupply()).should.be.bignumber.equal('30'); + (await this.cmtat.balanceOf(address1)).should.be.bignumber.equal(DIFFERENCE); + (await this.cmtat.totalSupply()).should.be.bignumber.equal(DIFFERENCE); // Burn 30 // Act - ({ logs: this.logs2 } = await this.cmtat.forceBurn(address1, 30, reason, { + ({ logs: this.logs2 } = await this.cmtat.forceBurn(address1, DIFFERENCE, REASON, { from: admin })) // Assert @@ -43,40 +47,39 @@ function BurnModuleCommon (admin, address1, address2) { expectEvent.inLogs(this.logs2, 'Transfer', { from: address1, to: ZERO_ADDRESS, - value: '30' + value: DIFFERENCE }) // Emits a Burn event expectEvent.inLogs(this.logs2, 'Burn', { owner: address1, - amount: '30', - reason + value: DIFFERENCE, + reason: REASON }); // Check balances and total supply - (await this.cmtat.balanceOf(address1)).should.be.bignumber.equal('0'); - (await this.cmtat.totalSupply()).should.be.bignumber.equal('0') + (await this.cmtat.balanceOf(address1)).should.be.bignumber.equal(BN(0)); + (await this.cmtat.totalSupply()).should.be.bignumber.equal(BN(0)) }) it('testCanBeBurntByBurnerRole', async function () { - const reason = 'BURN_TEST' // Arrange await this.cmtat.grantRole(BURNER_ROLE, address2, { from: admin }); // Act - ({ logs: this.logs } = await this.cmtat.forceBurn(address1, 20, reason, { from: address2 })); + ({ logs: this.logs } = await this.cmtat.forceBurn(address1, VALUE1, REASON, { from: address2 })); // Assert - (await this.cmtat.balanceOf(address1)).should.be.bignumber.equal('30'); - (await this.cmtat.totalSupply()).should.be.bignumber.equal('30') + (await this.cmtat.balanceOf(address1)).should.be.bignumber.equal(DIFFERENCE); + (await this.cmtat.totalSupply()).should.be.bignumber.equal(DIFFERENCE) // Emits a Transfer event expectEvent.inLogs(this.logs, 'Transfer', { from: address1, to: ZERO_ADDRESS, - value: '20' + value: VALUE1 }) // Emits a Burn event expectEvent.inLogs(this.logs, 'Burn', { owner: address1, - amount: '20', - reason + value: VALUE1, + reason: REASON }) }) @@ -99,5 +102,135 @@ function BurnModuleCommon (admin, address1, address2) { ) }) }) + context('BurnBatch', function () { + const REASON = 'BURN_TEST' + const TOKEN_HOLDER = [admin, address1, address2] + const TOKEN_SUPPLY_BY_HOLDERS = [BN(10), BN(100), BN(1000)] + const INITIAL_SUPPLY = TOKEN_SUPPLY_BY_HOLDERS.reduce((a, b) => { return a.add(b) }) + const TOKEN_BY_HOLDERS_TO_BURN = [BN(5), BN(50), BN(500)] + const TOKEN_BALANCE_BY_HOLDERS_AFTER_BURN = [ + TOKEN_SUPPLY_BY_HOLDERS[0].sub(TOKEN_BY_HOLDERS_TO_BURN[0]), + TOKEN_SUPPLY_BY_HOLDERS[1].sub(TOKEN_BY_HOLDERS_TO_BURN[1]), + TOKEN_SUPPLY_BY_HOLDERS[2].sub(TOKEN_BY_HOLDERS_TO_BURN[2])] + const TOTAL_SUPPLY_AFTER_BURN = INITIAL_SUPPLY.sub(TOKEN_BY_HOLDERS_TO_BURN.reduce((a, b) => { return a.add(b) })) + + beforeEach(async function () { + // await this.cmtat.mint(address1, INITIAL_SUPPLY, { from: admin }); + ({ logs: this.logs1 } = await this.cmtat.mintBatch(TOKEN_HOLDER, TOKEN_SUPPLY_BY_HOLDERS, { + from: admin + })); + (await this.cmtat.totalSupply()).should.be.bignumber.equal(INITIAL_SUPPLY) + }) + + it('testCanBeBurntBatchByAdmin', async function () { + // Act + // Burn + ({ logs: this.logs1 } = await this.cmtat.forceBurnBatch(TOKEN_HOLDER, TOKEN_BY_HOLDERS_TO_BURN, REASON, { + from: admin + })) + // Assert + // emits a Transfer event + // Assert event + // emits a Transfer event + for (let i = 0; i < TOKEN_HOLDER.length; ++i) { + // emits a Mint event + expectEvent.inLogs(this.logs1, 'Transfer', { + from: TOKEN_HOLDER[i], + to: ZERO_ADDRESS, + value: TOKEN_BY_HOLDERS_TO_BURN[i] + }) + } + + for (let i = 0; i < TOKEN_HOLDER.length; ++i) { + // emits a Mint event + expectEvent.inLogs(this.logs1, 'Burn', { + owner: TOKEN_HOLDER[i], + value: TOKEN_BY_HOLDERS_TO_BURN[i], + reason: REASON + }) + } + // Check balances and total supply + // Assert + for (let i = 0; i < TOKEN_HOLDER.length; ++i) { + (await this.cmtat.balanceOf(TOKEN_HOLDER[i])).should.be.bignumber.equal(TOKEN_BALANCE_BY_HOLDERS_AFTER_BURN[i]) + } + + (await this.cmtat.totalSupply()).should.be.bignumber.equal(TOTAL_SUPPLY_AFTER_BURN) + }) + + it('testCanBeBurntBatchByBurnerRole', async function () { + // Arrange + await this.cmtat.grantRole(BURNER_ROLE, address2, { from: admin }); + + // Act + // Burn + ({ logs: this.logs1 } = await this.cmtat.forceBurnBatch(TOKEN_HOLDER, TOKEN_BY_HOLDERS_TO_BURN, REASON, { + from: address2 + })) + // Assert + // emits a Transfer event + // Assert event + // emits a Transfer event + for (let i = 0; i < TOKEN_HOLDER.length; ++i) { + // emits a Mint event + expectEvent.inLogs(this.logs1, 'Transfer', { + from: TOKEN_HOLDER[i], + to: ZERO_ADDRESS, + value: TOKEN_BY_HOLDERS_TO_BURN[i] + }) + } + + for (let i = 0; i < TOKEN_HOLDER.length; ++i) { + // emits a Mint event + expectEvent.inLogs(this.logs1, 'Burn', { + owner: TOKEN_HOLDER[i], + value: TOKEN_BY_HOLDERS_TO_BURN[i] + }) + } + // Check balances and total supply + // Assert + for (let i = 0; i < TOKEN_HOLDER.length; ++i) { + (await this.cmtat.balanceOf(TOKEN_HOLDER[i])).should.be.bignumber.equal(TOKEN_BALANCE_BY_HOLDERS_AFTER_BURN[i]) + } + + (await this.cmtat.totalSupply()).should.be.bignumber.equal(TOTAL_SUPPLY_AFTER_BURN) + }) + + it('testCannotBeBurntIfOneBalanceExceeds', async function () { + const TOKEN_BY_HOLDERS_TO_BURN_FAIL = [BN(5), BN(50), BN(5000000)] + // Act + await expectRevert( + this.cmtat.forceBurnBatch(TOKEN_HOLDER, TOKEN_BY_HOLDERS_TO_BURN_FAIL, '', { from: admin }), + 'ERC20: burn amount exceeds balance' + ) + }) + + it('testCannotBeBurntWithoutBurnerRole', async function () { + // Act + await expectRevert( + this.cmtat.forceBurnBatch(TOKEN_HOLDER, TOKEN_BY_HOLDERS_TO_BURN, '', { from: address2 }), + 'AccessControl: account ' + + address2.toLowerCase() + + ' is missing role ' + + BURNER_ROLE + ) + }) + + it('testCannotBurnIfLengthMismatch', async function () { + const TOKEN_HOLDER_INVALID = [admin, address1] + await expectRevert( + this.cmtat.forceBurnBatch(TOKEN_HOLDER_INVALID, TOKEN_BY_HOLDERS_TO_BURN, REASON, { from: admin }), + 'CMTAT: accounts and values length mismatch' + ) + }) + + it('testCannotBurnBatchIfAccountsIsEmpty', async function () { + const TOKEN_ADDRESS_TOS_INVALID = [] + await expectRevert( + this.cmtat.forceBurnBatch(TOKEN_ADDRESS_TOS_INVALID, TOKEN_BY_HOLDERS_TO_BURN, REASON, { from: admin }), + 'CMTAT: accounts is empty' + ) + }) + }) } module.exports = BurnModuleCommon diff --git a/test/common/ERC20BaseModuleCommon.js b/test/common/ERC20BaseModuleCommon.js index 275f086d..ecb7fda7 100644 --- a/test/common/ERC20BaseModuleCommon.js +++ b/test/common/ERC20BaseModuleCommon.js @@ -1,8 +1,8 @@ -const { expectEvent, expectRevert } = require('@openzeppelin/test-helpers') +const { BN, expectEvent, expectRevert } = require('@openzeppelin/test-helpers') const { DEFAULT_ADMIN_ROLE } = require('../utils') const { should } = require('chai').should() -function BaseModuleCommon (owner, address1, address2, address3, proxyTest) { +function BaseModuleCommon (admin, address1, address2, address3, proxyTest) { context('Token structure', function () { it('testHasTheDefinedName', async function () { // Act + Assert @@ -176,9 +176,9 @@ function BaseModuleCommon (owner, address1, address2, address3, proxyTest) { context('Transfer', function () { beforeEach(async function () { - await this.cmtat.mint(address1, 31, { from: owner }) - await this.cmtat.mint(address2, 32, { from: owner }) - await this.cmtat.mint(address3, 33, { from: owner }) + await this.cmtat.mint(address1, 31, { from: admin }) + await this.cmtat.mint(address2, 32, { from: admin }) + await this.cmtat.mint(address3, 33, { from: admin }) }) it('testTransferFromOneAccountToAnother', async function () { @@ -237,7 +237,7 @@ function BaseModuleCommon (owner, address1, address2, address3, proxyTest) { expectEvent.inLogs(this.logs, 'Spend', { owner: address1, spender: address3, - amount: '11' + value: '11' }) }) @@ -272,5 +272,96 @@ function BaseModuleCommon (owner, address1, address2, address3, proxyTest) { ) }) }) + + context('transferFrom', function () { + beforeEach(async function () { + await this.cmtat.mint(address1, 31, { from: admin }) + await this.cmtat.mint(address2, 32, { from: admin }) + await this.cmtat.mint(address3, 33, { from: admin }) + }) + + it('testTransferFromOneAccountToAnother', async function () { + // Act + ({ logs: this.logs } = await this.cmtat.transfer(address2, 11, { + from: address1 + })); + // Assert + (await this.cmtat.balanceOf(address1)).should.be.bignumber.equal('20'); + (await this.cmtat.balanceOf(address2)).should.be.bignumber.equal('43'); + (await this.cmtat.balanceOf(address3)).should.be.bignumber.equal('33'); + (await this.cmtat.totalSupply()).should.be.bignumber.equal('96') + // emits a Transfer event + expectEvent.inLogs(this.logs, 'Transfer', { + from: address1, + to: address2, + value: '11' + }) + }) + + // ADDRESS1 -> ADDRESS2 + it('testCannotTransferMoreTokensThanOwn', async function () { + // Act + await expectRevert( + this.cmtat.transfer(address2, 50, { from: address1 }), + 'ERC20: transfer amount exceeds balance' + ) + }) + }) + + context('transferBatch', function () { + const TOKEN_ADDRESS_TOS = [address1, address2, address3] + const TOKEN_AMOUNTS = [BN(10), BN(100), BN(1000)] + + beforeEach(async function () { + await this.cmtat.mint(admin, TOKEN_AMOUNTS.reduce((a, b) => { return a.add(b) }), { from: admin }) + }) + + it('testTransferBatch', async function () { + // Act + ({ logs: this.logs } = await this.cmtat.transferBatch(TOKEN_ADDRESS_TOS, TOKEN_AMOUNTS, { + from: admin + })); + // Assert + for (let i = 0; i < TOKEN_ADDRESS_TOS.length; ++i) { + (await this.cmtat.balanceOf(TOKEN_ADDRESS_TOS[i])).should.be.bignumber.equal(TOKEN_AMOUNTS[i]) + } + // emits a Transfer event + for (let i = 0; i < TOKEN_ADDRESS_TOS.length; ++i) { + expectEvent.inLogs(this.logs, 'Transfer', { + from: admin, + to: TOKEN_ADDRESS_TOS[i], + value: TOKEN_AMOUNTS[i] + }) + } + }) + + // ADDRESS1 -> ADDRESS2 + it('testCannotTransferBatchMoreTokensThanOwn', async function () { + const TOKEN_AMOUNTS_INVALID = [TOKEN_AMOUNTS[0], TOKEN_AMOUNTS[1].add(BN(1)), TOKEN_AMOUNTS[2]] + // Act + await expectRevert( + this.cmtat.transferBatch(TOKEN_ADDRESS_TOS, TOKEN_AMOUNTS_INVALID, { + from: admin + }), + 'ERC20: transfer amount exceeds balance' + ) + }) + + it('testCannotTransferBatchIfLengthMismatch', async function () { + const TOKEN_ADDRESS_TOS_INVALID = [address1, address2] + await expectRevert( + this.cmtat.transferBatch(TOKEN_ADDRESS_TOS_INVALID, TOKEN_AMOUNTS, { from: admin }), + 'CMTAT: tos and values length mismatch' + ) + }) + + it('testCannotTransferBatchIfTOSIsEmpty', async function () { + const TOKEN_ADDRESS_TOS_INVALID = [] + await expectRevert( + this.cmtat.transferBatch(TOKEN_ADDRESS_TOS_INVALID, TOKEN_AMOUNTS, { from: admin }), + 'CMTAT: tos is empty' + ) + }) + }) } module.exports = BaseModuleCommon diff --git a/test/common/MintModuleCommon.js b/test/common/MintModuleCommon.js index 47f915b0..61bd19ca 100644 --- a/test/common/MintModuleCommon.js +++ b/test/common/MintModuleCommon.js @@ -1,86 +1,103 @@ -const { expectEvent, expectRevert } = require('@openzeppelin/test-helpers') +const { BN, expectEvent, expectRevert } = require('@openzeppelin/test-helpers') const { ZERO_ADDRESS, MINTER_ROLE } = require('../utils') const { should } = require('chai').should() function MintModuleCommon (admin, address1, address2) { context('Minting', function () { + const VALUE1 = new BN(20) + const VALUE2 = new BN(50) /** The admin is assigned the MINTER role when the contract is deployed */ it('testCanBeMintedByAdmin', async function () { + // Arrange + // Arrange - Assert // Check first balance - (await this.cmtat.balanceOf(admin)).should.be.bignumber.equal('0'); + (await this.cmtat.balanceOf(admin)).should.be.bignumber.equal(BN(0)); // Act // Issue 20 and check balances and total supply - ({ logs: this.logs1 } = await this.cmtat.mint(address1, 20, { + ({ logs: this.logs1 } = await this.cmtat.mint(address1, VALUE1, { from: admin })); // Assert - (await this.cmtat.balanceOf(address1)).should.be.bignumber.equal('20'); - (await this.cmtat.totalSupply()).should.be.bignumber.equal('20'); + (await this.cmtat.balanceOf(address1)).should.be.bignumber.equal(VALUE1); + (await this.cmtat.totalSupply()).should.be.bignumber.equal(VALUE1) + + // Assert event + // emits a Transfer event + expectEvent.inLogs(this.logs1, 'Transfer', { + from: ZERO_ADDRESS, + to: address1, + value: VALUE1 + }) + // emits a Mint event + expectEvent.inLogs(this.logs1, 'Mint', { + account: address1, + value: VALUE1 + }); // Act // Issue 50 and check intermediate balances and total supply - ({ logs: this.logs2 } = await this.cmtat.mint(address2, 50, { + ({ logs: this.logs2 } = await this.cmtat.mint(address2, VALUE2, { from: admin })); // Assert - (await this.cmtat.balanceOf(address2)).should.be.bignumber.equal('50'); - (await this.cmtat.totalSupply()).should.be.bignumber.equal('70') + (await this.cmtat.balanceOf(address2)).should.be.bignumber.equal(VALUE2); + (await this.cmtat.totalSupply()).should.be.bignumber.equal(VALUE1.add(VALUE2)) // Assert event // emits a Transfer event expectEvent.inLogs(this.logs2, 'Transfer', { from: ZERO_ADDRESS, to: address2, - value: '50' + value: VALUE2 }) // emits a Mint event expectEvent.inLogs(this.logs2, 'Mint', { - beneficiary: address2, - amount: '50' + account: address2, + value: VALUE2 }) }) - it('testCanBeMintedByANewMinter', async function () { + it('testCanMintByANewMinter', async function () { // Arrange await this.cmtat.grantRole(MINTER_ROLE, address1, { from: admin }); // Arrange - Assert // Check first balance - (await this.cmtat.balanceOf(admin)).should.be.bignumber.equal('0'); + (await this.cmtat.balanceOf(admin)).should.be.bignumber.equal(BN(0)); // Act // Issue 20 - ({ logs: this.logs1 } = await this.cmtat.mint(address1, 20, { + ({ logs: this.logs1 } = await this.cmtat.mint(address1, VALUE1, { from: address1 })); // Assert // Check balances and total supply - (await this.cmtat.balanceOf(address1)).should.be.bignumber.equal('20'); - (await this.cmtat.totalSupply()).should.be.bignumber.equal('20') + (await this.cmtat.balanceOf(address1)).should.be.bignumber.equal(VALUE1); + (await this.cmtat.totalSupply()).should.be.bignumber.equal(VALUE1) // Assert event // emits a Transfer event expectEvent.inLogs(this.logs1, 'Transfer', { from: ZERO_ADDRESS, to: address1, - value: '20' + value: VALUE1 }) // emits a Mint event expectEvent.inLogs(this.logs1, 'Mint', { - beneficiary: address1, - amount: '20' + account: address1, + value: VALUE1 }) }) // reverts when issuing by a non minter - it('testCannotIssuingByNonMinter', async function () { + it('testCannotMintByNonMinter', async function () { await expectRevert( - this.cmtat.mint(address1, 20, { from: address1 }), + this.cmtat.mint(address1, VALUE1, { from: address1 }), 'AccessControl: account ' + address1.toLowerCase() + ' is missing role ' + @@ -88,5 +105,127 @@ function MintModuleCommon (admin, address1, address2) { ) }) }) + + context('Batch Minting', function () { + const TOKEN_HOLDER = [admin, address1, address2] + const TOKEN_SUPPLY_BY_HOLDERS = [BN(10), BN(100), BN(1000)] + + /** + The admin is assigned the MINTER role when the contract is deployed + */ + it('testCanBeMintedBatchByAdmin', async function () { + // Arrange - Assert + // Check first balance + for (let i = 0; i < TOKEN_HOLDER.length; ++i) { + (await this.cmtat.balanceOf(TOKEN_HOLDER[i])).should.be.bignumber.equal(BN(0)) + } + + // Act + // Issue 20 and check balances and total supply + ({ logs: this.logs1 } = await this.cmtat.mintBatch(TOKEN_HOLDER, TOKEN_SUPPLY_BY_HOLDERS, { + from: admin + })) + + // Assert + for (let i = 0; i < TOKEN_HOLDER.length; ++i) { + (await this.cmtat.balanceOf(TOKEN_HOLDER[i])).should.be.bignumber.equal(TOKEN_SUPPLY_BY_HOLDERS[i]) + } + + (await this.cmtat.totalSupply()).should.be.bignumber.equal(TOKEN_SUPPLY_BY_HOLDERS.reduce((a, b) => { return a.add(b) })) + + // Assert event + // emits a Transfer event + for (let i = 0; i < TOKEN_HOLDER.length; ++i) { + // emits a Mint event + expectEvent.inLogs(this.logs1, 'Transfer', { + from: ZERO_ADDRESS, + to: TOKEN_HOLDER[i], + value: TOKEN_SUPPLY_BY_HOLDERS[i] + }) + } + + for (let i = 0; i < TOKEN_HOLDER.length; ++i) { + // emits a Mint event + expectEvent.inLogs(this.logs1, 'Mint', { + account: TOKEN_HOLDER[i], + value: TOKEN_SUPPLY_BY_HOLDERS[i] + }) + } + }) + + it('testCanBeMinteBatchdByANewMinter', async function () { + // Arrange + await this.cmtat.grantRole(MINTER_ROLE, address1, { from: admin }) + const TOKEN_HOLDER = [admin, address1, address2] + const TOKEN_SUPPLY_BY_HOLDERS = [BN(10), BN(100), BN(1000)] + + // Arrange - Assert + // Check first balance + for (let i = 0; i < TOKEN_HOLDER.length; ++i) { + (await this.cmtat.balanceOf(TOKEN_HOLDER[i])).should.be.bignumber.equal(BN(0)) + } + + // Act + // Issue 20 and check balances and total supply + ({ logs: this.logs1 } = await this.cmtat.mintBatch(TOKEN_HOLDER, TOKEN_SUPPLY_BY_HOLDERS, { + from: address1 + })) + + // Assert + for (let i = 0; i < TOKEN_HOLDER.length; ++i) { + (await this.cmtat.balanceOf(TOKEN_HOLDER[i])).should.be.bignumber.equal(TOKEN_SUPPLY_BY_HOLDERS[i]) + } + + (await this.cmtat.totalSupply()).should.be.bignumber.equal(TOKEN_SUPPLY_BY_HOLDERS.reduce((a, b) => { return a.add(b) })) + + // Assert event + // emits a Transfer event + for (let i = 0; i < TOKEN_HOLDER.length; ++i) { + expectEvent.inLogs(this.logs1, 'Transfer', { + from: ZERO_ADDRESS, + to: TOKEN_HOLDER[i], + value: TOKEN_SUPPLY_BY_HOLDERS[i] + }) + } + + // emits a Mint event + for (let i = 0; i < TOKEN_HOLDER.length; ++i) { + expectEvent.inLogs(this.logs1, 'Mint', { + account: TOKEN_HOLDER[i], + value: TOKEN_SUPPLY_BY_HOLDERS[i] + }) + } + }) + + it('testCannotMintBatchByNonMinter', async function () { + const TOKEN_HOLDER = [admin, address1, address2] + const TOKEN_SUPPLY_BY_HOLDERS = [BN(10), BN(100), BN(1000)] + await expectRevert( + this.cmtat.mintBatch(TOKEN_HOLDER, TOKEN_SUPPLY_BY_HOLDERS, { from: address1 }), + 'AccessControl: account ' + + address1.toLowerCase() + + ' is missing role ' + + MINTER_ROLE + ) + }) + + it('testCannotMintBatchIfLengthMismatch', async function () { + const TOKEN_HOLDER_INVALID = [admin, address1] + const TOKEN_SUPPLY_BY_HOLDERS = [BN(10), BN(100), BN(1000)] + await expectRevert( + this.cmtat.mintBatch(TOKEN_HOLDER_INVALID, TOKEN_SUPPLY_BY_HOLDERS, { from: admin }), + 'CMTAT: accounts and values length mismatch' + ) + }) + + it('testCannotMintBatchIfTOSIsEmpty', async function () { + const TOKEN_HOLDER_INVALID = [] + const TOKEN_SUPPLY_BY_HOLDERS = [] + await expectRevert( + this.cmtat.mintBatch(TOKEN_HOLDER_INVALID, TOKEN_SUPPLY_BY_HOLDERS, { from: admin }), + 'CMTAT: accounts is empty' + ) + }) + }) } module.exports = MintModuleCommon diff --git a/test/common/SnapshotModuleCommon/SnapshotModuleUtils/SnapshotModuleUtils.js b/test/common/SnapshotModuleCommon/SnapshotModuleUtils/SnapshotModuleUtils.js index 844f1b4f..c2a74fd8 100644 --- a/test/common/SnapshotModuleCommon/SnapshotModuleUtils/SnapshotModuleUtils.js +++ b/test/common/SnapshotModuleCommon/SnapshotModuleUtils/SnapshotModuleUtils.js @@ -1,4 +1,3 @@ - const getUnixTimestamp = () => { return Math.round(new Date().getTime() / 1000) } diff --git a/test/deployment/deployment.test.js b/test/deployment/deployment.test.js index 8f5ef1bc..562c5105 100644 --- a/test/deployment/deployment.test.js +++ b/test/deployment/deployment.test.js @@ -8,18 +8,18 @@ contract( function ([_], admin) { it('testCannotDeployProxyWithAdminSetToAddressZero', async function () { this.flag = 5 - + const DECIMAL = 0 // Act + Assert - await expectRevert.unspecified(deployProxy(CMTAT_PROXY, [ZERO_ADDRESS, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { + await expectRevert.unspecified(deployProxy(CMTAT_PROXY, [ZERO_ADDRESS, 'CMTA Token', 'CMTAT', DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { initializer: 'initialize', constructorArgs: [_] })) }) it('testCannotDeployStandaloneWithAdminSetToAddressZero', async function () { this.flag = 5 - + const DECIMAL = 0 // Act + Assert - await expectRevert.unspecified(CMTAT_STANDALONE.new(_, ZERO_ADDRESS, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: admin })) + await expectRevert.unspecified(CMTAT_STANDALONE.new(_, ZERO_ADDRESS, 'CMTA Token', 'CMTAT', DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: admin })) }) } ) diff --git a/test/deploymentUtils.js b/test/deploymentUtils.js new file mode 100644 index 00000000..4bd899ba --- /dev/null +++ b/test/deploymentUtils.js @@ -0,0 +1,23 @@ +const { ZERO_ADDRESS } = require('./utils') +const CMTAT_STANDALONE = artifacts.require('CMTAT_STANDALONE') +const CMTAT_PROXY = artifacts.require('CMTAT_PROXY') +const { deployProxy } = require('@openzeppelin/truffle-upgrades') +const DEPLOYMENT_FLAG = 5 +const DEPLOYMENT_DECIMAL = 0 + +async function deployCMTATStandalone (_, admin, deployerAddress) { + const cmtat = await CMTAT_STANDALONE.new(_, admin, 'CMTA Token', 'CMTAT', DEPLOYMENT_DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', DEPLOYMENT_FLAG, { from: deployerAddress }) + return cmtat +} + +async function deployCMTATProxy (_, admin, deployerAddress) { + + const cmtat = await deployProxy(CMTAT_PROXY, [admin, 'CMTA Token', 'CMTAT', DEPLOYMENT_DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', DEPLOYMENT_FLAG], { + initializer: 'initialize', + constructorArgs: [_], + from: deployerAddress + }) + return cmtat +} + +module.exports = { deployCMTATStandalone, deployCMTATProxy, DEPLOYMENT_FLAG, DEPLOYMENT_DECIMAL } diff --git a/test/proxy/general/KillImplementation.test.js b/test/proxy/general/KillImplementation.test.js index cbfa5e53..e96a8435 100644 --- a/test/proxy/general/KillImplementation.test.js +++ b/test/proxy/general/KillImplementation.test.js @@ -5,6 +5,7 @@ */ const { expectEvent, expectRevert } = require('@openzeppelin/test-helpers') const { should } = require('chai').should() +const DECIMAL = 0 const { ZERO_ADDRESS } = require('../../utils') const { deployProxy, @@ -16,9 +17,10 @@ const CMTAT_KILL_TEST = artifacts.require('CMTAT_KILL_TEST') contract('Proxy - Security Test', function ([_, admin]) { beforeEach(async function () { this.flag = 5 + // Contract to deploy: CMTAT_KILL_TEST this.CMTAT_PROXY = await deployProxy( CMTAT_KILL_TEST, - [admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], + [admin, 'CMTA Token', 'CMTAT', DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { initializer: 'initialize', constructorArgs: [ diff --git a/test/proxy/general/Proxy.test.js b/test/proxy/general/Proxy.test.js index f337f453..d8ea00c2 100644 --- a/test/proxy/general/Proxy.test.js +++ b/test/proxy/general/Proxy.test.js @@ -2,19 +2,19 @@ const { expectEvent, expectRevert } = require('@openzeppelin/test-helpers') const { should } = require('chai').should() const { deployProxy, upgradeProxy, erc1967 } = require('@openzeppelin/truffle-upgrades') -const CMTAT1 = artifacts.require('CMTAT_PROXY') -const { DEFAULT_ADMIN_ROLE } = require('../../utils') const CMTAT = artifacts.require('CMTAT_PROXY') +const { DEFAULT_ADMIN_ROLE } = require('../../utils') const { ZERO_ADDRESS } = require('../../utils') +const DECIMAL = 0 +const { deployCMTATProxy, DEPLOYMENT_FLAG } = require('../../deploymentUtils') + contract( 'Proxy - Security Test', - function ([_, admin, attacker]) { + function ([_, admin, attacker, deployerAddress]) { beforeEach(async function () { this.flag = 5 - this.CMTAT_PROXY = await deployProxy(CMTAT1, [admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { - initializer: 'initialize', - constructorArgs: [_] - }) + // Contract to deploy: CMTAT + this.CMTAT_PROXY = await deployCMTATProxy(_, admin, deployerAddress) const implementationContractAddress = await erc1967.getImplementationAddress(this.CMTAT_PROXY.address, { from: admin }) this.implementationContract = await CMTAT.at(implementationContractAddress) }) @@ -23,7 +23,7 @@ contract( // Here the argument to indicate if it is deployed with a proxy, set at false by the attacker it('testCannotBeTakenControlByAttacker1', async function () { await expectRevert( - this.implementationContract.initialize(attacker, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: attacker }), + this.implementationContract.initialize(attacker, 'CMTA Token', 'CMTAT', DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', DEPLOYMENT_FLAG, { from: attacker }), 'Initializable: contract is already initialized' ) await expectRevert( @@ -37,7 +37,7 @@ contract( // Here the argument to indicate if it is deployed with a proxy, set at true by the attacker it('testCannotBeTakenControlByAttacker2', async function () { await expectRevert( - this.implementationContract.initialize(attacker, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: attacker }), + this.implementationContract.initialize(attacker, 'CMTA Token', 'CMTAT', DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', DEPLOYMENT_FLAG, { from: attacker }), 'Initializable: contract is already initialized' ) await expectRevert( diff --git a/test/proxy/general/UpgradeProxy.test.js b/test/proxy/general/UpgradeProxy.test.js index 349ec71c..b800020e 100644 --- a/test/proxy/general/UpgradeProxy.test.js +++ b/test/proxy/general/UpgradeProxy.test.js @@ -5,6 +5,7 @@ const { deployProxy, upgradeProxy, erc1967 } = require('@openzeppelin/truffle-up const CMTAT1 = artifacts.require('CMTAT_PROXY') const CMTAT2 = artifacts.require('CMTAT_PROXY') const { ZERO_ADDRESS } = require('../../utils') +const DECIMAL = 0 contract('UpgradeableCMTAT - Proxy', function ([_, admin, address1]) { /* @@ -13,7 +14,7 @@ contract('UpgradeableCMTAT - Proxy', function ([_, admin, address1]) { it('testKeepStorageForTokens', async function () { this.flag = 5 // With the first version of CMTAT - this.CMTAT_PROXY = await deployProxy(CMTAT1, [admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { + this.CMTAT_PROXY = await deployProxy(CMTAT1, [admin, 'CMTA Token', 'CMTAT', DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { initializer: 'initialize', constructorArgs: [_] }) diff --git a/test/proxy/modules/AuthorizationModule/AuthorizationModule.test.js b/test/proxy/modules/AuthorizationModule/AuthorizationModule.test.js index c99a1ee7..d9dba733 100644 --- a/test/proxy/modules/AuthorizationModule/AuthorizationModule.test.js +++ b/test/proxy/modules/AuthorizationModule/AuthorizationModule.test.js @@ -1,19 +1,13 @@ -const CMTAT = artifacts.require('CMTAT_PROXY') -const { deployProxy } = require('@openzeppelin/truffle-upgrades') const AuthorizationModuleCommon = require('../../../common/AuthorizationModule/AuthorizationModuleCommon') -const { ZERO_ADDRESS } = require('../../../utils') +const {deployCMTATProxy} = require('../../../deploymentUtils') contract( 'Proxy - AuthorizationModule', - function ([_, owner, address1, address2]) { + function ([_, admin, address1, address2, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await deployProxy(CMTAT, [owner, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { - initializer: 'initialize', - constructorArgs: [_] - }) + this.cmtat = await deployCMTATProxy(_, admin, deployerAddress) }) - AuthorizationModuleCommon(owner, address1, address2) + AuthorizationModuleCommon(admin, address1, address2) } ) diff --git a/test/proxy/modules/BaseModule.test.js b/test/proxy/modules/BaseModule.test.js index 158915d6..c29a6730 100644 --- a/test/proxy/modules/BaseModule.test.js +++ b/test/proxy/modules/BaseModule.test.js @@ -2,16 +2,14 @@ const { deployProxy } = require('@openzeppelin/truffle-upgrades') const CMTAT = artifacts.require('CMTAT_PROXY') const BaseModuleCommon = require('../../common/BaseModuleCommon') const { ZERO_ADDRESS } = require('../../utils') +const {deployCMTATProxy, DEPLOYMENT_FLAG} = require('../../deploymentUtils') contract( 'Proxy - BaseModule', - function ([_, admin, address1, address2, address3]) { + function ([_, admin, address1, address2, address3, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await deployProxy(CMTAT, [admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { - initializer: 'initialize', - constructorArgs: [_] - }) + this.flag = DEPLOYMENT_FLAG // value used in tests + this.cmtat = await deployCMTATProxy(_, admin, deployerAddress) }) BaseModuleCommon(admin, address1, address2, address3, true) diff --git a/test/proxy/modules/BurnModule.test.js b/test/proxy/modules/BurnModule.test.js index 5978a9d5..734ae5d7 100644 --- a/test/proxy/modules/BurnModule.test.js +++ b/test/proxy/modules/BurnModule.test.js @@ -1,17 +1,11 @@ -const { deployProxy } = require('@openzeppelin/truffle-upgrades') -const CMTAT = artifacts.require('CMTAT_PROXY') const BurnModuleCommon = require('../../common/BurnModuleCommon') -const { ZERO_ADDRESS } = require('../../utils') +const {deployCMTATProxy} = require('../../deploymentUtils') contract( 'Proxy - BurnModule', - function ([_, admin, address1, address2]) { + function ([_, admin, address1, address2, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await deployProxy(CMTAT, [admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { - initializer: 'initialize', - constructorArgs: [_] - }) + this.cmtat = await deployCMTATProxy(_, admin, deployerAddress) }) BurnModuleCommon(admin, address1, address2) diff --git a/test/proxy/modules/CreditEventsModule.test.js b/test/proxy/modules/CreditEventsModule.test.js index 157bcaec..c3305ed3 100644 --- a/test/proxy/modules/CreditEventsModule.test.js +++ b/test/proxy/modules/CreditEventsModule.test.js @@ -1,17 +1,11 @@ -const { deployProxy } = require('@openzeppelin/truffle-upgrades') -const CMTAT = artifacts.require('CMTAT_PROXY') const CreditEventsModuleCommon = require('../../common/CreditEventsModuleCommon') -const { ZERO_ADDRESS } = require('../../utils') +const {deployCMTATProxy} = require('../../deploymentUtils') contract( 'Proxy - CreditEventsModule', - function ([_, admin, attacker]) { + function ([_, admin, attacker, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await deployProxy(CMTAT, [admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { - initializer: 'initialize', - constructorArgs: [_] - }) + this.cmtat = await deployCMTATProxy(_, admin, deployerAddress) }) CreditEventsModuleCommon(admin, attacker) diff --git a/test/proxy/modules/DebtModule.test.js b/test/proxy/modules/DebtModule.test.js index 913ecb79..bf47fcf4 100644 --- a/test/proxy/modules/DebtModule.test.js +++ b/test/proxy/modules/DebtModule.test.js @@ -1,17 +1,11 @@ -const { deployProxy } = require('@openzeppelin/truffle-upgrades') -const CMTAT = artifacts.require('CMTAT_PROXY') const DebtModuleCommon = require('../../common/DebtModuleCommon') -const { ZERO_ADDRESS } = require('../../utils') +const {deployCMTATProxy} = require('../../deploymentUtils') contract( 'Proxy - DebtModule', - function ([_, admin, address1, address2, address3]) { + function ([_, admin, address1, address2, address3, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await deployProxy(CMTAT, [admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { - initializer: 'initialize', - constructorArgs: [_] - }) + this.cmtat = await deployCMTATProxy(_, admin, deployerAddress) }) DebtModuleCommon(admin, address1, address2, address3, true) diff --git a/test/proxy/modules/ERC20BaseModule.test.js b/test/proxy/modules/ERC20BaseModule.test.js index 0fd6a5fd..80c98d59 100644 --- a/test/proxy/modules/ERC20BaseModule.test.js +++ b/test/proxy/modules/ERC20BaseModule.test.js @@ -1,17 +1,11 @@ -const { deployProxy } = require('@openzeppelin/truffle-upgrades') -const CMTAT = artifacts.require('CMTAT_PROXY') -const ERC20BaseModuleCommon = require('../../common/BaseModuleCommon') -const { ZERO_ADDRESS } = require('../../utils') +const ERC20BaseModuleCommon = require('../../common/ERC20BaseModuleCommon') +const {deployCMTATProxy} = require('../../deploymentUtils') contract( 'Proxy - ERC20BaseModule', - function ([_, admin, address1, address2, address3]) { + function ([_, admin, address1, address2, address3, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await deployProxy(CMTAT, [admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { - initializer: 'initialize', - constructorArgs: [_] - }) + this.cmtat = await deployCMTATProxy(_, admin, deployerAddress) }) ERC20BaseModuleCommon(admin, address1, address2, address3, true) diff --git a/test/proxy/modules/EnforcementModule.test.js b/test/proxy/modules/EnforcementModule.test.js index 9ec044fb..cc130a78 100644 --- a/test/proxy/modules/EnforcementModule.test.js +++ b/test/proxy/modules/EnforcementModule.test.js @@ -1,17 +1,11 @@ -const { deployProxy } = require('@openzeppelin/truffle-upgrades') -const CMTAT = artifacts.require('CMTAT_PROXY') const EnforcementModuleCommon = require('../../common/EnforcementModuleCommon') -const { ZERO_ADDRESS } = require('../../utils') +const {deployCMTATProxy} = require('../../deploymentUtils') contract( 'Proxy - EnforcementModule', - function ([_, admin, address1, address2, address3]) { + function ([_, admin, address1, address2, address3, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await deployProxy(CMTAT, [admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { - initializer: 'initialize', - constructorArgs: [_] - }) + this.cmtat = await deployCMTATProxy(_, admin, deployerAddress) }) EnforcementModuleCommon(admin, address1, address2, address3) diff --git a/test/proxy/modules/MetaTxModule.test.js b/test/proxy/modules/MetaTxModule.test.js index 1cbfae8a..a25d0b40 100644 --- a/test/proxy/modules/MetaTxModule.test.js +++ b/test/proxy/modules/MetaTxModule.test.js @@ -13,9 +13,10 @@ contract( ]) { beforeEach(async function () { this.flag = 5 + const DECIMAL = 0 this.trustedForwarder = await MinimalForwarderMock.new() await this.trustedForwarder.initialize() - this.cmtat = await deployProxy(CMTAT, [owner, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { + this.cmtat = await deployProxy(CMTAT, [owner, 'CMTA Token', 'CMTAT', DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { initializer: 'initialize', constructorArgs: [this.trustedForwarder.address] }) diff --git a/test/proxy/modules/MintModule.test.js b/test/proxy/modules/MintModule.test.js index 4c83cc52..26e0d07c 100644 --- a/test/proxy/modules/MintModule.test.js +++ b/test/proxy/modules/MintModule.test.js @@ -1,17 +1,13 @@ -const { deployProxy } = require('@openzeppelin/truffle-upgrades') const CMTAT = artifacts.require('CMTAT_PROXY') const MintModuleCommon = require('../../common/MintModuleCommon') const { ZERO_ADDRESS } = require('../../utils') +const {deployCMTATProxy} = require('../../deploymentUtils') contract( 'Proxy - MintModule', - function ([_, admin, address1, address2]) { + function ([_, admin, address1, address2, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await deployProxy(CMTAT, [admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { - initializer: 'initialize', - constructorArgs: [_] - }) + this.cmtat = await deployCMTATProxy(_, admin, deployerAddress) }) MintModuleCommon(admin, address1, address2) diff --git a/test/proxy/modules/PauseModule.test.js b/test/proxy/modules/PauseModule.test.js index 62d084ac..335b4354 100644 --- a/test/proxy/modules/PauseModule.test.js +++ b/test/proxy/modules/PauseModule.test.js @@ -1,15 +1,9 @@ -const { deployProxy } = require('@openzeppelin/truffle-upgrades') -const CMTAT = artifacts.require('CMTAT_PROXY') const PauseModuleCommon = require('../../common/PauseModuleCommon') -const { ZERO_ADDRESS } = require('../../utils') +const {deployCMTATProxy} = require('../../deploymentUtils') -contract('Proxy - PauseModule', function ([_, admin, address1, address2, address3]) { +contract('Proxy - PauseModule', function ([_, admin, address1, address2, address3, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await deployProxy(CMTAT, [admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { - initializer: 'initialize', - constructorArgs: [_] - }) + this.cmtat = await deployCMTATProxy(_, admin, deployerAddress) // Mint tokens to test the transfer await this.cmtat.mint(address1, 20, { from: admin diff --git a/test/proxy/modules/SnapshotModule.test.js b/test/proxy/modules/SnapshotModule.test.js index 8bbc4c13..d8dc565d 100644 --- a/test/proxy/modules/SnapshotModule.test.js +++ b/test/proxy/modules/SnapshotModule.test.js @@ -9,13 +9,14 @@ const SnapshotModuleMultiplePlannedTest = require('../../common/SnapshotModuleCo const SnapshotModuleOnePlannedSnapshotTest = require('../../common/SnapshotModuleCommon/global/SnapshotModuleOnePlannedSnapshotTest') const SnapshotModuleZeroPlannedSnapshotTest = require('../../common/SnapshotModuleCommon/global/SnapshotModuleZeroPlannedSnapshot') const { ZERO_ADDRESS } = require('../../utils') +const DECIMAL = 0 contract( 'Proxy - SnapshotModule', function ([_, admin, address1, address2, address3]) { beforeEach(async function () { this.flag = 5 - this.cmtat = await deployProxy(CMTAT, [admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { + this.cmtat = await deployProxy(CMTAT, [admin, 'CMTA Token', 'CMTAT', DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { initializer: 'initialize', constructorArgs: [_] }) @@ -31,4 +32,4 @@ contract( SnapshotModuleCommonUnschedule(admin, address1, address2, address3) SnapshotModuleCommonGetNextSnapshot(admin, address1, address2, address3) } -) +) \ No newline at end of file diff --git a/test/proxy/modules/ValidationModule/ValidationModule.test.js b/test/proxy/modules/ValidationModule/ValidationModule.test.js index a2318c38..4296a667 100644 --- a/test/proxy/modules/ValidationModule/ValidationModule.test.js +++ b/test/proxy/modules/ValidationModule/ValidationModule.test.js @@ -11,8 +11,9 @@ contract( function ([_, admin, address1, address2, address3]) { beforeEach(async function () { this.flag = 5 + const DECIMAL = 0 this.ruleEngineMock = await RuleEngineMock.new({ from: admin }) - this.cmtat = await deployProxy(CMTAT, [admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { + this.cmtat = await deployProxy(CMTAT, [admin, 'CMTA Token', 'CMTAT', DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { initializer: 'initialize', constructorArgs: [_] }) diff --git a/test/proxy/modules/ValidationModule/ValidationModuleConstructor.test.js b/test/proxy/modules/ValidationModule/ValidationModuleConstructor.test.js index de91132d..7c83ac2f 100644 --- a/test/proxy/modules/ValidationModule/ValidationModuleConstructor.test.js +++ b/test/proxy/modules/ValidationModule/ValidationModuleConstructor.test.js @@ -10,8 +10,9 @@ contract( function ([_, admin, address1, address2, address3]) { beforeEach(async function () { this.flag = 5 + const DECIMAL = 0 this.ruleEngineMock = await RuleEngineMock.new({ from: admin }) - this.cmtat = await deployProxy(CMTAT, [admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', this.ruleEngineMock.address, 'CMTAT_info', this.flag], { + this.cmtat = await deployProxy(CMTAT, [admin, 'CMTA Token', 'CMTAT', DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', this.ruleEngineMock.address, 'CMTAT_info', this.flag], { initializer: 'initialize', constructorArgs: [_] }) diff --git a/test/proxy/modules/ValidationModule/ValidationModuleSetRuleEngine.test.js b/test/proxy/modules/ValidationModule/ValidationModuleSetRuleEngine.test.js index b209eb48..3a5381cf 100644 --- a/test/proxy/modules/ValidationModule/ValidationModuleSetRuleEngine.test.js +++ b/test/proxy/modules/ValidationModule/ValidationModuleSetRuleEngine.test.js @@ -7,7 +7,8 @@ contract( function ([_, admin, address1, fakeRuleEngine]) { beforeEach(async function () { this.flag = 5 - this.cmtat = await deployProxy(CMTAT, [admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { + const DECIMAL = 0 + this.cmtat = await deployProxy(CMTAT, [admin, 'CMTA Token', 'CMTAT', DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag], { initializer: 'initialize', constructorArgs: [_] }) diff --git a/test/standard/modules/AuthorizationModule/AuthorizationModule.test.js b/test/standard/modules/AuthorizationModule/AuthorizationModule.test.js index a5772770..984fd357 100644 --- a/test/standard/modules/AuthorizationModule/AuthorizationModule.test.js +++ b/test/standard/modules/AuthorizationModule/AuthorizationModule.test.js @@ -1,13 +1,11 @@ -const CMTAT = artifacts.require('CMTAT_STANDALONE') const AuthorizationModuleCommon = require('../../../common/AuthorizationModule/AuthorizationModuleCommon') -const { ZERO_ADDRESS } = require('../../../utils') +const {deployCMTATStandalone} = require('../../../deploymentUtils') contract( 'Standard - AuthorizationModule', - function ([_, admin, address1, address2, randomDeployer]) { + function ([_, admin, address1, address2, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await CMTAT.new(_, admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: randomDeployer }) + this.cmtat = await deployCMTATStandalone(_, admin, deployerAddress) }) AuthorizationModuleCommon(admin, address1, address2) diff --git a/test/standard/modules/BaseModule.test.js b/test/standard/modules/BaseModule.test.js index b89c0aba..3a75b60f 100644 --- a/test/standard/modules/BaseModule.test.js +++ b/test/standard/modules/BaseModule.test.js @@ -1,13 +1,11 @@ -const CMTAT = artifacts.require('CMTAT_STANDALONE') const BaseModuleCommon = require('../../common/BaseModuleCommon') -const { ZERO_ADDRESS } = require('../../utils') - +const {deployCMTATStandalone, DEPLOYMENT_FLAG} = require('../../deploymentUtils') contract( 'Standard - BaseModule', - function ([_, admin, address1, address2, address3, randomDeployer]) { + function ([_, admin, address1, address2, address3, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await CMTAT.new(_, admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: randomDeployer }) + this.flag = DEPLOYMENT_FLAG // value used in tests + this.cmtat = await deployCMTATStandalone(_, admin, deployerAddress) }) BaseModuleCommon(admin, address1, address2, address3, false) diff --git a/test/standard/modules/BurnModule.test.js b/test/standard/modules/BurnModule.test.js index 04fbfc4b..542293b6 100644 --- a/test/standard/modules/BurnModule.test.js +++ b/test/standard/modules/BurnModule.test.js @@ -1,13 +1,10 @@ -const CMTAT = artifacts.require('CMTAT_STANDALONE') const BurnModuleCommon = require('../../common/BurnModuleCommon') -const { ZERO_ADDRESS } = require('../../utils') - +const {deployCMTATStandalone} = require('../../deploymentUtils') contract( 'Standard - BurnModule', - function ([_, admin, address1, address2, randomDeployer]) { + function ([_, admin, address1, address2, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await CMTAT.new(_, admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: randomDeployer }) + this.cmtat = await deployCMTATStandalone(_, admin, deployerAddress) }) BurnModuleCommon(admin, address1, address2) diff --git a/test/standard/modules/CreditEventsModule.test.js b/test/standard/modules/CreditEventsModule.test.js index d601fbfb..8ec1eead 100644 --- a/test/standard/modules/CreditEventsModule.test.js +++ b/test/standard/modules/CreditEventsModule.test.js @@ -1,13 +1,10 @@ -const CMTAT = artifacts.require('CMTAT_STANDALONE') const CreditEventsModuleCommon = require('../../common/CreditEventsModuleCommon') -const { ZERO_ADDRESS } = require('../../utils') - +const {deployCMTATStandalone} = require('../../deploymentUtils') contract( 'Standard - CreditEventsModule', - function ([_, admin, attacker, randomDeployer]) { + function ([_, admin, attacker, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await CMTAT.new(_, admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: randomDeployer }) + this.cmtat = await deployCMTATStandalone(_, admin, deployerAddress) }) CreditEventsModuleCommon(admin, attacker) diff --git a/test/standard/modules/DebtModule.test.js b/test/standard/modules/DebtModule.test.js index 101d0052..63af4716 100644 --- a/test/standard/modules/DebtModule.test.js +++ b/test/standard/modules/DebtModule.test.js @@ -1,13 +1,10 @@ -const CMTAT = artifacts.require('CMTAT_STANDALONE') const DebtModuleCommon = require('../../common/DebtModuleCommon') -const { ZERO_ADDRESS } = require('../../utils') - +const {deployCMTATStandalone} = require('../../deploymentUtils') contract( 'Standard - DebtModule', - function ([_, admin, address1, address2, address3, randomDeployer]) { + function ([_, admin, address1, address2, address3, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await CMTAT.new(_, admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: randomDeployer }) + this.cmtat = await deployCMTATStandalone(_, admin, deployerAddress) }) DebtModuleCommon(admin, address1, address2, address3, false) diff --git a/test/standard/modules/ERC20BaseModule.test.js b/test/standard/modules/ERC20BaseModule.test.js index ab0b0038..22485e7a 100644 --- a/test/standard/modules/ERC20BaseModule.test.js +++ b/test/standard/modules/ERC20BaseModule.test.js @@ -1,13 +1,10 @@ -const CMTAT = artifacts.require('CMTAT_STANDALONE') const ERC20BaseModuleCommon = require('../../common/ERC20BaseModuleCommon') -const { ZERO_ADDRESS } = require('../../utils') - +const {deployCMTATStandalone} = require('../../deploymentUtils') contract( 'Standard - ERC20BaseModule', - function ([_, admin, address1, address2, address3, randomDeployer]) { + function ([_, admin, address1, address2, address3, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await CMTAT.new(_, admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: randomDeployer }) + this.cmtat = await deployCMTATStandalone(_, admin, deployerAddress) }) ERC20BaseModuleCommon(admin, address1, address2, address3, false) diff --git a/test/standard/modules/EnforcementModule.test.js b/test/standard/modules/EnforcementModule.test.js index 305fb267..105b3faf 100644 --- a/test/standard/modules/EnforcementModule.test.js +++ b/test/standard/modules/EnforcementModule.test.js @@ -1,14 +1,10 @@ - -const CMTAT = artifacts.require('CMTAT_STANDALONE') const EnforcementModuleCommon = require('../../common/EnforcementModuleCommon') -const { ZERO_ADDRESS } = require('../../utils') - +const {deployCMTATStandalone} = require('../../deploymentUtils') contract( 'Standard - EnforcementModule', - function ([_, admin, address1, address2, address3, randomDeployer]) { + function ([_, admin, address1, address2, address3, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await CMTAT.new(_, admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: randomDeployer }) + this.cmtat = await deployCMTATStandalone(_, admin, deployerAddress) }) EnforcementModuleCommon(admin, address1, address2, address3) diff --git a/test/standard/modules/MetaTxModule.test.js b/test/standard/modules/MetaTxModule.test.js index d8c9ebc5..23e552a9 100644 --- a/test/standard/modules/MetaTxModule.test.js +++ b/test/standard/modules/MetaTxModule.test.js @@ -13,9 +13,10 @@ contract( ]) { beforeEach(async function () { this.flag = 5 + const DECIMAL = 0 this.trustedForwarder = await MinimalForwarderMock.new() this.trustedForwarder.initialize() - this.cmtat = await CMTAT.new(this.trustedForwarder.address, admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: randomDeployer }) + this.cmtat = await CMTAT.new(this.trustedForwarder.address, admin, 'CMTA Token', 'CMTAT', DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: randomDeployer }) }) MetaTxModuleCommon(admin, address1) diff --git a/test/standard/modules/MintModule.test.js b/test/standard/modules/MintModule.test.js index 10b45e23..8bd085ae 100644 --- a/test/standard/modules/MintModule.test.js +++ b/test/standard/modules/MintModule.test.js @@ -1,13 +1,10 @@ -const CMTAT = artifacts.require('CMTAT_STANDALONE') const MintModuleCommon = require('../../common/MintModuleCommon') -const { ZERO_ADDRESS } = require('../../utils') - +const { deployCMTATStandalone } = require('../../deploymentUtils') contract( 'Standard - MintModule', - function ([_, admin, address1, address2, randomDeployer]) { + function ([_, admin, address1, address2, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await CMTAT.new(_, admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: randomDeployer }) + this.cmtat = await deployCMTATStandalone(_, admin, deployerAddress) }) MintModuleCommon(admin, address1, address2) diff --git a/test/standard/modules/PauseModule.test.js b/test/standard/modules/PauseModule.test.js index 9c1ae4d3..2d09f071 100644 --- a/test/standard/modules/PauseModule.test.js +++ b/test/standard/modules/PauseModule.test.js @@ -1,12 +1,10 @@ -const CMTAT = artifacts.require('CMTAT_STANDALONE') const PauseModuleCommon = require('../../common/PauseModuleCommon') -const { ZERO_ADDRESS } = require('../../utils') +const {deployCMTATStandalone} = require('../../deploymentUtils') contract( 'Standard - PauseModule', - function ([_, admin, address1, address2, address3, randomDeployer]) { + function ([_, admin, address1, address2, address3, deployerAddress]) { beforeEach(async function () { - this.flag = 5 - this.cmtat = await CMTAT.new(_, admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: randomDeployer }) + this.cmtat = await deployCMTATStandalone(_, admin, deployerAddress) // Mint tokens to test the transfer await this.cmtat.mint(address1, 20, { from: admin diff --git a/test/standard/modules/SnapshotModule.test.js b/test/standard/modules/SnapshotModule.test.js index b355c587..89f25c2f 100644 --- a/test/standard/modules/SnapshotModule.test.js +++ b/test/standard/modules/SnapshotModule.test.js @@ -8,12 +8,13 @@ const SnapshotModuleMultiplePlannedTest = require('../../common/SnapshotModuleCo const SnapshotModuleOnePlannedSnapshotTest = require('../../common/SnapshotModuleCommon/global/SnapshotModuleOnePlannedSnapshotTest') const SnapshotModuleZeroPlannedSnapshotTest = require('../../common/SnapshotModuleCommon/global/SnapshotModuleZeroPlannedSnapshot') const { ZERO_ADDRESS } = require('../../utils') +const DECIMAL = 0 contract( 'Standard - SnapshotModule', function ([_, admin, address1, address2, address3, randomDeployer]) { beforeEach(async function () { this.flag = 5 - this.cmtat = await CMTAT.new(_, admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: randomDeployer }) + this.cmtat = await CMTAT.new(_, admin, 'CMTA Token', 'CMTAT', DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: randomDeployer }) }) SnapshotModuleMultiplePlannedTest(admin, address1, address2, address3) SnapshotModuleOnePlannedSnapshotTest(admin, address1, address2, address3) @@ -25,4 +26,4 @@ contract( SnapshotModuleCommonUnschedule(admin, address1, address2, address3) SnapshotModuleCommonGetNextSnapshot(admin, address1, address2, address3) } -) +) \ No newline at end of file diff --git a/test/standard/modules/ValidationModule/ValidationModule.test.js b/test/standard/modules/ValidationModule/ValidationModule.test.js index d27da87e..07eacf0f 100644 --- a/test/standard/modules/ValidationModule/ValidationModule.test.js +++ b/test/standard/modules/ValidationModule/ValidationModule.test.js @@ -6,10 +6,11 @@ const ADDRESS2_INITIAL_BALANCE = 32 const ADDRESS3_INITIAL_BALANCE = 33 contract( 'Standard - ValidationModule', - function ([_, admin, address1, address2, address3, randomDeployer]) { + function ([_, admin, address1, address2, address3, deployerAddress]) { beforeEach(async function () { this.flag = 5 - this.cmtat = await CMTAT.new(_, admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: randomDeployer }) + const DECIMAL = 0 + this.cmtat = await CMTAT.new(_, admin, 'CMTA Token', 'CMTAT', DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: deployerAddress }) await this.cmtat.mint(address1, ADDRESS1_INITIAL_BALANCE, { from: admin }) await this.cmtat.mint(address2, ADDRESS2_INITIAL_BALANCE, { from: admin }) await this.cmtat.mint(address3, ADDRESS3_INITIAL_BALANCE, { from: admin }) diff --git a/test/standard/modules/ValidationModule/ValidationModuleConstructor.test.js b/test/standard/modules/ValidationModule/ValidationModuleConstructor.test.js index c01c4a3f..143df888 100644 --- a/test/standard/modules/ValidationModule/ValidationModuleConstructor.test.js +++ b/test/standard/modules/ValidationModule/ValidationModuleConstructor.test.js @@ -6,11 +6,12 @@ const ADDRESS2_INITIAL_BALANCE = 18 const ADDRESS3_INITIAL_BALANCE = 19 contract( 'Standard - ValidationModule - Constructor', - function ([_, admin, address1, address2, address3, randomDeployer]) { + function ([_, admin, address1, address2, address3, deployerAddress]) { beforeEach(async function () { this.flag = 5 + const DECIMAL = 0 this.ruleEngineMock = await RuleEngineMock.new({ from: admin }) - this.cmtat = await CMTAT.new(_, admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', this.ruleEngineMock.address, 'CMTAT_info', this.flag, { from: randomDeployer }) + this.cmtat = await CMTAT.new(_, admin, 'CMTA Token', 'CMTAT', DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', this.ruleEngineMock.address, 'CMTAT_info', this.flag, { from: deployerAddress }) await this.cmtat.mint(address1, ADDRESS1_INITIAL_BALANCE, { from: admin }) await this.cmtat.mint(address2, ADDRESS2_INITIAL_BALANCE, { from: admin }) await this.cmtat.mint(address3, ADDRESS3_INITIAL_BALANCE, { from: admin }) diff --git a/test/standard/modules/ValidationModule/ValidationModuleSetRuleEngine.test.js b/test/standard/modules/ValidationModule/ValidationModuleSetRuleEngine.test.js index 44f1bb29..b5f2afbf 100644 --- a/test/standard/modules/ValidationModule/ValidationModuleSetRuleEngine.test.js +++ b/test/standard/modules/ValidationModule/ValidationModuleSetRuleEngine.test.js @@ -3,10 +3,11 @@ const ValidationModuleSetRuleEngineCommon = require('../../../common/ValidationM const { ZERO_ADDRESS } = require('../../../utils') contract( 'Standard - ValidationModule - setRuleEngine', - function ([_, admin, address1, fakeRuleEngine, randomDeployer]) { + function ([_, admin, address1, fakeRuleEngine, deployerAddress]) { beforeEach(async function () { this.flag = 5 - this.cmtat = await CMTAT.new(_, admin, 'CMTA Token', 'CMTAT', 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: randomDeployer }) + const DECIMAL = 5 + this.cmtat = await CMTAT.new(_, admin, 'CMTA Token', 'CMTAT', DECIMAL, 'CMTAT_ISIN', 'https://cmta.ch', ZERO_ADDRESS, 'CMTAT_info', this.flag, { from: deployerAddress }) }) ValidationModuleSetRuleEngineCommon(admin, address1, fakeRuleEngine) }